diff options
author | David Vrabel <david.vrabel@csr.com> | 2008-10-20 16:07:19 +0100 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-10-20 16:07:19 +0100 |
commit | 61e0e79ee3c609eb34edf2fe023708cba6a79b1f (patch) | |
tree | 663deacffd4071120dc9badb70428fe5f124c7b9 /drivers/usb | |
parent | c15895ef30c2c03e99802951787183039a349d32 (diff) | |
parent | 0cfd81031a26717fe14380d18275f8e217571615 (diff) | |
download | talos-op-linux-61e0e79ee3c609eb34edf2fe023708cba6a79b1f.tar.gz talos-op-linux-61e0e79ee3c609eb34edf2fe023708cba6a79b1f.zip |
Merge branch 'master' into for-upstream
Conflicts:
Documentation/ABI/testing/sysfs-bus-usb
drivers/Makefile
Diffstat (limited to 'drivers/usb')
142 files changed, 8808 insertions, 2121 deletions
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 07228721cafe..06dd114910d4 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -344,7 +344,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char __func__, sarb->len, vcc); /* discard cells already received */ skb_trim(sarb, 0); - UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); + UDSL_ASSERT(instance, sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); } memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); @@ -432,7 +432,7 @@ static void usbatm_extract_cells(struct usbatm_data *instance, unsigned char *cell_buf = instance->cell_buf; unsigned int space_left = stride - buf_usage; - UDSL_ASSERT(buf_usage <= stride); + UDSL_ASSERT(instance, buf_usage <= stride); if (avail_data >= space_left) { /* add new data and process cell */ @@ -475,7 +475,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, unsigned int stride = instance->tx_channel.stride; vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); - UDSL_ASSERT(!(avail_space % stride)); + UDSL_ASSERT(instance, !(avail_space % stride)); for (bytes_written = 0; bytes_written < avail_space && ctrl->len; bytes_written += stride, target += stride) { @@ -547,7 +547,7 @@ static void usbatm_rx_process(unsigned long data) if (!urb->iso_frame_desc[i].status) { unsigned int actual_length = urb->iso_frame_desc[i].actual_length; - UDSL_ASSERT(actual_length <= packet_size); + UDSL_ASSERT(instance, actual_length <= packet_size); if (!merge_length) merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; @@ -640,14 +640,13 @@ static void usbatm_cancel_send(struct usbatm_data *instance, atm_dbg(instance, "%s entered\n", __func__); spin_lock_irq(&instance->sndqueue.lock); - for (skb = instance->sndqueue.next, n = skb->next; - skb != (struct sk_buff *)&instance->sndqueue; - skb = n, n = skb->next) + skb_queue_walk_safe(&instance->sndqueue, skb, n) { if (UDSL_SKB(skb)->atm.vcc == vcc) { atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb); __skb_unlink(skb, &instance->sndqueue); usbatm_pop(vcc, skb); } + } spin_unlock_irq(&instance->sndqueue.lock); tasklet_disable(&instance->tx_channel.tasklet); @@ -1189,7 +1188,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, struct urb *urb; unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0; - UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint)); + UDSL_ASSERT(instance, !usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint)); urb = usb_alloc_urb(iso_packets, GFP_KERNEL); if (!urb) { diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index e6887c6cf3cf..f6f4508a9d42 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -40,9 +40,15 @@ */ #ifdef DEBUG -#define UDSL_ASSERT(x) BUG_ON(!(x)) +#define UDSL_ASSERT(instance, x) BUG_ON(!(x)) #else -#define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '%s' at line %d", __stringify(x), __LINE__); } while(0) +#define UDSL_ASSERT(instance, x) \ + do { \ + if (!(x)) \ + dev_warn(&(instance)->usb_intf->dev, \ + "failed assertion '%s' at line %d", \ + __stringify(x), __LINE__); \ + } while(0) #endif #define usb_err(instance, format, arg...) \ diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 8472543eee81..17d167bbd2dc 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c @@ -193,7 +193,7 @@ static int __init xusbatm_init(void) num_vendor != num_product || num_vendor != num_rx_endpoint || num_vendor != num_tx_endpoint) { - warn("malformed module parameters"); + printk(KERN_WARNING "xusbatm: malformed module parameters\n"); return -EINVAL; } diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index 66f17ed88cb5..2519e320098f 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -40,3 +40,13 @@ config USB_WDM To compile this driver as a module, choose M here: the module will be called cdc-wdm. +config USB_TMC + tristate "USB Test and Measurement Class support" + depends on USB + help + Say Y here if you want to connect a USB device that follows + the USB.org specification for USB Test and Measurement devices + to your computer's USB port. + + To compile this driver as a module, choose M here: the + module will be called usbtmc. diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile index 535d59a30600..32e85277b5cf 100644 --- a/drivers/usb/class/Makefile +++ b/drivers/usb/class/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_USB_ACM) += cdc-acm.o obj-$(CONFIG_USB_PRINTER) += usblp.o obj-$(CONFIG_USB_WDM) += cdc-wdm.o +obj-$(CONFIG_USB_TMC) += usbtmc.o diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c257453fa9de..fab23ee8702b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -326,8 +326,8 @@ exit: usb_mark_last_busy(acm->dev); retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) - err ("%s - usb_submit_urb failed with result %d", - __func__, retval); + dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " + "result %d", __func__, retval); } /* data interface returns incoming bytes, or we got unthrottled */ @@ -514,7 +514,7 @@ static void acm_waker(struct work_struct *waker) rv = usb_autopm_get_interface(acm->control); if (rv < 0) { - err("Autopm failure in %s", __func__); + dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__); return; } if (acm->delayed_wb) { @@ -924,7 +924,7 @@ static int acm_probe (struct usb_interface *intf, /* normal probing*/ if (!buffer) { - err("Weird descriptor references\n"); + dev_err(&intf->dev, "Weird descriptor references\n"); return -EINVAL; } @@ -934,21 +934,24 @@ static int acm_probe (struct usb_interface *intf, buflen = intf->cur_altsetting->endpoint->extralen; buffer = intf->cur_altsetting->endpoint->extra; } else { - err("Zero length descriptor references\n"); + dev_err(&intf->dev, + "Zero length descriptor references\n"); return -EINVAL; } } while (buflen > 0) { if (buffer [1] != USB_DT_CS_INTERFACE) { - err("skipping garbage\n"); + dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; } switch (buffer [2]) { case USB_CDC_UNION_TYPE: /* we've found it */ if (union_header) { - err("More than one union descriptor, skipping ..."); + dev_err(&intf->dev, "More than one " + "union descriptor, " + "skipping ...\n"); goto next_desc; } union_header = (struct usb_cdc_union_desc *) @@ -966,7 +969,9 @@ static int acm_probe (struct usb_interface *intf, call_management_function = buffer[3]; call_interface_num = buffer[4]; if ((call_management_function & 3) != 3) - err("This device cannot do calls on its own. It is no modem."); + dev_err(&intf->dev, "This device " + "cannot do calls on its own. " + "It is no modem.\n"); break; default: /* there are LOTS more CDC descriptors that @@ -1051,7 +1056,7 @@ skip_normal_probe: for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); if (minor == ACM_TTY_MINORS) { - err("no more free acm devices"); + dev_err(&intf->dev, "no more free acm devices\n"); return -ENODEV; } @@ -1454,7 +1459,8 @@ static int __init acm_init(void) return retval; } - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; } diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 7e8e1235e4e5..7429f70b9d06 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -132,10 +132,12 @@ static void wdm_in_callback(struct urb *urb) "nonzero urb status received: -ESHUTDOWN"); break; case -EPIPE: - err("nonzero urb status received: -EPIPE"); + dev_err(&desc->intf->dev, + "nonzero urb status received: -EPIPE\n"); break; default: - err("Unexpected error %d", status); + dev_err(&desc->intf->dev, + "Unexpected error %d\n", status); break; } } @@ -170,16 +172,18 @@ static void wdm_int_callback(struct urb *urb) return; /* unplug */ case -EPIPE: set_bit(WDM_INT_STALL, &desc->flags); - err("Stall on int endpoint"); + dev_err(&desc->intf->dev, "Stall on int endpoint\n"); goto sw; /* halt is cleared in work */ default: - err("nonzero urb status received: %d", status); + dev_err(&desc->intf->dev, + "nonzero urb status received: %d\n", status); break; } } if (urb->actual_length < sizeof(struct usb_cdc_notification)) { - err("wdm_int_callback - %d bytes", urb->actual_length); + dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n", + urb->actual_length); goto exit; } @@ -198,7 +202,8 @@ static void wdm_int_callback(struct urb *urb) goto exit; default: clear_bit(WDM_POLL_RUNNING, &desc->flags); - err("unknown notification %d received: index %d len %d", + dev_err(&desc->intf->dev, + "unknown notification %d received: index %d len %d\n", dr->bNotificationType, dr->wIndex, dr->wLength); goto exit; } @@ -236,14 +241,16 @@ static void wdm_int_callback(struct urb *urb) sw: rv = schedule_work(&desc->rxwork); if (rv) - err("Cannot schedule work"); + dev_err(&desc->intf->dev, + "Cannot schedule work\n"); } } exit: rv = usb_submit_urb(urb, GFP_ATOMIC); if (rv) - err("%s - usb_submit_urb failed with result %d", - __func__, rv); + dev_err(&desc->intf->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, rv); } @@ -353,7 +360,7 @@ static ssize_t wdm_write if (rv < 0) { kfree(buf); clear_bit(WDM_IN_USE, &desc->flags); - err("Tx URB error: %d", rv); + dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); } else { dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", req->wIndex); @@ -401,7 +408,8 @@ retry: int t = desc->rerr; desc->rerr = 0; spin_unlock_irq(&desc->iuspin); - err("reading had resulted in %d", t); + dev_err(&desc->intf->dev, + "reading had resulted in %d\n", t); rv = -EIO; goto err; } @@ -440,7 +448,7 @@ retry: err: mutex_unlock(&desc->rlock); if (rv < 0) - err("wdm_read: exit error"); + dev_err(&desc->intf->dev, "wdm_read: exit error\n"); return rv; } @@ -450,7 +458,8 @@ static int wdm_flush(struct file *file, fl_owner_t id) wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); if (desc->werr < 0) - err("Error in flush path: %d", desc->werr); + dev_err(&desc->intf->dev, "Error in flush path: %d\n", + desc->werr); return desc->werr; } @@ -502,7 +511,7 @@ static int wdm_open(struct inode *inode, struct file *file) rv = usb_autopm_get_interface(desc->intf); if (rv < 0) { - err("Error autopm - %d", rv); + dev_err(&desc->intf->dev, "Error autopm - %d\n", rv); goto out; } intf->needs_remote_wakeup = 1; @@ -512,7 +521,8 @@ static int wdm_open(struct inode *inode, struct file *file) rv = usb_submit_urb(desc->validity, GFP_KERNEL); if (rv < 0) { desc->count--; - err("Error submitting int urb - %d", rv); + dev_err(&desc->intf->dev, + "Error submitting int urb - %d\n", rv); } } else { rv = 0; @@ -600,7 +610,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) while (buflen > 0) { if (buffer [1] != USB_DT_CS_INTERFACE) { - err("skipping garbage"); + dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; } @@ -614,7 +624,8 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) "Finding maximum buffer length: %d", maxcom); break; default: - err("Ignoring extra header, type %d, length %d", + dev_err(&intf->dev, + "Ignoring extra header, type %d, length %d\n", buffer[2], buffer[0]); break; } @@ -772,7 +783,8 @@ static int recover_from_urb_loss(struct wdm_device *desc) if (desc->count) { rv = usb_submit_urb(desc->validity, GFP_NOIO); if (rv < 0) - err("Error resume submitting int urb - %d", rv); + dev_err(&desc->intf->dev, + "Error resume submitting int urb - %d\n", rv); } return rv; } diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 0647164d36db..b5775af3ba26 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -593,8 +593,9 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) err = usblp_hp_channel_change_request(usblp, arg, &newChannel); if (err < 0) { - err("usblp%d: error = %d setting " - "HP channel", + dev_err(&usblp->dev->dev, + "usblp%d: error = %d setting " + "HP channel\n", usblp->minor, err); retval = -EIO; goto done; @@ -1076,15 +1077,16 @@ static int usblp_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev (intf); - struct usblp *usblp = NULL; + struct usblp *usblp; int protocol; int retval; /* Malloc and start initializing usblp structure so we can use it * directly. */ - if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) { + usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL); + if (!usblp) { retval = -ENOMEM; - goto abort; + goto abort_ret; } usblp->dev = dev; mutex_init(&usblp->wmut); @@ -1179,12 +1181,11 @@ abort_intfdata: usb_set_intfdata (intf, NULL); device_remove_file(&intf->dev, &dev_attr_ieee1284_id); abort: - if (usblp) { - kfree(usblp->readbuf); - kfree(usblp->statusbuf); - kfree(usblp->device_id_string); - kfree(usblp); - } + kfree(usblp->readbuf); + kfree(usblp->statusbuf); + kfree(usblp->device_id_string); + kfree(usblp); +abort_ret: return retval; } @@ -1345,7 +1346,7 @@ static void usblp_disconnect(struct usb_interface *intf) usb_deregister_dev(intf, &usblp_class); if (!usblp || !usblp->dev) { - err("bogus disconnect"); + dev_err(&intf->dev, "bogus disconnect\n"); BUG (); } diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c new file mode 100644 index 000000000000..543811f6e6e8 --- /dev/null +++ b/drivers/usb/class/usbtmc.c @@ -0,0 +1,1087 @@ +/** + * drivers/usb/class/usbtmc.c - USB Test & Measurment class driver + * + * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany + * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The GNU General Public License is available at + * http://www.gnu.org/copyleft/gpl.html. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/kref.h> +#include <linux/mutex.h> +#include <linux/usb.h> +#include <linux/usb/tmc.h> + + +#define USBTMC_MINOR_BASE 176 + +/* + * Size of driver internal IO buffer. Must be multiple of 4 and at least as + * large as wMaxPacketSize (which is usually 512 bytes). + */ +#define USBTMC_SIZE_IOBUFFER 2048 + +/* Default USB timeout (in milliseconds) */ +#define USBTMC_TIMEOUT 10 + +/* + * Maximum number of read cycles to empty bulk in endpoint during CLEAR and + * ABORT_BULK_IN requests. Ends the loop if (for whatever reason) a short + * packet is never read. + */ +#define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 + +static struct usb_device_id usbtmc_devices[] = { + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, + { 0, } /* terminating entry */ +}; + +/* + * This structure is the capabilities for the device + * See section 4.2.1.8 of the USBTMC specification for details. + */ +struct usbtmc_dev_capabilities { + __u8 interface_capabilities; + __u8 device_capabilities; + __u8 usb488_interface_capabilities; + __u8 usb488_device_capabilities; +}; + +/* This structure holds private data for each USBTMC device. One copy is + * allocated for each USBTMC device in the driver's probe function. + */ +struct usbtmc_device_data { + const struct usb_device_id *id; + struct usb_device *usb_dev; + struct usb_interface *intf; + + unsigned int bulk_in; + unsigned int bulk_out; + + u8 bTag; + u8 bTag_last_write; /* needed for abort */ + u8 bTag_last_read; /* needed for abort */ + + /* attributes from the USB TMC spec for this device */ + u8 TermChar; + bool TermCharEnabled; + bool auto_abort; + + struct usbtmc_dev_capabilities capabilities; + struct kref kref; + struct mutex io_mutex; /* only one i/o function running at a time */ +}; +#define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) + +/* Forward declarations */ +static struct usb_driver usbtmc_driver; + +static void usbtmc_delete(struct kref *kref) +{ + struct usbtmc_device_data *data = to_usbtmc_data(kref); + + usb_put_dev(data->usb_dev); + kfree(data); +} + +static int usbtmc_open(struct inode *inode, struct file *filp) +{ + struct usb_interface *intf; + struct usbtmc_device_data *data; + int retval = -ENODEV; + + intf = usb_find_interface(&usbtmc_driver, iminor(inode)); + if (!intf) { + printk(KERN_ERR KBUILD_MODNAME + ": can not find device for minor %d", iminor(inode)); + goto exit; + } + + data = usb_get_intfdata(intf); + kref_get(&data->kref); + + /* Store pointer in file structure's private data field */ + filp->private_data = data; + +exit: + return retval; +} + +static int usbtmc_release(struct inode *inode, struct file *file) +{ + struct usbtmc_device_data *data = file->private_data; + + kref_put(&data->kref, usbtmc_delete); + return 0; +} + +static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) +{ + char *buffer; + struct device *dev; + int rv; + int n; + int actual; + struct usb_host_interface *current_setting; + int max_size; + + dev = &data->intf->dev; + buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_INITIATE_ABORT_BULK_IN, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, + data->bTag_last_read, data->bulk_in, + buffer, 2, USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); + + if (buffer[0] == USBTMC_STATUS_FAILED) { + rv = 0; + goto exit; + } + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", + buffer[0]); + rv = -EPERM; + goto exit; + } + + max_size = 0; + current_setting = data->intf->cur_altsetting; + for (n = 0; n < current_setting->desc.bNumEndpoints; n++) + if (current_setting->endpoint[n].desc.bEndpointAddress == + data->bulk_in) + max_size = le16_to_cpu(current_setting->endpoint[n]. + desc.wMaxPacketSize); + + if (max_size == 0) { + dev_err(dev, "Couldn't get wMaxPacketSize\n"); + rv = -EPERM; + goto exit; + } + + dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size); + + n = 0; + + do { + dev_dbg(dev, "Reading from bulk in EP\n"); + + rv = usb_bulk_msg(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, USBTMC_SIZE_IOBUFFER, + &actual, USBTMC_TIMEOUT); + + n++; + + if (rv < 0) { + dev_err(dev, "usb_bulk_msg returned %d\n", rv); + goto exit; + } + } while ((actual == max_size) && + (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); + + if (actual == max_size) { + dev_err(dev, "Couldn't clear device buffer within %d cycles\n", + USBTMC_MAX_READS_TO_CLEAR_BULK_IN); + rv = -EPERM; + goto exit; + } + + n = 0; + +usbtmc_abort_bulk_in_status: + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, + 0, data->bulk_in, buffer, 0x08, + USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); + + if (buffer[0] == USBTMC_STATUS_SUCCESS) { + rv = 0; + goto exit; + } + + if (buffer[0] != USBTMC_STATUS_PENDING) { + dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); + rv = -EPERM; + goto exit; + } + + if (buffer[1] == 1) + do { + dev_dbg(dev, "Reading from bulk in EP\n"); + + rv = usb_bulk_msg(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, USBTMC_SIZE_IOBUFFER, + &actual, USBTMC_TIMEOUT); + + n++; + + if (rv < 0) { + dev_err(dev, "usb_bulk_msg returned %d\n", rv); + goto exit; + } + } while ((actual = max_size) && + (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); + + if (actual == max_size) { + dev_err(dev, "Couldn't clear device buffer within %d cycles\n", + USBTMC_MAX_READS_TO_CLEAR_BULK_IN); + rv = -EPERM; + goto exit; + } + + goto usbtmc_abort_bulk_in_status; + +exit: + kfree(buffer); + return rv; + +} + +static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) +{ + struct device *dev; + u8 *buffer; + int rv; + int n; + + dev = &data->intf->dev; + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, + data->bTag_last_write, data->bulk_out, + buffer, 2, USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "INITIATE_ABORT_BULK_OUT returned %x\n", buffer[0]); + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "INITIATE_ABORT_BULK_OUT returned %x\n", + buffer[0]); + rv = -EPERM; + goto exit; + } + + n = 0; + +usbtmc_abort_bulk_out_check_status: + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, + 0, data->bulk_out, buffer, 0x08, + USBTMC_TIMEOUT); + n++; + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "CHECK_ABORT_BULK_OUT returned %x\n", buffer[0]); + + if (buffer[0] == USBTMC_STATUS_SUCCESS) + goto usbtmc_abort_bulk_out_clear_halt; + + if ((buffer[0] == USBTMC_STATUS_PENDING) && + (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)) + goto usbtmc_abort_bulk_out_check_status; + + rv = -EPERM; + goto exit; + +usbtmc_abort_bulk_out_clear_halt: + rv = usb_control_msg(data->usb_dev, + usb_sndctrlpipe(data->usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_DIR_OUT | USB_TYPE_STANDARD | + USB_RECIP_ENDPOINT, + USB_ENDPOINT_HALT, data->bulk_out, buffer, + 0, USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + rv = 0; + +exit: + kfree(buffer); + return rv; +} + +static ssize_t usbtmc_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct usbtmc_device_data *data; + struct device *dev; + unsigned long int n_characters; + u8 *buffer; + int actual; + int done; + int remaining; + int retval; + int this_part; + + /* Get pointer to private data structure */ + data = filp->private_data; + dev = &data->intf->dev; + + buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + mutex_lock(&data->io_mutex); + + remaining = count; + done = 0; + + while (remaining > 0) { + if (remaining > USBTMC_SIZE_IOBUFFER - 12 - 3) + this_part = USBTMC_SIZE_IOBUFFER - 12 - 3; + else + this_part = remaining; + + /* Setup IO buffer for DEV_DEP_MSG_IN message + * Refer to class specs for details + */ + buffer[0] = 2; + buffer[1] = data->bTag; + buffer[2] = ~(data->bTag); + buffer[3] = 0; /* Reserved */ + buffer[4] = (this_part - 12 - 3) & 255; + buffer[5] = ((this_part - 12 - 3) >> 8) & 255; + buffer[6] = ((this_part - 12 - 3) >> 16) & 255; + buffer[7] = ((this_part - 12 - 3) >> 24) & 255; + buffer[8] = data->TermCharEnabled * 2; + /* Use term character? */ + buffer[9] = data->TermChar; + buffer[10] = 0; /* Reserved */ + buffer[11] = 0; /* Reserved */ + + /* Send bulk URB */ + retval = usb_bulk_msg(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, 12, &actual, USBTMC_TIMEOUT); + + /* Store bTag (in case we need to abort) */ + data->bTag_last_write = data->bTag; + + /* Increment bTag -- and increment again if zero */ + data->bTag++; + if (!data->bTag) + (data->bTag)++; + + if (retval < 0) { + dev_err(dev, "usb_bulk_msg returned %d\n", retval); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_out(data); + goto exit; + } + + /* Send bulk URB */ + retval = usb_bulk_msg(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, USBTMC_SIZE_IOBUFFER, &actual, + USBTMC_TIMEOUT); + + /* Store bTag (in case we need to abort) */ + data->bTag_last_read = data->bTag; + + if (retval < 0) { + dev_err(dev, "Unable to read data, error %d\n", retval); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + /* How many characters did the instrument send? */ + n_characters = buffer[4] + + (buffer[5] << 8) + + (buffer[6] << 16) + + (buffer[7] << 24); + + /* Copy buffer to user space */ + if (copy_to_user(buf + done, &buffer[12], n_characters)) { + /* There must have been an addressing problem */ + retval = -EFAULT; + goto exit; + } + + done += n_characters; + if (n_characters < USBTMC_SIZE_IOBUFFER) + remaining = 0; + } + + /* Update file position value */ + *f_pos = *f_pos + done; + retval = done; + +exit: + mutex_unlock(&data->io_mutex); + kfree(buffer); + return retval; +} + +static ssize_t usbtmc_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct usbtmc_device_data *data; + u8 *buffer; + int retval; + int actual; + unsigned long int n_bytes; + int n; + int remaining; + int done; + int this_part; + + data = filp->private_data; + + buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + mutex_lock(&data->io_mutex); + + remaining = count; + done = 0; + + while (remaining > 0) { + if (remaining > USBTMC_SIZE_IOBUFFER - 12) { + this_part = USBTMC_SIZE_IOBUFFER - 12; + buffer[8] = 0; + } else { + this_part = remaining; + buffer[8] = 1; + } + + /* Setup IO buffer for DEV_DEP_MSG_OUT message */ + buffer[0] = 1; + buffer[1] = data->bTag; + buffer[2] = ~(data->bTag); + buffer[3] = 0; /* Reserved */ + buffer[4] = this_part & 255; + buffer[5] = (this_part >> 8) & 255; + buffer[6] = (this_part >> 16) & 255; + buffer[7] = (this_part >> 24) & 255; + /* buffer[8] is set above... */ + buffer[9] = 0; /* Reserved */ + buffer[10] = 0; /* Reserved */ + buffer[11] = 0; /* Reserved */ + + if (copy_from_user(&buffer[12], buf + done, this_part)) { + retval = -EFAULT; + goto exit; + } + + n_bytes = 12 + this_part; + if (this_part % 4) + n_bytes += 4 - this_part % 4; + for (n = 12 + this_part; n < n_bytes; n++) + buffer[n] = 0; + + retval = usb_bulk_msg(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, n_bytes, &actual, USBTMC_TIMEOUT); + + data->bTag_last_write = data->bTag; + data->bTag++; + + if (!data->bTag) + data->bTag++; + + if (retval < 0) { + dev_err(&data->intf->dev, + "Unable to send data, error %d\n", retval); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_out(data); + goto exit; + } + + remaining -= this_part; + done += this_part; + } + + retval = count; +exit: + mutex_unlock(&data->io_mutex); + kfree(buffer); + return retval; +} + +static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) +{ + struct usb_host_interface *current_setting; + struct usb_endpoint_descriptor *desc; + struct device *dev; + u8 *buffer; + int rv; + int n; + int actual; + int max_size; + + dev = &data->intf->dev; + + dev_dbg(dev, "Sending INITIATE_CLEAR request\n"); + + buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_INITIATE_CLEAR, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, 0, buffer, 1, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "INITIATE_CLEAR returned %x\n", buffer[0]); + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "INITIATE_CLEAR returned %x\n", buffer[0]); + rv = -EPERM; + goto exit; + } + + max_size = 0; + current_setting = data->intf->cur_altsetting; + for (n = 0; n < current_setting->desc.bNumEndpoints; n++) { + desc = ¤t_setting->endpoint[n].desc; + if (desc->bEndpointAddress == data->bulk_in) + max_size = le16_to_cpu(desc->wMaxPacketSize); + } + + if (max_size == 0) { + dev_err(dev, "Couldn't get wMaxPacketSize\n"); + rv = -EPERM; + goto exit; + } + + dev_dbg(dev, "wMaxPacketSize is %d\n", max_size); + + n = 0; + +usbtmc_clear_check_status: + + dev_dbg(dev, "Sending CHECK_CLEAR_STATUS request\n"); + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_CHECK_CLEAR_STATUS, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, 0, buffer, 2, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "CHECK_CLEAR_STATUS returned %x\n", buffer[0]); + + if (buffer[0] == USBTMC_STATUS_SUCCESS) + goto usbtmc_clear_bulk_out_halt; + + if (buffer[0] != USBTMC_STATUS_PENDING) { + dev_err(dev, "CHECK_CLEAR_STATUS returned %x\n", buffer[0]); + rv = -EPERM; + goto exit; + } + + if (buffer[1] == 1) + do { + dev_dbg(dev, "Reading from bulk in EP\n"); + + rv = usb_bulk_msg(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, USBTMC_SIZE_IOBUFFER, + &actual, USBTMC_TIMEOUT); + n++; + + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", + rv); + goto exit; + } + } while ((actual == max_size) && + (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); + + if (actual == max_size) { + dev_err(dev, "Couldn't clear device buffer within %d cycles\n", + USBTMC_MAX_READS_TO_CLEAR_BULK_IN); + rv = -EPERM; + goto exit; + } + + goto usbtmc_clear_check_status; + +usbtmc_clear_bulk_out_halt: + + rv = usb_control_msg(data->usb_dev, + usb_sndctrlpipe(data->usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_DIR_OUT | USB_TYPE_STANDARD | + USB_RECIP_ENDPOINT, + USB_ENDPOINT_HALT, + data->bulk_out, buffer, 0, + USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + rv = 0; + +exit: + kfree(buffer); + return rv; +} + +static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data) +{ + u8 *buffer; + int rv; + + buffer = kmalloc(2, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, + usb_sndctrlpipe(data->usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_DIR_OUT | USB_TYPE_STANDARD | + USB_RECIP_ENDPOINT, + USB_ENDPOINT_HALT, data->bulk_out, + buffer, 0, USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", + rv); + goto exit; + } + rv = 0; + +exit: + kfree(buffer); + return rv; +} + +static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) +{ + u8 *buffer; + int rv; + + buffer = kmalloc(2, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, usb_sndctrlpipe(data->usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_DIR_OUT | USB_TYPE_STANDARD | + USB_RECIP_ENDPOINT, + USB_ENDPOINT_HALT, data->bulk_in, buffer, 0, + USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", + rv); + goto exit; + } + rv = 0; + +exit: + kfree(buffer); + return rv; +} + +static int get_capabilities(struct usbtmc_device_data *data) +{ + struct device *dev = &data->usb_dev->dev; + char *buffer; + int rv; + + buffer = kmalloc(0x18, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_GET_CAPABILITIES, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, 0, buffer, 0x18, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + return rv; + } + + dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); + dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]); + dev_dbg(dev, "Device capabilities are %x\n", buffer[5]); + dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]); + dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); + return -EPERM; + } + + data->capabilities.interface_capabilities = buffer[4]; + data->capabilities.device_capabilities = buffer[5]; + data->capabilities.usb488_interface_capabilities = buffer[14]; + data->capabilities.usb488_device_capabilities = buffer[15]; + + kfree(buffer); + return 0; +} + +#define capability_attribute(name) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usbtmc_device_data *data = usb_get_intfdata(intf); \ + \ + return sprintf(buf, "%d\n", data->capabilities.name); \ +} \ +static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +capability_attribute(interface_capabilities); +capability_attribute(device_capabilities); +capability_attribute(usb488_interface_capabilities); +capability_attribute(usb488_device_capabilities); + +static struct attribute *capability_attrs[] = { + &dev_attr_interface_capabilities.attr, + &dev_attr_device_capabilities.attr, + &dev_attr_usb488_interface_capabilities.attr, + &dev_attr_usb488_device_capabilities.attr, + NULL, +}; + +static struct attribute_group capability_attr_grp = { + .attrs = capability_attrs, +}; + +static ssize_t show_TermChar(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usbtmc_device_data *data = usb_get_intfdata(intf); + + return sprintf(buf, "%c\n", data->TermChar); +} + +static ssize_t store_TermChar(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usbtmc_device_data *data = usb_get_intfdata(intf); + + if (count < 1) + return -EINVAL; + data->TermChar = buf[0]; + return count; +} +static DEVICE_ATTR(TermChar, S_IRUGO, show_TermChar, store_TermChar); + +#define data_attribute(name) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usbtmc_device_data *data = usb_get_intfdata(intf); \ + \ + return sprintf(buf, "%d\n", data->name); \ +} \ +static ssize_t store_##name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usbtmc_device_data *data = usb_get_intfdata(intf); \ + ssize_t result; \ + unsigned val; \ + \ + result = sscanf(buf, "%u\n", &val); \ + if (result != 1) \ + result = -EINVAL; \ + data->name = val; \ + if (result < 0) \ + return result; \ + else \ + return count; \ +} \ +static DEVICE_ATTR(name, S_IRUGO, show_##name, store_##name) + +data_attribute(TermCharEnabled); +data_attribute(auto_abort); + +static struct attribute *data_attrs[] = { + &dev_attr_TermChar.attr, + &dev_attr_TermCharEnabled.attr, + &dev_attr_auto_abort.attr, + NULL, +}; + +static struct attribute_group data_attr_grp = { + .attrs = data_attrs, +}; + +static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) +{ + struct device *dev; + u8 *buffer; + int rv; + + dev = &data->intf->dev; + + buffer = kmalloc(2, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC_REQUEST_INDICATOR_PULSE, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, 0, buffer, 0x01, USBTMC_TIMEOUT); + + if (rv < 0) { + dev_err(dev, "usb_control_msg returned %d\n", rv); + goto exit; + } + + dev_dbg(dev, "INDICATOR_PULSE returned %x\n", buffer[0]); + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "INDICATOR_PULSE returned %x\n", buffer[0]); + rv = -EPERM; + goto exit; + } + rv = 0; + +exit: + kfree(buffer); + return rv; +} + +static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct usbtmc_device_data *data; + int retval = -EBADRQC; + + data = file->private_data; + mutex_lock(&data->io_mutex); + + switch (cmd) { + case USBTMC_IOCTL_CLEAR_OUT_HALT: + retval = usbtmc_ioctl_clear_out_halt(data); + + case USBTMC_IOCTL_CLEAR_IN_HALT: + retval = usbtmc_ioctl_clear_in_halt(data); + + case USBTMC_IOCTL_INDICATOR_PULSE: + retval = usbtmc_ioctl_indicator_pulse(data); + + case USBTMC_IOCTL_CLEAR: + retval = usbtmc_ioctl_clear(data); + + case USBTMC_IOCTL_ABORT_BULK_OUT: + retval = usbtmc_ioctl_abort_bulk_out(data); + + case USBTMC_IOCTL_ABORT_BULK_IN: + retval = usbtmc_ioctl_abort_bulk_in(data); + } + + mutex_unlock(&data->io_mutex); + return retval; +} + +static struct file_operations fops = { + .owner = THIS_MODULE, + .read = usbtmc_read, + .write = usbtmc_write, + .open = usbtmc_open, + .release = usbtmc_release, + .unlocked_ioctl = usbtmc_ioctl, +}; + +static struct usb_class_driver usbtmc_class = { + .name = "usbtmc%d", + .fops = &fops, + .minor_base = USBTMC_MINOR_BASE, +}; + + +static int usbtmc_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usbtmc_device_data *data; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int n; + int retcode; + + dev_dbg(&intf->dev, "%s called\n", __func__); + + data = kmalloc(sizeof(struct usbtmc_device_data), GFP_KERNEL); + if (!data) { + dev_err(&intf->dev, "Unable to allocate kernel memory\n"); + return -ENOMEM; + } + + data->intf = intf; + data->id = id; + data->usb_dev = usb_get_dev(interface_to_usbdev(intf)); + usb_set_intfdata(intf, data); + kref_init(&data->kref); + mutex_init(&data->io_mutex); + + /* Initialize USBTMC bTag and other fields */ + data->bTag = 1; + data->TermCharEnabled = 0; + data->TermChar = '\n'; + + /* USBTMC devices have only one setting, so use that */ + iface_desc = data->intf->cur_altsetting; + + /* Find bulk in endpoint */ + for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { + endpoint = &iface_desc->endpoint[n].desc; + + if (usb_endpoint_is_bulk_in(endpoint)) { + data->bulk_in = endpoint->bEndpointAddress; + dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", + data->bulk_in); + break; + } + } + + /* Find bulk out endpoint */ + for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { + endpoint = &iface_desc->endpoint[n].desc; + + if (usb_endpoint_is_bulk_out(endpoint)) { + data->bulk_out = endpoint->bEndpointAddress; + dev_dbg(&intf->dev, "Found Bulk out endpoint at %u\n", + data->bulk_out); + break; + } + } + + retcode = get_capabilities(data); + if (retcode) + dev_err(&intf->dev, "can't read capabilities\n"); + else + retcode = sysfs_create_group(&intf->dev.kobj, + &capability_attr_grp); + + retcode = sysfs_create_group(&intf->dev.kobj, &data_attr_grp); + + retcode = usb_register_dev(intf, &usbtmc_class); + if (retcode) { + dev_err(&intf->dev, "Not able to get a minor" + " (base %u, slice default): %d\n", USBTMC_MINOR_BASE, + retcode); + goto error_register; + } + dev_dbg(&intf->dev, "Using minor number %d\n", intf->minor); + + return 0; + +error_register: + sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); + sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); + kref_put(&data->kref, usbtmc_delete); + return retcode; +} + +static void usbtmc_disconnect(struct usb_interface *intf) +{ + struct usbtmc_device_data *data; + + dev_dbg(&intf->dev, "usbtmc_disconnect called\n"); + + data = usb_get_intfdata(intf); + usb_deregister_dev(intf, &usbtmc_class); + sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); + sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); + kref_put(&data->kref, usbtmc_delete); +} + +static struct usb_driver usbtmc_driver = { + .name = "usbtmc", + .id_table = usbtmc_devices, + .probe = usbtmc_probe, + .disconnect = usbtmc_disconnect +}; + +static int __init usbtmc_init(void) +{ + int retcode; + + retcode = usb_register(&usbtmc_driver); + if (retcode) + printk(KERN_ERR KBUILD_MODNAME": Unable to register driver\n"); + return retcode; +} +module_init(usbtmc_init); + +static void __exit usbtmc_exit(void) +{ + usb_deregister(&usbtmc_driver); +} +module_exit(usbtmc_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index cc9f397e8398..e1759d17ac5d 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -134,5 +134,5 @@ config USB_OTG_BLACKLIST_HUB If you say Y here, then Linux will refuse to enumerate external hubs. OTG hosts are allowed to reduce hardware and software costs by not supporting external hubs. So - are "Emedded Hosts" that don't offer OTG support. + are "Embedded Hosts" that don't offer OTG support. diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 20290c5b1562..2bccefebff1b 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -413,7 +413,8 @@ static void driver_disconnect(struct usb_interface *intf) if (likely(ifnum < 8*sizeof(ps->ifclaimed))) clear_bit(ifnum, &ps->ifclaimed); else - warn("interface number %u out of range", ifnum); + dev_warn(&intf->dev, "interface number %u out of range\n", + ifnum); usb_set_intfdata(intf, NULL); @@ -624,6 +625,8 @@ static int usbdev_open(struct inode *inode, struct file *file) smp_wmb(); list_add_tail(&ps->list, &dev->filelist); file->private_data = ps; + snoop(&dev->dev, "opened by process %d: %s\n", task_pid_nr(current), + current->comm); out: if (ret) { kfree(ps); @@ -1729,9 +1732,9 @@ static int usb_classdev_add(struct usb_device *dev) { struct device *cldev; - cldev = device_create_drvdata(usb_classdev_class, &dev->dev, - dev->dev.devt, NULL, "usbdev%d.%d", - dev->bus->busnum, dev->devnum); + cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt, + NULL, "usbdev%d.%d", dev->bus->busnum, + dev->devnum); if (IS_ERR(cldev)) return PTR_ERR(cldev); dev->usb_classdev = cldev; @@ -1774,19 +1777,20 @@ int __init usb_devio_init(void) retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX, "usb_device"); if (retval) { - err("unable to register minors for usb_device"); + printk(KERN_ERR "Unable to register minors for usb_device\n"); goto out; } cdev_init(&usb_device_cdev, &usbdev_file_operations); retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); if (retval) { - err("unable to get usb_device major %d", USB_DEVICE_MAJOR); + printk(KERN_ERR "Unable to get usb_device major %d\n", + USB_DEVICE_MAJOR); goto error_cdev; } #ifdef CONFIG_USB_DEVICE_CLASS usb_classdev_class = class_create(THIS_MODULE, "usb_device"); if (IS_ERR(usb_classdev_class)) { - err("unable to register usb_device class"); + printk(KERN_ERR "Unable to register usb_device class\n"); retval = PTR_ERR(usb_classdev_class); cdev_del(&usb_device_cdev); usb_classdev_class = NULL; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 5a7fa6f09958..e935be7eb468 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1070,7 +1070,8 @@ static int autosuspend_check(struct usb_device *udev, int reschedule) struct usb_driver *driver; driver = to_usb_driver(intf->dev.driver); - if (!driver->reset_resume) + if (!driver->reset_resume || + intf->needs_remote_wakeup) return -EOPNOTSUPP; } } diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 22912136fc14..946fae43d622 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -169,7 +169,8 @@ static int usb_endpoint_major_init(void) error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS, "usb_endpoint"); if (error) { - err("unable to get a dynamic major for usb endpoints"); + printk(KERN_ERR "Unable to get a dynamic major for " + "usb endpoints.\n"); return error; } usb_endpoint_major = MAJOR(dev); diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 6b1b229e38cd..997e659ff693 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -86,7 +86,7 @@ static int init_usb_class(void) usb_class->class = class_create(THIS_MODULE, "usb"); if (IS_ERR(usb_class->class)) { result = IS_ERR(usb_class->class); - err("class_create failed for usb devices"); + printk(KERN_ERR "class_create failed for usb devices\n"); kfree(usb_class); usb_class = NULL; } @@ -115,7 +115,8 @@ int usb_major_init(void) error = register_chrdev(USB_MAJOR, "usb", &usb_fops); if (error) - err("unable to get major %d for usb devices", USB_MAJOR); + printk(KERN_ERR "Unable to get major %d for usb devices\n", + USB_MAJOR); return error; } @@ -196,9 +197,9 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev, - MKDEV(USB_MAJOR, minor), NULL, - "%s", temp); + intf->usb_dev = device_create(usb_class->class, &intf->dev, + MKDEV(USB_MAJOR, minor), NULL, + "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8ab389dca2b9..fc9018e72a09 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -81,6 +81,10 @@ /*-------------------------------------------------------------------------*/ +/* Keep track of which host controller drivers are loaded */ +unsigned long usb_hcds_loaded; +EXPORT_SYMBOL_GPL(usb_hcds_loaded); + /* host controllers we manage */ LIST_HEAD (usb_bus_list); EXPORT_SYMBOL_GPL (usb_bus_list); @@ -818,9 +822,8 @@ static int usb_register_bus(struct usb_bus *bus) set_bit (busnum, busmap.busmap); bus->busnum = busnum; - bus->dev = device_create_drvdata(usb_host_class, bus->controller, - MKDEV(0, 0), bus, - "usb_host%d", busnum); + bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0), + bus, "usb_host%d", busnum); result = PTR_ERR(bus->dev); if (IS_ERR(bus->dev)) goto error_create_class_dev; diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index e710ce04e228..2dcde61c465e 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -482,4 +482,10 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, */ extern struct rw_semaphore ehci_cf_port_reset_rwsem; +/* Keep track of which host controller drivers are loaded */ +#define USB_UHCI_LOADED 0 +#define USB_OHCI_LOADED 1 +#define USB_EHCI_LOADED 2 +extern unsigned long usb_hcds_loaded; + #endif /* __KERNEL__ */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d99963873e37..d73ce262c365 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -77,6 +77,7 @@ struct usb_hub { unsigned has_indicators:1; u8 indicator[USB_MAXCHILDREN]; struct delayed_work leds; + struct delayed_work init_work; }; @@ -100,6 +101,15 @@ module_param (blinkenlights, bool, S_IRUGO); MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); /* + * Device SATA8000 FW1.0 from DATAST0R Technology Corp requires about + * 10 seconds to send reply for the initial 64-byte descriptor request. + */ +/* define initial 64-byte descriptor request timeout in milliseconds */ +static int initial_descriptor_timeout = USB_CTRL_GET_TIMEOUT; +module_param(initial_descriptor_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(initial_descriptor_timeout, "initial 64-byte descriptor request timeout in milliseconds (default 5000 - 5.0 seconds)"); + +/* * As of 2.6.10 we introduce a new USB device initialization scheme which * closely resembles the way Windows works. Hopefully it will be compatible * with a wider range of devices than the old scheme. However some previously @@ -515,10 +525,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) } EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer); -static void hub_power_on(struct usb_hub *hub) +/* If do_delay is false, return the number of milliseconds the caller + * needs to delay. + */ +static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) { int port1; unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; + unsigned delay; u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); @@ -537,7 +551,10 @@ static void hub_power_on(struct usb_hub *hub) set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ - msleep(max(pgood_delay, (unsigned) 100)); + delay = max(pgood_delay, (unsigned) 100); + if (do_delay) + msleep(delay); + return delay; } static int hub_hub_status(struct usb_hub *hub, @@ -599,21 +616,55 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) } enum hub_activation_type { - HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME + HUB_INIT, HUB_INIT2, HUB_INIT3, + HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, }; +static void hub_init_func2(struct work_struct *ws); +static void hub_init_func3(struct work_struct *ws); + static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) { struct usb_device *hdev = hub->hdev; int port1; int status; bool need_debounce_delay = false; + unsigned delay; + + /* Continue a partial initialization */ + if (type == HUB_INIT2) + goto init2; + if (type == HUB_INIT3) + goto init3; /* After a resume, port power should still be on. * For any other type of activation, turn it on. */ - if (type != HUB_RESUME) - hub_power_on(hub); + if (type != HUB_RESUME) { + + /* Speed up system boot by using a delayed_work for the + * hub's initial power-up delays. This is pretty awkward + * and the implementation looks like a home-brewed sort of + * setjmp/longjmp, but it saves at least 100 ms for each + * root hub (assuming usbcore is compiled into the kernel + * rather than as a module). It adds up. + * + * This can't be done for HUB_RESUME or HUB_RESET_RESUME + * because for those activation types the ports have to be + * operational when we return. In theory this could be done + * for HUB_POST_RESET, but it's easier not to. + */ + if (type == HUB_INIT) { + delay = hub_power_on(hub, false); + PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); + schedule_delayed_work(&hub->init_work, + msecs_to_jiffies(delay)); + return; /* Continues at init2: below */ + } else { + hub_power_on(hub, true); + } + } + init2: /* Check each port and set hub->change_bits to let khubd know * which ports need attention. @@ -692,9 +743,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) * If any port-status changes do occur during this delay, khubd * will see them later and handle them normally. */ - if (need_debounce_delay) - msleep(HUB_DEBOUNCE_STABLE); - + if (need_debounce_delay) { + delay = HUB_DEBOUNCE_STABLE; + + /* Don't do a long sleep inside a workqueue routine */ + if (type == HUB_INIT2) { + PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3); + schedule_delayed_work(&hub->init_work, + msecs_to_jiffies(delay)); + return; /* Continues at init3: below */ + } else { + msleep(delay); + } + } + init3: hub->quiescing = 0; status = usb_submit_urb(hub->urb, GFP_NOIO); @@ -707,6 +769,21 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) kick_khubd(hub); } +/* Implement the continuations for the delays above */ +static void hub_init_func2(struct work_struct *ws) +{ + struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work); + + hub_activate(hub, HUB_INIT2); +} + +static void hub_init_func3(struct work_struct *ws) +{ + struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work); + + hub_activate(hub, HUB_INIT3); +} + enum hub_quiescing_type { HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND }; @@ -716,6 +793,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) struct usb_device *hdev = hub->hdev; int i; + cancel_delayed_work_sync(&hub->init_work); + /* khubd and related activity won't re-trigger */ hub->quiescing = 1; @@ -1099,6 +1178,7 @@ descriptor_error: hub->intfdev = &intf->dev; hub->hdev = hdev; INIT_DELAYED_WORK(&hub->leds, led_work); + INIT_DELAYED_WORK(&hub->init_work, NULL); usb_get_intf(intf); usb_set_intfdata (intf, hub); @@ -2467,7 +2547,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_DT_DEVICE << 8, 0, buf, GET_DESCRIPTOR_BUFSIZE, - USB_CTRL_GET_TIMEOUT); + initial_descriptor_timeout); switch (buf->bMaxPacketSize0) { case 8: case 16: case 32: case 64: case 255: if (buf->bDescriptorType == @@ -3035,7 +3115,7 @@ static void hub_events(void) i); clear_port_feature(hdev, i, USB_PORT_FEAT_C_OVER_CURRENT); - hub_power_on(hub); + hub_power_on(hub, true); } if (portchange & USB_PORT_STAT_C_RESET) { @@ -3070,7 +3150,7 @@ static void hub_events(void) dev_dbg (hub_dev, "overcurrent change\n"); msleep(500); /* Cool down */ clear_hub_feature(hdev, C_HUB_OVER_CURRENT); - hub_power_on(hub); + hub_power_on(hub, true); } } diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index db410e92c80d..94632264dccf 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -97,7 +97,7 @@ enum { Opt_err, }; -static match_table_t tokens = { +static const match_table_t tokens = { {Opt_devuid, "devuid=%u"}, {Opt_devgid, "devgid=%u"}, {Opt_devmode, "devmode=%o"}, @@ -180,8 +180,8 @@ static int parse_options(struct super_block *s, char *data) listmode = option & S_IRWXUGO; break; default: - err("usbfs: unrecognised mount option \"%s\" " - "or missing value\n", p); + printk(KERN_ERR "usbfs: unrecognised mount option " + "\"%s\" or missing value\n", p); return -EINVAL; } } @@ -240,7 +240,9 @@ static void update_sb(struct super_block *sb) update_special(bus); break; default: - warn("Unknown node %s mode %x found on remount!\n",bus->d_name.name,bus->d_inode->i_mode); + printk(KERN_WARNING "usbfs: Unknown node %s " + "mode %x found on remount!\n", + bus->d_name.name, bus->d_inode->i_mode); break; } } @@ -259,7 +261,7 @@ static int remount(struct super_block *sb, int *flags, char *data) return 0; if (parse_options(sb, data)) { - warn("usbfs: mount parameter error:"); + printk(KERN_WARNING "usbfs: mount parameter error.\n"); return -EINVAL; } @@ -599,7 +601,7 @@ static int create_special_files (void) /* create the devices special file */ retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count); if (retval) { - err ("Unable to get usbfs mount"); + printk(KERN_ERR "Unable to get usbfs mount\n"); goto exit; } @@ -611,7 +613,7 @@ static int create_special_files (void) NULL, &usbfs_devices_fops, listuid, listgid); if (devices_usbfs_dentry == NULL) { - err ("Unable to create devices usbfs file"); + printk(KERN_ERR "Unable to create devices usbfs file\n"); retval = -ENODEV; goto error_clean_mounts; } @@ -663,7 +665,7 @@ static void usbfs_add_bus(struct usb_bus *bus) bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, bus, NULL, busuid, busgid); if (bus->usbfs_dentry == NULL) { - err ("error creating usbfs bus entry"); + printk(KERN_ERR "Error creating usbfs bus entry\n"); return; } } @@ -694,7 +696,7 @@ static void usbfs_add_device(struct usb_device *dev) &usbdev_file_operations, devuid, devgid); if (dev->usbfs_dentry == NULL) { - err ("error creating usbfs device entry"); + printk(KERN_ERR "Error creating usbfs device entry\n"); return; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 286b4431a097..887738577b28 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1204,7 +1204,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) alt = usb_altnum_to_altsetting(iface, alternate); if (!alt) { - warn("selecting invalid altsetting %d", alternate); + dev_warn(&dev->dev, "selecting invalid altsetting %d", + alternate); return -EINVAL; } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 5e1f5d55bf04..f66fba11fbd5 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -743,6 +743,29 @@ static ssize_t show_modalias(struct device *dev, } static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); +static ssize_t show_supports_autosuspend(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf; + struct usb_device *udev; + int ret; + + intf = to_usb_interface(dev); + udev = interface_to_usbdev(intf); + + usb_lock_device(udev); + /* Devices will be autosuspended even when an interface isn't claimed */ + if (!intf->dev.driver || + to_usb_driver(intf->dev.driver)->supports_autosuspend) + ret = sprintf(buf, "%u\n", 1); + else + ret = sprintf(buf, "%u\n", 0); + usb_unlock_device(udev); + + return ret; +} +static DEVICE_ATTR(supports_autosuspend, S_IRUGO, show_supports_autosuspend, NULL); + static struct attribute *intf_attrs[] = { &dev_attr_bInterfaceNumber.attr, &dev_attr_bAlternateSetting.attr, @@ -751,6 +774,7 @@ static struct attribute *intf_attrs[] = { &dev_attr_bInterfaceSubClass.attr, &dev_attr_bInterfaceProtocol.attr, &dev_attr_modalias.attr, + &dev_attr_supports_autosuspend.attr, NULL, }; static struct attribute_group intf_attr_grp = { diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 47111e88f791..f2638009a464 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -10,6 +10,8 @@ #define to_urb(d) container_of(d, struct urb, kref) +static DEFINE_SPINLOCK(usb_reject_lock); + static void urb_destroy(struct kref *kref) { struct urb *urb = to_urb(kref); @@ -68,7 +70,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) iso_packets * sizeof(struct usb_iso_packet_descriptor), mem_flags); if (!urb) { - err("alloc_urb: kmalloc failed"); + printk(KERN_ERR "alloc_urb: kmalloc failed\n"); return NULL; } usb_init_urb(urb); @@ -127,6 +129,13 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor) usb_get_urb(urb); list_add_tail(&urb->anchor_list, &anchor->urb_list); urb->anchor = anchor; + + if (unlikely(anchor->poisoned)) { + spin_lock(&usb_reject_lock); + urb->reject++; + spin_unlock(&usb_reject_lock); + } + spin_unlock_irqrestore(&anchor->lock, flags); } EXPORT_SYMBOL_GPL(usb_anchor_urb); @@ -398,7 +407,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* fail if submitter gave bogus flags */ if (urb->transfer_flags != orig_flags) { - err("BOGUS urb flags, %x --> %x", + dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n", orig_flags, urb->transfer_flags); return -EINVAL; } @@ -544,25 +553,70 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb); */ void usb_kill_urb(struct urb *urb) { - static DEFINE_MUTEX(reject_mutex); - might_sleep(); if (!(urb && urb->dev && urb->ep)) return; - mutex_lock(&reject_mutex); + spin_lock_irq(&usb_reject_lock); ++urb->reject; - mutex_unlock(&reject_mutex); + spin_unlock_irq(&usb_reject_lock); usb_hcd_unlink_urb(urb, -ENOENT); wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); - mutex_lock(&reject_mutex); + spin_lock_irq(&usb_reject_lock); --urb->reject; - mutex_unlock(&reject_mutex); + spin_unlock_irq(&usb_reject_lock); } EXPORT_SYMBOL_GPL(usb_kill_urb); /** + * usb_poison_urb - reliably kill a transfer and prevent further use of an URB + * @urb: pointer to URB describing a previously submitted request, + * may be NULL + * + * This routine cancels an in-progress request. It is guaranteed that + * upon return all completion handlers will have finished and the URB + * will be totally idle and cannot be reused. These features make + * this an ideal way to stop I/O in a disconnect() callback. + * If the request has not already finished or been unlinked + * the completion handler will see urb->status == -ENOENT. + * + * After and while the routine runs, attempts to resubmit the URB will fail + * with error -EPERM. Thus even if the URB's completion handler always + * tries to resubmit, it will not succeed and the URB will become idle. + * + * This routine may not be used in an interrupt context (such as a bottom + * half or a completion handler), or when holding a spinlock, or in other + * situations where the caller can't schedule(). + */ +void usb_poison_urb(struct urb *urb) +{ + might_sleep(); + if (!(urb && urb->dev && urb->ep)) + return; + spin_lock_irq(&usb_reject_lock); + ++urb->reject; + spin_unlock_irq(&usb_reject_lock); + + usb_hcd_unlink_urb(urb, -ENOENT); + wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); +} +EXPORT_SYMBOL_GPL(usb_poison_urb); + +void usb_unpoison_urb(struct urb *urb) +{ + unsigned long flags; + + if (!urb) + return; + + spin_lock_irqsave(&usb_reject_lock, flags); + --urb->reject; + spin_unlock_irqrestore(&usb_reject_lock, flags); +} +EXPORT_SYMBOL_GPL(usb_unpoison_urb); + +/** * usb_kill_anchored_urbs - cancel transfer requests en masse * @anchor: anchor the requests are bound to * @@ -589,6 +643,35 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor) } EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); + +/** + * usb_poison_anchored_urbs - cease all traffic from an anchor + * @anchor: anchor the requests are bound to + * + * this allows all outstanding URBs to be poisoned starting + * from the back of the queue. Newly added URBs will also be + * poisoned + */ +void usb_poison_anchored_urbs(struct usb_anchor *anchor) +{ + struct urb *victim; + + spin_lock_irq(&anchor->lock); + anchor->poisoned = 1; + while (!list_empty(&anchor->urb_list)) { + victim = list_entry(anchor->urb_list.prev, struct urb, + anchor_list); + /* we must make sure the URB isn't freed before we kill it*/ + usb_get_urb(victim); + spin_unlock_irq(&anchor->lock); + /* this will unanchor the URB */ + usb_poison_urb(victim); + usb_put_urb(victim); + spin_lock_irq(&anchor->lock); + } + spin_unlock_irq(&anchor->lock); +} +EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); /** * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse * @anchor: anchor the requests are bound to @@ -633,3 +716,73 @@ int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, msecs_to_jiffies(timeout)); } EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout); + +/** + * usb_get_from_anchor - get an anchor's oldest urb + * @anchor: the anchor whose urb you want + * + * this will take the oldest urb from an anchor, + * unanchor and return it + */ +struct urb *usb_get_from_anchor(struct usb_anchor *anchor) +{ + struct urb *victim; + unsigned long flags; + + spin_lock_irqsave(&anchor->lock, flags); + if (!list_empty(&anchor->urb_list)) { + victim = list_entry(anchor->urb_list.next, struct urb, + anchor_list); + usb_get_urb(victim); + spin_unlock_irqrestore(&anchor->lock, flags); + usb_unanchor_urb(victim); + } else { + spin_unlock_irqrestore(&anchor->lock, flags); + victim = NULL; + } + + return victim; +} + +EXPORT_SYMBOL_GPL(usb_get_from_anchor); + +/** + * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs + * @anchor: the anchor whose urbs you want to unanchor + * + * use this to get rid of all an anchor's urbs + */ +void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) +{ + struct urb *victim; + unsigned long flags; + + spin_lock_irqsave(&anchor->lock, flags); + while (!list_empty(&anchor->urb_list)) { + victim = list_entry(anchor->urb_list.prev, struct urb, + anchor_list); + usb_get_urb(victim); + spin_unlock_irqrestore(&anchor->lock, flags); + /* this may free the URB */ + usb_unanchor_urb(victim); + usb_put_urb(victim); + spin_lock_irqsave(&anchor->lock, flags); + } + spin_unlock_irqrestore(&anchor->lock, flags); +} + +EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs); + +/** + * usb_anchor_empty - is an anchor empty + * @anchor: the anchor you want to query + * + * returns 1 if the anchor has no urbs associated with it + */ +int usb_anchor_empty(struct usb_anchor *anchor) +{ + return list_empty(&anchor->urb_list); +} + +EXPORT_SYMBOL_GPL(usb_anchor_empty); + diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index acc95b2ac6f8..dd4cd5a51370 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -45,7 +45,7 @@ if USB_GADGET config USB_GADGET_DEBUG boolean "Debugging messages (DEVELOPMENT)" - depends on USB_GADGET && DEBUG_KERNEL + depends on DEBUG_KERNEL help Many controller and gadget drivers will print some debugging messages if you use this option to ask for those messages. @@ -59,7 +59,7 @@ config USB_GADGET_DEBUG config USB_GADGET_DEBUG_FILES boolean "Debugging information files (DEVELOPMENT)" - depends on USB_GADGET && PROC_FS + depends on PROC_FS help Some of the drivers in the "gadget" framework can expose debugging information in files such as /proc/driver/udc @@ -70,7 +70,7 @@ config USB_GADGET_DEBUG_FILES config USB_GADGET_DEBUG_FS boolean "Debugging information files in debugfs (DEVELOPMENT)" - depends on USB_GADGET && DEBUG_FS + depends on DEBUG_FS help Some of the drivers in the "gadget" framework can expose debugging information in files under /sys/kernel/debug/. @@ -79,12 +79,36 @@ config USB_GADGET_DEBUG_FS Enable these files by choosing "Y" here. If in doubt, or to conserve kernel memory, say "N". +config USB_GADGET_VBUS_DRAW + int "Maximum VBUS Power usage (2-500 mA)" + range 2 500 + default 2 + help + Some devices need to draw power from USB when they are + configured, perhaps to operate circuitry or to recharge + batteries. This is in addition to any local power supply, + such as an AC adapter or batteries. + + Enter the maximum power your device draws through USB, in + milliAmperes. The permitted range of values is 2 - 500 mA; + 0 mA would be legal, but can make some hosts misbehave. + + This value will be used except for system-specific gadget + drivers that have more specific information. + config USB_GADGET_SELECTED boolean # # USB Peripheral Controller Support # +# The order here is alphabetical, except that integrated controllers go +# before discrete ones so they will be the initial/default value: +# - integrated/SOC controllers first +# - licensed IP used in both SOC and discrete versions +# - discrete ones (including all PCI-only controllers) +# - debug/dummy gadget+hcd is last. +# choice prompt "USB Peripheral Controller" depends on USB_GADGET @@ -94,26 +118,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 +# +# Integrated controllers +# + +config USB_GADGET_AT91 + boolean "Atmel AT91 USB Device Port" + depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 + select USB_GADGET_SELECTED 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. + Many Atmel AT91 processors (such as the AT91RM2000) have a + full speed USB Device Port with support for five configurable + endpoints (plus endpoint zero). Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "amd5536udc" and force all + dynamically linked module called "at91_udc" and force all gadget drivers to also be dynamically linked. -config USB_AMD5536UDC +config USB_AT91 tristate - depends on USB_GADGET_AMD5536UDC + depends on USB_GADGET_AT91 default USB_GADGET - select USB_GADGET_SELECTED config USB_GADGET_ATMEL_USBA boolean "Atmel USBA" @@ -150,28 +175,50 @@ config USB_FSL_USB2 default USB_GADGET select USB_GADGET_SELECTED -config USB_GADGET_NET2280 - boolean "NetChip 228x" - depends on PCI - select USB_GADGET_DUALSPEED +config USB_GADGET_LH7A40X + boolean "LH7A40X" + depends on ARCH_LH7A40X help - NetChip 2280 / 2282 is a PCI based USB peripheral controller which - supports both full and high speed USB 2.0 data transfers. - - It has six configurable endpoints, as well as endpoint zero - (for control transfers) and several endpoints with dedicated - functions. + This driver provides USB Device Controller driver for LH7A40x + +config USB_LH7A40X + tristate + depends on USB_GADGET_LH7A40X + default USB_GADGET + select USB_GADGET_SELECTED + +config USB_GADGET_OMAP + boolean "OMAP USB Device Controller" + depends on ARCH_OMAP + select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG + help + Many Texas Instruments OMAP processors have flexible full + speed USB device controllers, with support for up to 30 + endpoints (plus endpoint zero). This driver supports the + controller in the OMAP 1611, and should work with controllers + in other OMAP processors too, given minor tweaks. Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "net2280" and force all + dynamically linked module called "omap_udc" and force all gadget drivers to also be dynamically linked. -config USB_NET2280 +config USB_OMAP tristate - depends on USB_GADGET_NET2280 + depends on USB_GADGET_OMAP default USB_GADGET select USB_GADGET_SELECTED +config USB_OTG + boolean "OTG Support" + depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD + help + The most notable feature of USB OTG is support for a + "Dual-Role" device, which can act as either a device + or a host. The initial role choice can be changed + later, when two dual-role devices talk to each other. + + Select this only if your OMAP board has a Mini-AB connector. + config USB_GADGET_PXA25X boolean "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX @@ -203,34 +250,6 @@ config USB_PXA25X_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 SUPERH_BUILT_IN_M66592 - boolean "Enable SuperH built-in USB like the M66592" - depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722 - help - SH7722 has USB like the M66592. - - The transfer rate is very slow when use "Ethernet Gadget". - However, this problem is improved if change a value of - NET_IP_ALIGN to 4. - config USB_GADGET_PXA27X boolean "PXA 27x" depends on ARCH_PXA && PXA27x @@ -251,40 +270,32 @@ config USB_PXA27X default USB_GADGET select USB_GADGET_SELECTED -config USB_GADGET_GOKU - boolean "Toshiba TC86C001 'Goku-S'" - depends on PCI +config USB_GADGET_S3C2410 + boolean "S3C2410 USB Device Controller" + depends on ARCH_S3C2410 help - The Toshiba TC86C001 is a PCI device which includes controllers - for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI). - - The device controller has three configurable (bulk or interrupt) - endpoints, plus endpoint zero (for control transfers). + Samsung's S3C2410 is an ARM-4 processor with an integrated + full speed USB 1.1 device controller. It has 4 configurable + endpoints, as well as endpoint zero (for control transfers). - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "goku_udc" and to force all - gadget drivers to also be dynamically linked. + This driver has been tested on the S3C2410, S3C2412, and + S3C2440 processors. -config USB_GOKU +config USB_S3C2410 tristate - depends on USB_GADGET_GOKU + depends on USB_GADGET_S3C2410 default USB_GADGET select USB_GADGET_SELECTED +config USB_S3C2410_DEBUG + boolean "S3C2410 udc debug messages" + depends on USB_GADGET_S3C2410 -config USB_GADGET_LH7A40X - boolean "LH7A40X" - depends on ARCH_LH7A40X - help - This driver provides USB Device Controller driver for LH7A40x - -config USB_LH7A40X - tristate - depends on USB_GADGET_LH7A40X - default USB_GADGET - select USB_GADGET_SELECTED +# +# Controllers available in both integrated and discrete versions +# -# built in ../musb along with host support +# musb builds in ../musb along with host support config USB_GADGET_MUSB_HDRC boolean "Inventra HDRC USB Peripheral (TI, ...)" depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG) @@ -294,76 +305,124 @@ config USB_GADGET_MUSB_HDRC This OTG-capable silicon IP is used in dual designs including the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010. -config USB_GADGET_OMAP - boolean "OMAP USB Device Controller" - depends on ARCH_OMAP - select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 +config USB_GADGET_M66592 + boolean "Renesas M66592 USB Peripheral Controller" + select USB_GADGET_DUALSPEED help - Many Texas Instruments OMAP processors have flexible full - speed USB device controllers, with support for up to 30 - endpoints (plus endpoint zero). This driver supports the - controller in the OMAP 1611, and should work with controllers - in other OMAP processors too, given minor tweaks. + 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 "omap_udc" and force all + dynamically linked module called "m66592_udc" and force all gadget drivers to also be dynamically linked. -config USB_OMAP +config USB_M66592 tristate - depends on USB_GADGET_OMAP + depends on USB_GADGET_M66592 default USB_GADGET select USB_GADGET_SELECTED -config USB_OTG - boolean "OTG Support" - depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD +config SUPERH_BUILT_IN_M66592 + boolean "Enable SuperH built-in USB like the M66592" + depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722 help - The most notable feature of USB OTG is support for a - "Dual-Role" device, which can act as either a device - or a host. The initial role choice can be changed - later, when two dual-role devices talk to each other. + SH7722 has USB like the M66592. - Select this only if your OMAP board has a Mini-AB connector. + The transfer rate is very slow when use "Ethernet Gadget". + However, this problem is improved if change a value of + NET_IP_ALIGN to 4. -config USB_GADGET_S3C2410 - boolean "S3C2410 USB Device Controller" - depends on ARCH_S3C2410 +# +# Controllers available only in discrete form (and all PCI controllers) +# + +config USB_GADGET_AMD5536UDC + boolean "AMD5536 UDC" + depends on PCI + select USB_GADGET_DUALSPEED help - Samsung's S3C2410 is an ARM-4 processor with an integrated - full speed USB 1.1 device controller. It has 4 configurable - endpoints, as well as endpoint zero (for control transfers). + 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. - This driver has been tested on the S3C2410, S3C2412, and - S3C2440 processors. + 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_S3C2410 +config USB_AMD5536UDC tristate - depends on USB_GADGET_S3C2410 + depends on USB_GADGET_AMD5536UDC default USB_GADGET select USB_GADGET_SELECTED -config USB_S3C2410_DEBUG - boolean "S3C2410 udc debug messages" - depends on USB_GADGET_S3C2410 +config USB_GADGET_FSL_QE + boolean "Freescale QE/CPM USB Device Controller" + depends on FSL_SOC && (QUICC_ENGINE || CPM) + help + Some of Freescale PowerPC processors have a Full Speed + QE/CPM2 USB controller, which support device mode with 4 + programmable endpoints. This driver supports the + controller in the MPC8360 and MPC8272, and should work with + controllers having QE or CPM2, given minor tweaks. -config USB_GADGET_AT91 - boolean "AT91 USB Device Port" - depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 + Set CONFIG_USB_GADGET to "m" to build this driver as a + dynmically linked module called "fsl_qe_udc". + +config USB_FSL_QE + tristate + depends on USB_GADGET_FSL_QE + default USB_GADGET select USB_GADGET_SELECTED + +config USB_GADGET_NET2280 + boolean "NetChip 228x" + depends on PCI + select USB_GADGET_DUALSPEED help - Many Atmel AT91 processors (such as the AT91RM2000) have a - full speed USB Device Port with support for five configurable - endpoints (plus endpoint zero). + NetChip 2280 / 2282 is a PCI based USB peripheral controller which + supports both full and high speed USB 2.0 data transfers. + + It has six configurable endpoints, as well as endpoint zero + (for control transfers) and several endpoints with dedicated + functions. Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "at91_udc" and force all + dynamically linked module called "net2280" and force all gadget drivers to also be dynamically linked. -config USB_AT91 +config USB_NET2280 tristate - depends on USB_GADGET_AT91 + depends on USB_GADGET_NET2280 + default USB_GADGET + select USB_GADGET_SELECTED + +config USB_GADGET_GOKU + boolean "Toshiba TC86C001 'Goku-S'" + depends on PCI + help + The Toshiba TC86C001 is a PCI device which includes controllers + for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI). + + The device controller has three configurable (bulk or interrupt) + endpoints, plus endpoint zero (for control transfers). + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "goku_udc" and to force all + gadget drivers to also be dynamically linked. + +config USB_GOKU + tristate + depends on USB_GADGET_GOKU default USB_GADGET + select USB_GADGET_SELECTED + + +# +# LAST -- dummy/emulated controller +# config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" @@ -553,19 +612,23 @@ config USB_FILE_STORAGE_TEST normal operation. config USB_G_SERIAL - tristate "Serial Gadget (with CDC ACM support)" + tristate "Serial Gadget (with CDC ACM and CDC OBEX support)" help The Serial Gadget talks to the Linux-USB generic serial driver. This driver supports a CDC-ACM module option, which can be used to interoperate with MS-Windows hosts or with the Linux-USB "cdc-acm" driver. + This driver also supports a CDC-OBEX option. You will need a + user space OBEX server talking to /dev/ttyGS*, since the kernel + itself doesn't implement the OBEX protocol. + Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_serial". For more information, see Documentation/usb/gadget_serial.txt which includes instructions and a "driver info file" needed to - make MS-Windows work with this driver. + make MS-Windows work with CDC ACM. config USB_MIDI_GADGET tristate "MIDI Gadget (EXPERIMENTAL)" diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index fcb5cb9094d9..bd4041b47dce 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -18,28 +18,20 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o obj-$(CONFIG_USB_M66592) += m66592-udc.o +obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o # # USB gadget drivers # -C_UTILS = composite.o usbstring.o config.o epautoconf.o - -g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS) -g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS) -g_serial-objs := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS) -g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o +g_zero-objs := zero.o +g_ether-objs := ether.o +g_serial-objs := serial.o +g_midi-objs := gmidi.o gadgetfs-objs := inode.o -g_file_storage-objs := file_storage.o usbstring.o config.o \ - epautoconf.o -g_printer-objs := printer.o usbstring.o config.o \ - epautoconf.o -g_cdc-objs := cdc2.o u_ether.o f_ecm.o \ - u_serial.o f_acm.o $(C_UTILS) +g_file_storage-objs := file_storage.o +g_printer-objs := printer.o +g_cdc-objs := cdc2.o -ifeq ($(CONFIG_USB_ETH_RNDIS),y) - g_ether-objs += f_rndis.o rndis.o -endif - obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_ETH) += g_ether.o obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index a39a4b940c33..5495b171cf29 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -43,6 +43,25 @@ /*-------------------------------------------------------------------------*/ +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ + +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" +#include "u_serial.c" +#include "f_acm.c" +#include "f_ecm.c" +#include "u_ether.c" + +/*-------------------------------------------------------------------------*/ + static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -136,7 +155,6 @@ static struct usb_configuration cdc_config_driver = { .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* 2 mA, minimal */ }; /*-------------------------------------------------------------------------*/ @@ -148,7 +166,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) int status; if (!can_support_ecm(cdev->gadget)) { - ERROR(cdev, "controller '%s' not usable\n", gadget->name); + dev_err(&gadget->dev, "controller '%s' not usable\n", + gadget->name); return -EINVAL; } @@ -203,7 +222,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail1; - INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); + dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", + DRIVER_DESC); return 0; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 85c876c1f150..f2da0269e1b1 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -128,6 +128,70 @@ done: } /** + * usb_function_deactivate - prevent function and gadget enumeration + * @function: the function that isn't yet ready to respond + * + * Blocks response of the gadget driver to host enumeration by + * preventing the data line pullup from being activated. This is + * normally called during @bind() processing to change from the + * initial "ready to respond" state, or when a required resource + * becomes available. + * + * For example, drivers that serve as a passthrough to a userspace + * daemon can block enumeration unless that daemon (such as an OBEX, + * MTP, or print server) is ready to handle host requests. + * + * Not all systems support software control of their USB peripheral + * data pullups. + * + * Returns zero on success, else negative errno. + */ +int usb_function_deactivate(struct usb_function *function) +{ + struct usb_composite_dev *cdev = function->config->cdev; + int status = 0; + + spin_lock(&cdev->lock); + + if (cdev->deactivations == 0) + status = usb_gadget_disconnect(cdev->gadget); + if (status == 0) + cdev->deactivations++; + + spin_unlock(&cdev->lock); + return status; +} + +/** + * usb_function_activate - allow function and gadget enumeration + * @function: function on which usb_function_activate() was called + * + * Reverses effect of usb_function_deactivate(). If no more functions + * are delaying their activation, the gadget driver will respond to + * host enumeration procedures. + * + * Returns zero on success, else negative errno. + */ +int usb_function_activate(struct usb_function *function) +{ + struct usb_composite_dev *cdev = function->config->cdev; + int status = 0; + + spin_lock(&cdev->lock); + + if (WARN_ON(cdev->deactivations == 0)) + status = -EINVAL; + else { + cdev->deactivations--; + if (cdev->deactivations == 0) + status = usb_gadget_connect(cdev->gadget); + } + + spin_unlock(&cdev->lock); + return status; +} + +/** * usb_interface_id() - allocate an unused interface ID * @config: configuration associated with the interface * @function: function handling the interface @@ -181,7 +245,7 @@ static int config_buf(struct usb_configuration *config, c->bConfigurationValue = config->bConfigurationValue; c->iConfiguration = config->iConfiguration; c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; - c->bMaxPower = config->bMaxPower; + c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2); /* There may be e.g. OTG descriptors */ if (config->descriptors) { @@ -368,7 +432,7 @@ static int set_config(struct usb_composite_dev *cdev, } /* when we return, be sure our power usage is valid */ - power = 2 * c->bMaxPower; + power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; done: usb_gadget_vbus_draw(gadget, power); return result; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 7600a0c78753..9064696636ac 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -82,6 +82,7 @@ struct dummy_ep { const struct usb_endpoint_descriptor *desc; struct usb_ep ep; unsigned halted : 1; + unsigned wedged : 1; unsigned already_seen : 1; unsigned setup_stage : 1; }; @@ -436,6 +437,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) /* at this point real hardware should be NAKing transfers * to that endpoint, until a buffer is queued to it. */ + ep->halted = ep->wedged = 0; retval = 0; done: return retval; @@ -597,7 +599,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) } static int -dummy_set_halt (struct usb_ep *_ep, int value) +dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged) { struct dummy_ep *ep; struct dummy *dum; @@ -609,16 +611,32 @@ dummy_set_halt (struct usb_ep *_ep, int value) if (!dum->driver) return -ESHUTDOWN; if (!value) - ep->halted = 0; + ep->halted = ep->wedged = 0; else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && !list_empty (&ep->queue)) return -EAGAIN; - else + else { ep->halted = 1; + if (wedged) + ep->wedged = 1; + } /* FIXME clear emulated data toggle too */ return 0; } +static int +dummy_set_halt(struct usb_ep *_ep, int value) +{ + return dummy_set_halt_and_wedge(_ep, value, 0); +} + +static int dummy_set_wedge(struct usb_ep *_ep) +{ + if (!_ep || _ep->name == ep0name) + return -EINVAL; + return dummy_set_halt_and_wedge(_ep, 1, 1); +} + static const struct usb_ep_ops dummy_ep_ops = { .enable = dummy_enable, .disable = dummy_disable, @@ -630,6 +648,7 @@ static const struct usb_ep_ops dummy_ep_ops = { .dequeue = dummy_dequeue, .set_halt = dummy_set_halt, + .set_wedge = dummy_set_wedge, }; /*-------------------------------------------------------------------------*/ @@ -760,7 +779,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) ep->ep.name = ep_name [i]; ep->ep.ops = &dummy_ep_ops; list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list); - ep->halted = ep->already_seen = ep->setup_stage = 0; + ep->halted = ep->wedged = ep->already_seen = + ep->setup_stage = 0; ep->ep.maxpacket = ~0; ep->last_io = jiffies; ep->gadget = &dum->gadget; @@ -1351,7 +1371,7 @@ restart: } else if (setup.bRequestType == Ep_Request) { // endpoint halt ep2 = find_endpoint (dum, w_index); - if (!ep2) { + if (!ep2 || ep2->ep.name == ep0name) { value = -EOPNOTSUPP; break; } @@ -1380,7 +1400,8 @@ restart: value = -EOPNOTSUPP; break; } - ep2->halted = 0; + if (!ep2->wedged) + ep2->halted = 0; value = 0; status = 0; } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index bcac2e68660d..37252d0012a7 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -96,6 +96,28 @@ static inline bool has_rndis(void) /*-------------------------------------------------------------------------*/ +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +#include "f_ecm.c" +#include "f_subset.c" +#ifdef CONFIG_USB_ETH_RNDIS +#include "f_rndis.c" +#include "rndis.c" +#endif +#include "u_ether.c" + +/*-------------------------------------------------------------------------*/ + /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! * Instead: allocate your own, using normal USB-IF procedures. */ @@ -220,7 +242,6 @@ static struct usb_configuration rndis_config_driver = { .bConfigurationValue = 2, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* 2 mA, minimal */ }; /*-------------------------------------------------------------------------*/ @@ -249,7 +270,6 @@ static struct usb_configuration eth_config_driver = { .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* 2 mA, minimal */ }; /*-------------------------------------------------------------------------*/ @@ -293,7 +313,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev) * but if the controller isn't recognized at all then * that assumption is a bit more likely to be wrong. */ - WARNING(cdev, "controller '%s' not recognized; trying %s\n", + dev_warn(&gadget->dev, + "controller '%s' not recognized; trying %s\n", gadget->name, eth_config_driver.label); device_desc.bcdDevice = @@ -332,7 +353,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail; - INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); + dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", + DRIVER_DESC); return 0; diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index a2b5c092bda0..4ae579948e54 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -83,7 +83,7 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f) } /* peak (theoretical) bulk transfer rate in bits-per-second */ -static inline unsigned bitrate(struct usb_gadget *g) +static inline unsigned ecm_bitrate(struct usb_gadget *g) { if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) return 13 * 512 * 8 * 1000 * 8; @@ -107,7 +107,7 @@ static inline unsigned bitrate(struct usb_gadget *g) */ #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ -#define STATUS_BYTECOUNT 16 /* 8 byte header + data */ +#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ /* interface descriptor: */ @@ -125,8 +125,8 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = { /* .iInterface = DYNAMIC */ }; -static struct usb_cdc_header_desc header_desc __initdata = { - .bLength = sizeof header_desc, +static struct usb_cdc_header_desc ecm_header_desc __initdata = { + .bLength = sizeof ecm_header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, @@ -141,8 +141,8 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = { /* .bSlaveInterface0 = DYNAMIC */ }; -static struct usb_cdc_ether_desc ether_desc __initdata = { - .bLength = sizeof ether_desc, +static struct usb_cdc_ether_desc ecm_desc __initdata = { + .bLength = sizeof ecm_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, @@ -186,17 +186,17 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = { /* full speed support: */ -static struct usb_endpoint_descriptor fs_notify_desc __initdata = { +static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; -static struct usb_endpoint_descriptor fs_in_desc __initdata = { +static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -204,7 +204,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor fs_out_desc __initdata = { +static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -212,34 +212,34 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_descriptor_header *eth_fs_function[] __initdata = { +static struct usb_descriptor_header *ecm_fs_function[] __initdata = { /* CDC ECM control descriptors */ (struct usb_descriptor_header *) &ecm_control_intf, - (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &ecm_header_desc, (struct usb_descriptor_header *) &ecm_union_desc, - (struct usb_descriptor_header *) ðer_desc, + (struct usb_descriptor_header *) &ecm_desc, /* NOTE: status endpoint might need to be removed */ - (struct usb_descriptor_header *) &fs_notify_desc, + (struct usb_descriptor_header *) &fs_ecm_notify_desc, /* data interface, altsettings 0 and 1 */ (struct usb_descriptor_header *) &ecm_data_nop_intf, (struct usb_descriptor_header *) &ecm_data_intf, - (struct usb_descriptor_header *) &fs_in_desc, - (struct usb_descriptor_header *) &fs_out_desc, + (struct usb_descriptor_header *) &fs_ecm_in_desc, + (struct usb_descriptor_header *) &fs_ecm_out_desc, NULL, }; /* high speed support: */ -static struct usb_endpoint_descriptor hs_notify_desc __initdata = { +static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; -static struct usb_endpoint_descriptor hs_in_desc __initdata = { +static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = { .wMaxPacketSize = __constant_cpu_to_le16(512), }; -static struct usb_endpoint_descriptor hs_out_desc __initdata = { +static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -257,19 +257,19 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { .wMaxPacketSize = __constant_cpu_to_le16(512), }; -static struct usb_descriptor_header *eth_hs_function[] __initdata = { +static struct usb_descriptor_header *ecm_hs_function[] __initdata = { /* CDC ECM control descriptors */ (struct usb_descriptor_header *) &ecm_control_intf, - (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &ecm_header_desc, (struct usb_descriptor_header *) &ecm_union_desc, - (struct usb_descriptor_header *) ðer_desc, + (struct usb_descriptor_header *) &ecm_desc, /* NOTE: status endpoint might need to be removed */ - (struct usb_descriptor_header *) &hs_notify_desc, + (struct usb_descriptor_header *) &hs_ecm_notify_desc, /* data interface, altsettings 0 and 1 */ (struct usb_descriptor_header *) &ecm_data_nop_intf, (struct usb_descriptor_header *) &ecm_data_intf, - (struct usb_descriptor_header *) &hs_in_desc, - (struct usb_descriptor_header *) &hs_out_desc, + (struct usb_descriptor_header *) &hs_ecm_in_desc, + (struct usb_descriptor_header *) &hs_ecm_out_desc, NULL, }; @@ -329,14 +329,14 @@ static void ecm_do_notify(struct f_ecm *ecm) event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; event->wValue = cpu_to_le16(0); event->wLength = cpu_to_le16(8); - req->length = STATUS_BYTECOUNT; + req->length = ECM_STATUS_BYTECOUNT; /* SPEED_CHANGE data is up/down speeds in bits/sec */ data = req->buf + sizeof *event; - data[0] = cpu_to_le32(bitrate(cdev->gadget)); + data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget)); data[1] = data[0]; - DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget)); + DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget)); ecm->notify_state = ECM_NOTIFY_NONE; break; } @@ -628,13 +628,13 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) status = -ENODEV; /* allocate instance-specific endpoints */ - ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); + ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc); if (!ep) goto fail; ecm->port.in_ep = ep; ep->driver_data = cdev; /* claim */ - ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); + ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc); if (!ep) goto fail; ecm->port.out_ep = ep; @@ -644,7 +644,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) * don't treat it that way. It's simpler, and some newer CDC * profiles (wireless handsets) no longer treat it as optional. */ - ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc); + ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc); if (!ep) goto fail; ecm->notify = ep; @@ -656,47 +656,47 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); if (!ecm->notify_req) goto fail; - ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL); + ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL); if (!ecm->notify_req->buf) goto fail; ecm->notify_req->context = ecm; ecm->notify_req->complete = ecm_notify_complete; /* copy descriptors, and track endpoint copies */ - f->descriptors = usb_copy_descriptors(eth_fs_function); + f->descriptors = usb_copy_descriptors(ecm_fs_function); if (!f->descriptors) goto fail; - ecm->fs.in = usb_find_endpoint(eth_fs_function, - f->descriptors, &fs_in_desc); - ecm->fs.out = usb_find_endpoint(eth_fs_function, - f->descriptors, &fs_out_desc); - ecm->fs.notify = usb_find_endpoint(eth_fs_function, - f->descriptors, &fs_notify_desc); + ecm->fs.in = usb_find_endpoint(ecm_fs_function, + f->descriptors, &fs_ecm_in_desc); + ecm->fs.out = usb_find_endpoint(ecm_fs_function, + f->descriptors, &fs_ecm_out_desc); + ecm->fs.notify = usb_find_endpoint(ecm_fs_function, + f->descriptors, &fs_ecm_notify_desc); /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ if (gadget_is_dualspeed(c->cdev->gadget)) { - hs_in_desc.bEndpointAddress = - fs_in_desc.bEndpointAddress; - hs_out_desc.bEndpointAddress = - fs_out_desc.bEndpointAddress; - hs_notify_desc.bEndpointAddress = - fs_notify_desc.bEndpointAddress; + hs_ecm_in_desc.bEndpointAddress = + fs_ecm_in_desc.bEndpointAddress; + hs_ecm_out_desc.bEndpointAddress = + fs_ecm_out_desc.bEndpointAddress; + hs_ecm_notify_desc.bEndpointAddress = + fs_ecm_notify_desc.bEndpointAddress; /* copy descriptors, and track endpoint copies */ - f->hs_descriptors = usb_copy_descriptors(eth_hs_function); + f->hs_descriptors = usb_copy_descriptors(ecm_hs_function); if (!f->hs_descriptors) goto fail; - ecm->hs.in = usb_find_endpoint(eth_hs_function, - f->hs_descriptors, &hs_in_desc); - ecm->hs.out = usb_find_endpoint(eth_hs_function, - f->hs_descriptors, &hs_out_desc); - ecm->hs.notify = usb_find_endpoint(eth_hs_function, - f->hs_descriptors, &hs_notify_desc); + ecm->hs.in = usb_find_endpoint(ecm_hs_function, + f->hs_descriptors, &hs_ecm_in_desc); + ecm->hs.out = usb_find_endpoint(ecm_hs_function, + f->hs_descriptors, &hs_ecm_out_desc); + ecm->hs.notify = usb_find_endpoint(ecm_hs_function, + f->hs_descriptors, &hs_ecm_notify_desc); } /* NOTE: all that is done without knowing or caring about @@ -795,7 +795,7 @@ int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) if (status < 0) return status; ecm_string_defs[1].id = status; - ether_desc.iMACAddress = status; + ecm_desc.iMACAddress = status; } /* allocate and initialize one new instance */ diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index eda4cde72c82..8affe1dfc2c1 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -70,7 +70,7 @@ static struct usb_interface_descriptor loopback_intf = { /* full speed support: */ -static struct usb_endpoint_descriptor fs_source_desc = { +static struct usb_endpoint_descriptor fs_loop_source_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -78,7 +78,7 @@ static struct usb_endpoint_descriptor fs_source_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor fs_sink_desc = { +static struct usb_endpoint_descriptor fs_loop_sink_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -88,14 +88,14 @@ static struct usb_endpoint_descriptor fs_sink_desc = { static struct usb_descriptor_header *fs_loopback_descs[] = { (struct usb_descriptor_header *) &loopback_intf, - (struct usb_descriptor_header *) &fs_sink_desc, - (struct usb_descriptor_header *) &fs_source_desc, + (struct usb_descriptor_header *) &fs_loop_sink_desc, + (struct usb_descriptor_header *) &fs_loop_source_desc, NULL, }; /* high speed support: */ -static struct usb_endpoint_descriptor hs_source_desc = { +static struct usb_endpoint_descriptor hs_loop_source_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -103,7 +103,7 @@ static struct usb_endpoint_descriptor hs_source_desc = { .wMaxPacketSize = __constant_cpu_to_le16(512), }; -static struct usb_endpoint_descriptor hs_sink_desc = { +static struct usb_endpoint_descriptor hs_loop_sink_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -113,8 +113,8 @@ static struct usb_endpoint_descriptor hs_sink_desc = { static struct usb_descriptor_header *hs_loopback_descs[] = { (struct usb_descriptor_header *) &loopback_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, + (struct usb_descriptor_header *) &hs_loop_source_desc, + (struct usb_descriptor_header *) &hs_loop_sink_desc, NULL, }; @@ -152,7 +152,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f) /* allocate endpoints */ - loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); + loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc); if (!loop->in_ep) { autoconf_fail: ERROR(cdev, "%s: can't autoconfigure on %s\n", @@ -161,17 +161,17 @@ autoconf_fail: } loop->in_ep->driver_data = cdev; /* claim */ - loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc); + loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc); if (!loop->out_ep) goto autoconf_fail; loop->out_ep->driver_data = cdev; /* claim */ /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { - hs_source_desc.bEndpointAddress = - fs_source_desc.bEndpointAddress; - hs_sink_desc.bEndpointAddress = - fs_sink_desc.bEndpointAddress; + hs_loop_source_desc.bEndpointAddress = + fs_loop_source_desc.bEndpointAddress; + hs_loop_sink_desc.bEndpointAddress = + fs_loop_sink_desc.bEndpointAddress; f->hs_descriptors = hs_loopback_descs; } @@ -255,8 +255,10 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) struct usb_request *req; unsigned i; - src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc); - sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc); + src = ep_choose(cdev->gadget, + &hs_loop_source_desc, &fs_loop_source_desc); + sink = ep_choose(cdev->gadget, + &hs_loop_sink_desc, &fs_loop_sink_desc); /* one endpoint writes data back IN to the host */ ep = loop->in_ep; @@ -350,7 +352,6 @@ static struct usb_configuration loopback_driver = { .bind = loopback_bind_config, .bConfigurationValue = 2, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* 2 mA, minimal */ /* .iConfiguration = DYNAMIC */ }; diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c new file mode 100644 index 000000000000..80c2e7e9622f --- /dev/null +++ b/drivers/usb/gadget/f_obex.c @@ -0,0 +1,493 @@ +/* + * f_obex.c -- USB CDC OBEX function driver + * + * Copyright (C) 2008 Nokia Corporation + * Contact: Felipe Balbi <felipe.balbi@nokia.com> + * + * Based on f_acm.c by Al Borchers and David Brownell. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include <linux/kernel.h> +#include <linux/utsname.h> +#include <linux/device.h> + +#include "u_serial.h" +#include "gadget_chips.h" + + +/* + * This CDC OBEX function support just packages a TTY-ish byte stream. + * A user mode server will put it into "raw" mode and handle all the + * relevant protocol details ... this is just a kernel passthrough. + * When possible, we prevent gadget enumeration until that server is + * ready to handle the commands. + */ + +struct obex_ep_descs { + struct usb_endpoint_descriptor *obex_in; + struct usb_endpoint_descriptor *obex_out; +}; + +struct f_obex { + struct gserial port; + u8 ctrl_id; + u8 data_id; + u8 port_num; + u8 can_activate; + + struct obex_ep_descs fs; + struct obex_ep_descs hs; +}; + +static inline struct f_obex *func_to_obex(struct usb_function *f) +{ + return container_of(f, struct f_obex, port.func); +} + +static inline struct f_obex *port_to_obex(struct gserial *p) +{ + return container_of(p, struct f_obex, port); +} + +/*-------------------------------------------------------------------------*/ + +#define OBEX_CTRL_IDX 0 +#define OBEX_DATA_IDX 1 + +static struct usb_string obex_string_defs[] = { + [OBEX_CTRL_IDX].s = "CDC Object Exchange (OBEX)", + [OBEX_DATA_IDX].s = "CDC OBEX Data", + { }, /* end of list */ +}; + +static struct usb_gadget_strings obex_string_table = { + .language = 0x0409, /* en-US */ + .strings = obex_string_defs, +}; + +static struct usb_gadget_strings *obex_strings[] = { + &obex_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static struct usb_interface_descriptor obex_control_intf __initdata = { + .bLength = sizeof(obex_control_intf), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX, +}; + +static struct usb_interface_descriptor obex_data_nop_intf __initdata = { + .bLength = sizeof(obex_data_nop_intf), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_CDC_DATA, +}; + +static struct usb_interface_descriptor obex_data_intf __initdata = { + .bLength = sizeof(obex_data_intf), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 2, + + .bAlternateSetting = 1, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, +}; + +static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { + .bLength = sizeof(obex_cdc_header_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + .bcdCDC = __constant_cpu_to_le16(0x0120), +}; + +static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { + .bLength = sizeof(obex_cdc_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + .bMasterInterface0 = 1, + .bSlaveInterface0 = 2, +}; + +static struct usb_cdc_obex_desc obex_desc __initdata = { + .bLength = sizeof(obex_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_OBEX_TYPE, + .bcdVersion = __constant_cpu_to_le16(0x0100), +}; + +/* High-Speed Support */ + +static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static struct usb_descriptor_header *hs_function[] __initdata = { + (struct usb_descriptor_header *) &obex_control_intf, + (struct usb_descriptor_header *) &obex_cdc_header_desc, + (struct usb_descriptor_header *) &obex_desc, + (struct usb_descriptor_header *) &obex_cdc_union_desc, + + (struct usb_descriptor_header *) &obex_data_nop_intf, + (struct usb_descriptor_header *) &obex_data_intf, + (struct usb_descriptor_header *) &obex_hs_ep_in_desc, + (struct usb_descriptor_header *) &obex_hs_ep_out_desc, + NULL, +}; + +/* Full-Speed Support */ + +static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *fs_function[] __initdata = { + (struct usb_descriptor_header *) &obex_control_intf, + (struct usb_descriptor_header *) &obex_cdc_header_desc, + (struct usb_descriptor_header *) &obex_desc, + (struct usb_descriptor_header *) &obex_cdc_union_desc, + + (struct usb_descriptor_header *) &obex_data_nop_intf, + (struct usb_descriptor_header *) &obex_data_intf, + (struct usb_descriptor_header *) &obex_fs_ep_in_desc, + (struct usb_descriptor_header *) &obex_fs_ep_out_desc, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_obex *obex = func_to_obex(f); + struct usb_composite_dev *cdev = f->config->cdev; + + if (intf == obex->ctrl_id) { + if (alt != 0) + goto fail; + /* NOP */ + DBG(cdev, "reset obex ttyGS%d control\n", obex->port_num); + + } else if (intf == obex->data_id) { + if (alt > 1) + goto fail; + + if (obex->port.in->driver_data) { + DBG(cdev, "reset obex ttyGS%d\n", obex->port_num); + gserial_disconnect(&obex->port); + } + + if (!obex->port.in_desc) { + DBG(cdev, "init obex ttyGS%d\n", obex->port_num); + obex->port.in_desc = ep_choose(cdev->gadget, + obex->hs.obex_in, obex->fs.obex_in); + obex->port.out_desc = ep_choose(cdev->gadget, + obex->hs.obex_out, obex->fs.obex_out); + } + + if (alt == 1) { + DBG(cdev, "activate obex ttyGS%d\n", obex->port_num); + gserial_connect(&obex->port, obex->port_num); + } + + } else + goto fail; + + return 0; + +fail: + return -EINVAL; +} + +static int obex_get_alt(struct usb_function *f, unsigned intf) +{ + struct f_obex *obex = func_to_obex(f); + + if (intf == obex->ctrl_id) + return 0; + + return obex->port.in->driver_data ? 1 : 0; +} + +static void obex_disable(struct usb_function *f) +{ + struct f_obex *obex = func_to_obex(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "obex ttyGS%d disable\n", obex->port_num); + gserial_disconnect(&obex->port); +} + +/*-------------------------------------------------------------------------*/ + +static void obex_connect(struct gserial *g) +{ + struct f_obex *obex = port_to_obex(g); + struct usb_composite_dev *cdev = g->func.config->cdev; + int status; + + if (!obex->can_activate) + return; + + status = usb_function_activate(&g->func); + if (status) + DBG(cdev, "obex ttyGS%d function activate --> %d\n", + obex->port_num, status); +} + +static void obex_disconnect(struct gserial *g) +{ + struct f_obex *obex = port_to_obex(g); + struct usb_composite_dev *cdev = g->func.config->cdev; + int status; + + if (!obex->can_activate) + return; + + status = usb_function_deactivate(&g->func); + if (status) + DBG(cdev, "obex ttyGS%d function deactivate --> %d\n", + obex->port_num, status); +} + +/*-------------------------------------------------------------------------*/ + +static int __init +obex_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_obex *obex = func_to_obex(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs, and patch descriptors */ + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + obex->ctrl_id = status; + + obex_control_intf.bInterfaceNumber = status; + obex_cdc_union_desc.bMasterInterface0 = status; + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + obex->data_id = status; + + obex_data_nop_intf.bInterfaceNumber = status; + obex_data_intf.bInterfaceNumber = status; + obex_cdc_union_desc.bSlaveInterface0 = status; + + /* allocate instance-specific endpoints */ + + ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc); + if (!ep) + goto fail; + obex->port.in = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc); + if (!ep) + goto fail; + obex->port.out = ep; + ep->driver_data = cdev; /* claim */ + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(fs_function); + + obex->fs.obex_in = usb_find_endpoint(fs_function, + f->descriptors, &obex_fs_ep_in_desc); + obex->fs.obex_out = usb_find_endpoint(fs_function, + f->descriptors, &obex_fs_ep_out_desc); + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + + obex_hs_ep_in_desc.bEndpointAddress = + obex_fs_ep_in_desc.bEndpointAddress; + obex_hs_ep_out_desc.bEndpointAddress = + obex_fs_ep_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(hs_function); + + obex->hs.obex_in = usb_find_endpoint(hs_function, + f->descriptors, &obex_hs_ep_in_desc); + obex->hs.obex_out = usb_find_endpoint(hs_function, + f->descriptors, &obex_hs_ep_out_desc); + } + + /* Avoid letting this gadget enumerate until the userspace + * OBEX server is active. + */ + status = usb_function_deactivate(f); + if (status < 0) + WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n", + obex->port_num, status); + else + obex->can_activate = true; + + + DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", + obex->port_num, + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + obex->port.in->name, obex->port.out->name); + + return 0; + +fail: + /* we might as well release our claims on endpoints */ + if (obex->port.out) + obex->port.out->driver_data = NULL; + if (obex->port.in) + obex->port.in->driver_data = NULL; + + ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); + + return status; +} + +static void +obex_unbind(struct usb_configuration *c, struct usb_function *f) +{ + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + kfree(func_to_obex(f)); +} + +/* Some controllers can't support CDC OBEX ... */ +static inline bool can_support_obex(struct usb_configuration *c) +{ + /* Since the first interface is a NOP, we can ignore the + * issue of multi-interface support on most controllers. + * + * Altsettings are mandatory, however... + */ + if (!gadget_supports_altsettings(c->cdev->gadget)) + return false; + + /* everything else is *probably* fine ... */ + return true; +} + +/** + * obex_bind_config - add a CDC OBEX function to a configuration + * @c: the configuration to support the CDC OBEX instance + * @port_num: /dev/ttyGS* port this interface will use + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gserial_setup() with enough ports to + * handle all the ones it binds. Caller is also responsible + * for calling @gserial_cleanup() before module unload. + */ +int __init obex_bind_config(struct usb_configuration *c, u8 port_num) +{ + struct f_obex *obex; + int status; + + if (!can_support_obex(c)) + return -EINVAL; + + /* maybe allocate device-global string IDs, and patch descriptors */ + if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { + status = usb_string_id(c->cdev); + if (status < 0) + return status; + obex_string_defs[OBEX_CTRL_IDX].id = status; + + obex_control_intf.iInterface = status; + + status = usb_string_id(c->cdev); + if (status < 0) + return status; + obex_string_defs[OBEX_DATA_IDX].id = status; + + obex_data_nop_intf.iInterface = + obex_data_intf.iInterface = status; + } + + /* allocate and initialize one new instance */ + obex = kzalloc(sizeof *obex, GFP_KERNEL); + if (!obex) + return -ENOMEM; + + obex->port_num = port_num; + + obex->port.connect = obex_connect; + obex->port.disconnect = obex_disconnect; + + obex->port.func.name = "obex"; + obex->port.func.strings = obex_strings; + /* descriptors are per-instance copies */ + obex->port.func.bind = obex_bind; + obex->port.func.unbind = obex_unbind; + obex->port.func.set_alt = obex_set_alt; + obex->port.func.get_alt = obex_get_alt; + obex->port.func.disable = obex_disable; + + status = usb_add_function(c, &obex->port.func); + if (status) + kfree(obex); + + return status; +} + +MODULE_AUTHOR("Felipe Balbi"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index f18c3a14d72a..dc84d26d2835 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -552,7 +552,6 @@ static struct usb_configuration sourcesink_driver = { .setup = sourcesink_setup, .bConfigurationValue = 3, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* 2 mA, minimal */ /* .iConfiguration = DYNAMIC */ }; diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index acb8d233aa1d..fe1832875771 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -103,8 +103,8 @@ static struct usb_interface_descriptor subset_data_intf __initdata = { /* .iInterface = DYNAMIC */ }; -static struct usb_cdc_header_desc header_desc __initdata = { - .bLength = sizeof header_desc, +static struct usb_cdc_header_desc mdlm_header_desc __initdata = { + .bLength = sizeof mdlm_header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, @@ -152,7 +152,7 @@ static struct usb_cdc_ether_desc ether_desc __initdata = { /* full speed support: */ -static struct usb_endpoint_descriptor fs_in_desc __initdata = { +static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -160,7 +160,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor fs_out_desc __initdata = { +static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -170,18 +170,18 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = { static struct usb_descriptor_header *fs_eth_function[] __initdata = { (struct usb_descriptor_header *) &subset_data_intf, - (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &mdlm_header_desc, (struct usb_descriptor_header *) &mdlm_desc, (struct usb_descriptor_header *) &mdlm_detail_desc, (struct usb_descriptor_header *) ðer_desc, - (struct usb_descriptor_header *) &fs_in_desc, - (struct usb_descriptor_header *) &fs_out_desc, + (struct usb_descriptor_header *) &fs_subset_in_desc, + (struct usb_descriptor_header *) &fs_subset_out_desc, NULL, }; /* high speed support: */ -static struct usb_endpoint_descriptor hs_in_desc __initdata = { +static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -189,7 +189,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = { .wMaxPacketSize = __constant_cpu_to_le16(512), }; -static struct usb_endpoint_descriptor hs_out_desc __initdata = { +static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -199,12 +199,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { static struct usb_descriptor_header *hs_eth_function[] __initdata = { (struct usb_descriptor_header *) &subset_data_intf, - (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &mdlm_header_desc, (struct usb_descriptor_header *) &mdlm_desc, (struct usb_descriptor_header *) &mdlm_detail_desc, (struct usb_descriptor_header *) ðer_desc, - (struct usb_descriptor_header *) &hs_in_desc, - (struct usb_descriptor_header *) &hs_out_desc, + (struct usb_descriptor_header *) &hs_subset_in_desc, + (struct usb_descriptor_header *) &hs_subset_out_desc, NULL, }; @@ -281,13 +281,13 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) status = -ENODEV; /* allocate instance-specific endpoints */ - ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); + ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_in_desc); if (!ep) goto fail; geth->port.in_ep = ep; ep->driver_data = cdev; /* claim */ - ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); + ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc); if (!ep) goto fail; geth->port.out_ep = ep; @@ -297,9 +297,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) f->descriptors = usb_copy_descriptors(fs_eth_function); geth->fs.in = usb_find_endpoint(fs_eth_function, - f->descriptors, &fs_in_desc); + f->descriptors, &fs_subset_in_desc); geth->fs.out = usb_find_endpoint(fs_eth_function, - f->descriptors, &fs_out_desc); + f->descriptors, &fs_subset_out_desc); /* support all relevant hardware speeds... we expect that when @@ -307,18 +307,18 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) * both speeds */ if (gadget_is_dualspeed(c->cdev->gadget)) { - hs_in_desc.bEndpointAddress = - fs_in_desc.bEndpointAddress; - hs_out_desc.bEndpointAddress = - fs_out_desc.bEndpointAddress; + hs_subset_in_desc.bEndpointAddress = + fs_subset_in_desc.bEndpointAddress; + hs_subset_out_desc.bEndpointAddress = + fs_subset_out_desc.bEndpointAddress; /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(hs_eth_function); geth->hs.in = usb_find_endpoint(hs_eth_function, - f->hs_descriptors, &hs_in_desc); + f->hs_descriptors, &hs_subset_in_desc); geth->hs.out = usb_find_endpoint(hs_eth_function, - f->hs_descriptors, &hs_out_desc); + f->hs_descriptors, &hs_subset_out_desc); } /* NOTE: all that is done without knowing or caring about diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index ea2c31d18080..c4e62a6297d7 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -245,6 +245,18 @@ #include "gadget_chips.h" + +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + /*-------------------------------------------------------------------------*/ #define DRIVER_DESC "File-backed Storage Gadget" @@ -839,7 +851,7 @@ config_desc = { .bConfigurationValue = CONFIG_VALUE, .iConfiguration = STRING_CONFIG, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, // self-powered + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, }; static struct usb_otg_descriptor @@ -2664,11 +2676,24 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, /* Verify the length of the command itself */ if (cmnd_size != fsg->cmnd_size) { - /* Special case workaround: MS-Windows issues REQUEST SENSE - * with cbw->Length == 12 (it should be 6). */ - if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12) + /* Special case workaround: There are plenty of buggy SCSI + * implementations. Many have issues with cbw->Length + * field passing a wrong command size. For those cases we + * always try to work around the problem by using the length + * sent by the host side provided it is at least as large + * as the correct command length. + * Examples of such cases would be MS-Windows, which issues + * REQUEST SENSE with cbw->Length == 12 where it should + * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and + * REQUEST SENSE with cbw->Length == 10 where it should + * be 6 as well. + */ + if (cmnd_size <= fsg->cmnd_size) { + DBG(fsg, "%s is buggy! Expected length %d " + "but we got %d\n", name, + cmnd_size, fsg->cmnd_size); cmnd_size = fsg->cmnd_size; - else { + } else { fsg->phase_error = 1; return -EINVAL; } diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c new file mode 100644 index 000000000000..1fe8b44787b3 --- /dev/null +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -0,0 +1,2760 @@ +/* + * driver/usb/gadget/fsl_qe_udc.c + * + * Copyright (c) 2006-2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Xie Xiaobo <X.Xie@freescale.com> + * Li Yang <leoli@freescale.com> + * Based on bareboard code from Shlomi Gridish. + * + * Description: + * Freescle QE/CPM USB Pheripheral Controller Driver + * The controller can be found on MPC8360, MPC8272, and etc. + * MPC8360 Rev 1.1 may need QE mircocode update + * + * 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. + */ + +#undef USB_TRACE + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/moduleparam.h> +#include <linux/of_platform.h> +#include <linux/dma-mapping.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> +#include <linux/usb/otg.h> +#include <asm/qe.h> +#include <asm/cpm.h> +#include <asm/dma.h> +#include <asm/reg.h> +#include "fsl_qe_udc.h" + +#define DRIVER_DESC "Freescale QE/CPM USB Device Controller driver" +#define DRIVER_AUTHOR "Xie XiaoBo" +#define DRIVER_VERSION "1.0" + +#define DMA_ADDR_INVALID (~(dma_addr_t)0) + +static const char driver_name[] = "fsl_qe_udc"; +static const char driver_desc[] = DRIVER_DESC; + +/*ep name is important in gadget, it should obey the convention of ep_match()*/ +static const char *const ep_name[] = { + "ep0-control", /* everyone has ep0 */ + /* 3 configurable endpoints */ + "ep1", + "ep2", + "ep3", +}; + +static struct usb_endpoint_descriptor qe_ep0_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = 0, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + .wMaxPacketSize = USB_MAX_CTRL_PAYLOAD, +}; + +/* it is initialized in probe() */ +static struct qe_udc *udc_controller; + +/******************************************************************** + * Internal Used Function Start +********************************************************************/ +/*----------------------------------------------------------------- + * done() - retire a request; caller blocked irqs + *--------------------------------------------------------------*/ +static void done(struct qe_ep *ep, struct qe_req *req, int status) +{ + struct qe_udc *udc = ep->udc; + unsigned char stopped = ep->stopped; + + /* the req->queue pointer is used by ep_queue() func, in which + * the request will be added into a udc_ep->queue 'd tail + * so here the req will be dropped from the ep->queue + */ + list_del_init(&req->queue); + + /* req.status should be set as -EINPROGRESS in ep_queue() */ + if (req->req.status == -EINPROGRESS) + req->req.status = status; + else + status = req->req.status; + + if (req->mapped) { + dma_unmap_single(udc->gadget.dev.parent, + req->req.dma, req->req.length, + ep_is_in(ep) + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + req->req.dma = DMA_ADDR_INVALID; + req->mapped = 0; + } else + dma_sync_single_for_cpu(udc->gadget.dev.parent, + req->req.dma, req->req.length, + ep_is_in(ep) + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + + if (status && (status != -ESHUTDOWN)) + dev_vdbg(udc->dev, "complete %s req %p stat %d len %u/%u\n", + ep->ep.name, &req->req, status, + req->req.actual, req->req.length); + + /* don't modify queue heads during completion callback */ + ep->stopped = 1; + spin_unlock(&udc->lock); + + /* this complete() should a func implemented by gadget layer, + * eg fsg->bulk_in_complete() */ + if (req->req.complete) + req->req.complete(&ep->ep, &req->req); + + spin_lock(&udc->lock); + + ep->stopped = stopped; +} + +/*----------------------------------------------------------------- + * nuke(): delete all requests related to this ep + *--------------------------------------------------------------*/ +static void nuke(struct qe_ep *ep, int status) +{ + /* Whether this eq has request linked */ + while (!list_empty(&ep->queue)) { + struct qe_req *req = NULL; + req = list_entry(ep->queue.next, struct qe_req, queue); + + done(ep, req, status); + } +} + +/*---------------------------------------------------------------------------* + * USB and Endpoint manipulate process, include parameter and register * + *---------------------------------------------------------------------------*/ +/* @value: 1--set stall 0--clean stall */ +static int qe_eprx_stall_change(struct qe_ep *ep, int value) +{ + u16 tem_usep; + u8 epnum = ep->epnum; + struct qe_udc *udc = ep->udc; + + tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]); + tem_usep = tem_usep & ~USB_RHS_MASK; + if (value == 1) + tem_usep |= USB_RHS_STALL; + else if (ep->dir == USB_DIR_IN) + tem_usep |= USB_RHS_IGNORE_OUT; + + out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep); + return 0; +} + +static int qe_eptx_stall_change(struct qe_ep *ep, int value) +{ + u16 tem_usep; + u8 epnum = ep->epnum; + struct qe_udc *udc = ep->udc; + + tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]); + tem_usep = tem_usep & ~USB_THS_MASK; + if (value == 1) + tem_usep |= USB_THS_STALL; + else if (ep->dir == USB_DIR_OUT) + tem_usep |= USB_THS_IGNORE_IN; + + out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep); + + return 0; +} + +static int qe_ep0_stall(struct qe_udc *udc) +{ + qe_eptx_stall_change(&udc->eps[0], 1); + qe_eprx_stall_change(&udc->eps[0], 1); + udc_controller->ep0_state = WAIT_FOR_SETUP; + udc_controller->ep0_dir = 0; + return 0; +} + +static int qe_eprx_nack(struct qe_ep *ep) +{ + u8 epnum = ep->epnum; + struct qe_udc *udc = ep->udc; + + if (ep->state == EP_STATE_IDLE) { + /* Set the ep's nack */ + clrsetbits_be16(&udc->usb_regs->usb_usep[epnum], + USB_RHS_MASK, USB_RHS_NACK); + + /* Mask Rx and Busy interrupts */ + clrbits16(&udc->usb_regs->usb_usbmr, + (USB_E_RXB_MASK | USB_E_BSY_MASK)); + + ep->state = EP_STATE_NACK; + } + return 0; +} + +static int qe_eprx_normal(struct qe_ep *ep) +{ + struct qe_udc *udc = ep->udc; + + if (ep->state == EP_STATE_NACK) { + clrsetbits_be16(&udc->usb_regs->usb_usep[ep->epnum], + USB_RTHS_MASK, USB_THS_IGNORE_IN); + + /* Unmask RX interrupts */ + out_be16(&udc->usb_regs->usb_usber, + USB_E_BSY_MASK | USB_E_RXB_MASK); + setbits16(&udc->usb_regs->usb_usbmr, + (USB_E_RXB_MASK | USB_E_BSY_MASK)); + + ep->state = EP_STATE_IDLE; + ep->has_data = 0; + } + + return 0; +} + +static int qe_ep_cmd_stoptx(struct qe_ep *ep) +{ + if (ep->udc->soc_type == PORT_CPM) + cpm_command(CPM_USB_STOP_TX | (ep->epnum << CPM_USB_EP_SHIFT), + CPM_USB_STOP_TX_OPCODE); + else + qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, + ep->epnum, 0); + + return 0; +} + +static int qe_ep_cmd_restarttx(struct qe_ep *ep) +{ + if (ep->udc->soc_type == PORT_CPM) + cpm_command(CPM_USB_RESTART_TX | (ep->epnum << + CPM_USB_EP_SHIFT), CPM_USB_RESTART_TX_OPCODE); + else + qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB, + ep->epnum, 0); + + return 0; +} + +static int qe_ep_flushtxfifo(struct qe_ep *ep) +{ + struct qe_udc *udc = ep->udc; + int i; + + i = (int)ep->epnum; + + qe_ep_cmd_stoptx(ep); + out_8(&udc->usb_regs->usb_uscom, + USB_CMD_FLUSH_FIFO | (USB_CMD_EP_MASK & (ep->epnum))); + out_be16(&udc->ep_param[i]->tbptr, in_be16(&udc->ep_param[i]->tbase)); + out_be32(&udc->ep_param[i]->tstate, 0); + out_be16(&udc->ep_param[i]->tbcnt, 0); + + ep->c_txbd = ep->txbase; + ep->n_txbd = ep->txbase; + qe_ep_cmd_restarttx(ep); + return 0; +} + +static int qe_ep_filltxfifo(struct qe_ep *ep) +{ + struct qe_udc *udc = ep->udc; + + out_8(&udc->usb_regs->usb_uscom, + USB_CMD_STR_FIFO | (USB_CMD_EP_MASK & (ep->epnum))); + return 0; +} + +static int qe_epbds_reset(struct qe_udc *udc, int pipe_num) +{ + struct qe_ep *ep; + u32 bdring_len; + struct qe_bd __iomem *bd; + int i; + + ep = &udc->eps[pipe_num]; + + if (ep->dir == USB_DIR_OUT) + bdring_len = USB_BDRING_LEN_RX; + else + bdring_len = USB_BDRING_LEN; + + bd = ep->rxbase; + for (i = 0; i < (bdring_len - 1); i++) { + out_be32((u32 __iomem *)bd, R_E | R_I); + bd++; + } + out_be32((u32 __iomem *)bd, R_E | R_I | R_W); + + bd = ep->txbase; + for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) { + out_be32(&bd->buf, 0); + out_be32((u32 __iomem *)bd, 0); + bd++; + } + out_be32((u32 __iomem *)bd, T_W); + + return 0; +} + +static int qe_ep_reset(struct qe_udc *udc, int pipe_num) +{ + struct qe_ep *ep; + u16 tmpusep; + + ep = &udc->eps[pipe_num]; + tmpusep = in_be16(&udc->usb_regs->usb_usep[pipe_num]); + tmpusep &= ~USB_RTHS_MASK; + + switch (ep->dir) { + case USB_DIR_BOTH: + qe_ep_flushtxfifo(ep); + break; + case USB_DIR_OUT: + tmpusep |= USB_THS_IGNORE_IN; + break; + case USB_DIR_IN: + qe_ep_flushtxfifo(ep); + tmpusep |= USB_RHS_IGNORE_OUT; + break; + default: + break; + } + out_be16(&udc->usb_regs->usb_usep[pipe_num], tmpusep); + + qe_epbds_reset(udc, pipe_num); + + return 0; +} + +static int qe_ep_toggledata01(struct qe_ep *ep) +{ + ep->data01 ^= 0x1; + return 0; +} + +static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num) +{ + struct qe_ep *ep = &udc->eps[pipe_num]; + unsigned long tmp_addr = 0; + struct usb_ep_para __iomem *epparam; + int i; + struct qe_bd __iomem *bd; + int bdring_len; + + if (ep->dir == USB_DIR_OUT) + bdring_len = USB_BDRING_LEN_RX; + else + bdring_len = USB_BDRING_LEN; + + epparam = udc->ep_param[pipe_num]; + /* alloc multi-ram for BD rings and set the ep parameters */ + tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len + + USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD); + out_be16(&epparam->rbase, (u16)tmp_addr); + out_be16(&epparam->tbase, (u16)(tmp_addr + + (sizeof(struct qe_bd) * bdring_len))); + + out_be16(&epparam->rbptr, in_be16(&epparam->rbase)); + out_be16(&epparam->tbptr, in_be16(&epparam->tbase)); + + ep->rxbase = cpm_muram_addr(tmp_addr); + ep->txbase = cpm_muram_addr(tmp_addr + (sizeof(struct qe_bd) + * bdring_len)); + ep->n_rxbd = ep->rxbase; + ep->e_rxbd = ep->rxbase; + ep->n_txbd = ep->txbase; + ep->c_txbd = ep->txbase; + ep->data01 = 0; /* data0 */ + + /* Init TX and RX bds */ + bd = ep->rxbase; + for (i = 0; i < bdring_len - 1; i++) { + out_be32(&bd->buf, 0); + out_be32((u32 __iomem *)bd, 0); + bd++; + } + out_be32(&bd->buf, 0); + out_be32((u32 __iomem *)bd, R_W); + + bd = ep->txbase; + for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) { + out_be32(&bd->buf, 0); + out_be32((u32 __iomem *)bd, 0); + bd++; + } + out_be32(&bd->buf, 0); + out_be32((u32 __iomem *)bd, T_W); + + return 0; +} + +static int qe_ep_rxbd_update(struct qe_ep *ep) +{ + unsigned int size; + int i; + unsigned int tmp; + struct qe_bd __iomem *bd; + unsigned int bdring_len; + + if (ep->rxbase == NULL) + return -EINVAL; + + bd = ep->rxbase; + + ep->rxframe = kmalloc(sizeof(*ep->rxframe), GFP_ATOMIC); + if (ep->rxframe == NULL) { + dev_err(ep->udc->dev, "malloc rxframe failed\n"); + return -ENOMEM; + } + + qe_frame_init(ep->rxframe); + + if (ep->dir == USB_DIR_OUT) + bdring_len = USB_BDRING_LEN_RX; + else + bdring_len = USB_BDRING_LEN; + + size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (bdring_len + 1); + ep->rxbuffer = kzalloc(size, GFP_ATOMIC); + if (ep->rxbuffer == NULL) { + dev_err(ep->udc->dev, "malloc rxbuffer failed,size=%d\n", + size); + kfree(ep->rxframe); + return -ENOMEM; + } + + ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer); + if (ep->rxbuf_d == DMA_ADDR_INVALID) { + ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent, + ep->rxbuffer, + size, + DMA_FROM_DEVICE); + ep->rxbufmap = 1; + } else { + dma_sync_single_for_device(udc_controller->gadget.dev.parent, + ep->rxbuf_d, size, + DMA_FROM_DEVICE); + ep->rxbufmap = 0; + } + + size = ep->ep.maxpacket + USB_CRC_SIZE + 2; + tmp = ep->rxbuf_d; + tmp = (u32)(((tmp >> 2) << 2) + 4); + + for (i = 0; i < bdring_len - 1; i++) { + out_be32(&bd->buf, tmp); + out_be32((u32 __iomem *)bd, (R_E | R_I)); + tmp = tmp + size; + bd++; + } + out_be32(&bd->buf, tmp); + out_be32((u32 __iomem *)bd, (R_E | R_I | R_W)); + + return 0; +} + +static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num) +{ + struct qe_ep *ep = &udc->eps[pipe_num]; + struct usb_ep_para __iomem *epparam; + u16 usep, logepnum; + u16 tmp; + u8 rtfcr = 0; + + epparam = udc->ep_param[pipe_num]; + + usep = 0; + logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usep |= (logepnum << USB_EPNUM_SHIFT); + + switch (ep->desc->bmAttributes & 0x03) { + case USB_ENDPOINT_XFER_BULK: + usep |= USB_TRANS_BULK; + break; + case USB_ENDPOINT_XFER_ISOC: + usep |= USB_TRANS_ISO; + break; + case USB_ENDPOINT_XFER_INT: + usep |= USB_TRANS_INT; + break; + default: + usep |= USB_TRANS_CTR; + break; + } + + switch (ep->dir) { + case USB_DIR_OUT: + usep |= USB_THS_IGNORE_IN; + break; + case USB_DIR_IN: + usep |= USB_RHS_IGNORE_OUT; + break; + default: + break; + } + out_be16(&udc->usb_regs->usb_usep[pipe_num], usep); + + rtfcr = 0x30; + out_8(&epparam->rbmr, rtfcr); + out_8(&epparam->tbmr, rtfcr); + + tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE); + /* MRBLR must be divisble by 4 */ + tmp = (u16)(((tmp >> 2) << 2) + 4); + out_be16(&epparam->mrblr, tmp); + + return 0; +} + +static int qe_ep_init(struct qe_udc *udc, + unsigned char pipe_num, + const struct usb_endpoint_descriptor *desc) +{ + struct qe_ep *ep = &udc->eps[pipe_num]; + unsigned long flags; + int reval = 0; + u16 max = 0; + + max = le16_to_cpu(desc->wMaxPacketSize); + + /* check the max package size validate for this endpoint */ + /* Refer to USB2.0 spec table 9-13, + */ + if (pipe_num != 0) { + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: + if (strstr(ep->ep.name, "-iso") + || strstr(ep->ep.name, "-int")) + goto en_done; + switch (udc->gadget.speed) { + case USB_SPEED_HIGH: + if ((max == 128) || (max == 256) || (max == 512)) + break; + default: + switch (max) { + case 4: + case 8: + case 16: + case 32: + case 64: + break; + default: + case USB_SPEED_LOW: + goto en_done; + } + } + break; + case USB_ENDPOINT_XFER_INT: + if (strstr(ep->ep.name, "-iso")) /* bulk is ok */ + goto en_done; + switch (udc->gadget.speed) { + case USB_SPEED_HIGH: + if (max <= 1024) + break; + case USB_SPEED_FULL: + if (max <= 64) + break; + default: + if (max <= 8) + break; + goto en_done; + } + break; + case USB_ENDPOINT_XFER_ISOC: + if (strstr(ep->ep.name, "-bulk") + || strstr(ep->ep.name, "-int")) + goto en_done; + switch (udc->gadget.speed) { + case USB_SPEED_HIGH: + if (max <= 1024) + break; + case USB_SPEED_FULL: + if (max <= 1023) + break; + default: + goto en_done; + } + break; + case USB_ENDPOINT_XFER_CONTROL: + if (strstr(ep->ep.name, "-iso") + || strstr(ep->ep.name, "-int")) + goto en_done; + switch (udc->gadget.speed) { + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + switch (max) { + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + case 64: + break; + default: + goto en_done; + } + case USB_SPEED_LOW: + switch (max) { + case 1: + case 2: + case 4: + case 8: + break; + default: + goto en_done; + } + default: + goto en_done; + } + break; + + default: + goto en_done; + } + } /* if ep0*/ + + spin_lock_irqsave(&udc->lock, flags); + + /* initialize ep structure */ + ep->ep.maxpacket = max; + ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + ep->desc = desc; + ep->stopped = 0; + ep->init = 1; + + if (pipe_num == 0) { + ep->dir = USB_DIR_BOTH; + udc->ep0_dir = USB_DIR_OUT; + udc->ep0_state = WAIT_FOR_SETUP; + } else { + switch (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { + case USB_DIR_OUT: + ep->dir = USB_DIR_OUT; + break; + case USB_DIR_IN: + ep->dir = USB_DIR_IN; + default: + break; + } + } + + /* hardware special operation */ + qe_ep_bd_init(udc, pipe_num); + if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_OUT)) { + reval = qe_ep_rxbd_update(ep); + if (reval) + goto en_done1; + } + + if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_IN)) { + ep->txframe = kmalloc(sizeof(*ep->txframe), GFP_ATOMIC); + if (ep->txframe == NULL) { + dev_err(udc->dev, "malloc txframe failed\n"); + goto en_done2; + } + qe_frame_init(ep->txframe); + } + + qe_ep_register_init(udc, pipe_num); + + /* Now HW will be NAKing transfers to that EP, + * until a buffer is queued to it. */ + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +en_done2: + kfree(ep->rxbuffer); + kfree(ep->rxframe); +en_done1: + spin_unlock_irqrestore(&udc->lock, flags); +en_done: + dev_dbg(udc->dev, "failed to initialize %s\n", ep->ep.name); + return -ENODEV; +} + +static inline void qe_usb_enable(void) +{ + setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN); +} + +static inline void qe_usb_disable(void) +{ + clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN); +} + +/*----------------------------------------------------------------------------* + * USB and EP basic manipulate function end * + *----------------------------------------------------------------------------*/ + + +/****************************************************************************** + UDC transmit and receive process + ******************************************************************************/ +static void recycle_one_rxbd(struct qe_ep *ep) +{ + u32 bdstatus; + + bdstatus = in_be32((u32 __iomem *)ep->e_rxbd); + bdstatus = R_I | R_E | (bdstatus & R_W); + out_be32((u32 __iomem *)ep->e_rxbd, bdstatus); + + if (bdstatus & R_W) + ep->e_rxbd = ep->rxbase; + else + ep->e_rxbd++; +} + +static void recycle_rxbds(struct qe_ep *ep, unsigned char stopatnext) +{ + u32 bdstatus; + struct qe_bd __iomem *bd, *nextbd; + unsigned char stop = 0; + + nextbd = ep->n_rxbd; + bd = ep->e_rxbd; + bdstatus = in_be32((u32 __iomem *)bd); + + while (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK) && !stop) { + bdstatus = R_E | R_I | (bdstatus & R_W); + out_be32((u32 __iomem *)bd, bdstatus); + + if (bdstatus & R_W) + bd = ep->rxbase; + else + bd++; + + bdstatus = in_be32((u32 __iomem *)bd); + if (stopatnext && (bd == nextbd)) + stop = 1; + } + + ep->e_rxbd = bd; +} + +static void ep_recycle_rxbds(struct qe_ep *ep) +{ + struct qe_bd __iomem *bd = ep->n_rxbd; + u32 bdstatus; + u8 epnum = ep->epnum; + struct qe_udc *udc = ep->udc; + + bdstatus = in_be32((u32 __iomem *)bd); + if (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK)) { + bd = ep->rxbase + + ((in_be16(&udc->ep_param[epnum]->rbptr) - + in_be16(&udc->ep_param[epnum]->rbase)) + >> 3); + bdstatus = in_be32((u32 __iomem *)bd); + + if (bdstatus & R_W) + bd = ep->rxbase; + else + bd++; + + ep->e_rxbd = bd; + recycle_rxbds(ep, 0); + ep->e_rxbd = ep->n_rxbd; + } else + recycle_rxbds(ep, 1); + + if (in_be16(&udc->usb_regs->usb_usber) & USB_E_BSY_MASK) + out_be16(&udc->usb_regs->usb_usber, USB_E_BSY_MASK); + + if (ep->has_data <= 0 && (!list_empty(&ep->queue))) + qe_eprx_normal(ep); + + ep->localnack = 0; +} + +static void setup_received_handle(struct qe_udc *udc, + struct usb_ctrlrequest *setup); +static int qe_ep_rxframe_handle(struct qe_ep *ep); +static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req); +/* when BD PID is setup, handle the packet */ +static int ep0_setup_handle(struct qe_udc *udc) +{ + struct qe_ep *ep = &udc->eps[0]; + struct qe_frame *pframe; + unsigned int fsize; + u8 *cp; + + pframe = ep->rxframe; + if ((frame_get_info(pframe) & PID_SETUP) + && (udc->ep0_state == WAIT_FOR_SETUP)) { + fsize = frame_get_length(pframe); + if (unlikely(fsize != 8)) + return -EINVAL; + cp = (u8 *)&udc->local_setup_buff; + memcpy(cp, pframe->data, fsize); + ep->data01 = 1; + + /* handle the usb command base on the usb_ctrlrequest */ + setup_received_handle(udc, &udc->local_setup_buff); + return 0; + } + return -EINVAL; +} + +static int qe_ep0_rx(struct qe_udc *udc) +{ + struct qe_ep *ep = &udc->eps[0]; + struct qe_frame *pframe; + struct qe_bd __iomem *bd; + u32 bdstatus, length; + u32 vaddr; + + pframe = ep->rxframe; + + if (ep->dir == USB_DIR_IN) { + dev_err(udc->dev, "ep0 not a control endpoint\n"); + return -EINVAL; + } + + bd = ep->n_rxbd; + bdstatus = in_be32((u32 __iomem *)bd); + length = bdstatus & BD_LENGTH_MASK; + + while (!(bdstatus & R_E) && length) { + if ((bdstatus & R_F) && (bdstatus & R_L) + && !(bdstatus & R_ERROR)) { + if (length == USB_CRC_SIZE) { + udc->ep0_state = WAIT_FOR_SETUP; + dev_vdbg(udc->dev, + "receive a ZLP in status phase\n"); + } else { + qe_frame_clean(pframe); + vaddr = (u32)phys_to_virt(in_be32(&bd->buf)); + frame_set_data(pframe, (u8 *)vaddr); + frame_set_length(pframe, + (length - USB_CRC_SIZE)); + frame_set_status(pframe, FRAME_OK); + switch (bdstatus & R_PID) { + case R_PID_SETUP: + frame_set_info(pframe, PID_SETUP); + break; + case R_PID_DATA1: + frame_set_info(pframe, PID_DATA1); + break; + default: + frame_set_info(pframe, PID_DATA0); + break; + } + + if ((bdstatus & R_PID) == R_PID_SETUP) + ep0_setup_handle(udc); + else + qe_ep_rxframe_handle(ep); + } + } else { + dev_err(udc->dev, "The receive frame with error!\n"); + } + + /* note: don't clear the rxbd's buffer address */ + recycle_one_rxbd(ep); + + /* Get next BD */ + if (bdstatus & R_W) + bd = ep->rxbase; + else + bd++; + + bdstatus = in_be32((u32 __iomem *)bd); + length = bdstatus & BD_LENGTH_MASK; + + } + + ep->n_rxbd = bd; + + return 0; +} + +static int qe_ep_rxframe_handle(struct qe_ep *ep) +{ + struct qe_frame *pframe; + u8 framepid = 0; + unsigned int fsize; + u8 *cp; + struct qe_req *req; + + pframe = ep->rxframe; + + if (frame_get_info(pframe) & PID_DATA1) + framepid = 0x1; + + if (framepid != ep->data01) { + dev_err(ep->udc->dev, "the data01 error!\n"); + return -EIO; + } + + fsize = frame_get_length(pframe); + if (list_empty(&ep->queue)) { + dev_err(ep->udc->dev, "the %s have no requeue!\n", ep->name); + } else { + req = list_entry(ep->queue.next, struct qe_req, queue); + + cp = (u8 *)(req->req.buf) + req->req.actual; + if (cp) { + memcpy(cp, pframe->data, fsize); + req->req.actual += fsize; + if ((fsize < ep->ep.maxpacket) || + (req->req.actual >= req->req.length)) { + if (ep->epnum == 0) + ep0_req_complete(ep->udc, req); + else + done(ep, req, 0); + if (list_empty(&ep->queue) && ep->epnum != 0) + qe_eprx_nack(ep); + } + } + } + + qe_ep_toggledata01(ep); + + return 0; +} + +static void ep_rx_tasklet(unsigned long data) +{ + struct qe_udc *udc = (struct qe_udc *)data; + struct qe_ep *ep; + struct qe_frame *pframe; + struct qe_bd __iomem *bd; + unsigned long flags; + u32 bdstatus, length; + u32 vaddr, i; + + spin_lock_irqsave(&udc->lock, flags); + + for (i = 1; i < USB_MAX_ENDPOINTS; i++) { + ep = &udc->eps[i]; + + if (ep->dir == USB_DIR_IN || ep->enable_tasklet == 0) { + dev_dbg(udc->dev, + "This is a transmit ep or disable tasklet!\n"); + continue; + } + + pframe = ep->rxframe; + bd = ep->n_rxbd; + bdstatus = in_be32((u32 __iomem *)bd); + length = bdstatus & BD_LENGTH_MASK; + + while (!(bdstatus & R_E) && length) { + if (list_empty(&ep->queue)) { + qe_eprx_nack(ep); + dev_dbg(udc->dev, + "The rxep have noreq %d\n", + ep->has_data); + break; + } + + if ((bdstatus & R_F) && (bdstatus & R_L) + && !(bdstatus & R_ERROR)) { + qe_frame_clean(pframe); + vaddr = (u32)phys_to_virt(in_be32(&bd->buf)); + frame_set_data(pframe, (u8 *)vaddr); + frame_set_length(pframe, + (length - USB_CRC_SIZE)); + frame_set_status(pframe, FRAME_OK); + switch (bdstatus & R_PID) { + case R_PID_DATA1: + frame_set_info(pframe, PID_DATA1); + break; + case R_PID_SETUP: + frame_set_info(pframe, PID_SETUP); + break; + default: + frame_set_info(pframe, PID_DATA0); + break; + } + /* handle the rx frame */ + qe_ep_rxframe_handle(ep); + } else { + dev_err(udc->dev, + "error in received frame\n"); + } + /* note: don't clear the rxbd's buffer address */ + /*clear the length */ + out_be32((u32 __iomem *)bd, bdstatus & BD_STATUS_MASK); + ep->has_data--; + if (!(ep->localnack)) + recycle_one_rxbd(ep); + + /* Get next BD */ + if (bdstatus & R_W) + bd = ep->rxbase; + else + bd++; + + bdstatus = in_be32((u32 __iomem *)bd); + length = bdstatus & BD_LENGTH_MASK; + } + + ep->n_rxbd = bd; + + if (ep->localnack) + ep_recycle_rxbds(ep); + + ep->enable_tasklet = 0; + } /* for i=1 */ + + spin_unlock_irqrestore(&udc->lock, flags); +} + +static int qe_ep_rx(struct qe_ep *ep) +{ + struct qe_udc *udc; + struct qe_frame *pframe; + struct qe_bd __iomem *bd; + u16 swoffs, ucoffs, emptybds; + + udc = ep->udc; + pframe = ep->rxframe; + + if (ep->dir == USB_DIR_IN) { + dev_err(udc->dev, "transmit ep in rx function\n"); + return -EINVAL; + } + + bd = ep->n_rxbd; + + swoffs = (u16)(bd - ep->rxbase); + ucoffs = (u16)((in_be16(&udc->ep_param[ep->epnum]->rbptr) - + in_be16(&udc->ep_param[ep->epnum]->rbase)) >> 3); + if (swoffs < ucoffs) + emptybds = USB_BDRING_LEN_RX - ucoffs + swoffs; + else + emptybds = swoffs - ucoffs; + + if (emptybds < MIN_EMPTY_BDS) { + qe_eprx_nack(ep); + ep->localnack = 1; + dev_vdbg(udc->dev, "%d empty bds, send NACK\n", emptybds); + } + ep->has_data = USB_BDRING_LEN_RX - emptybds; + + if (list_empty(&ep->queue)) { + qe_eprx_nack(ep); + dev_vdbg(udc->dev, "The rxep have no req queued with %d BDs\n", + ep->has_data); + return 0; + } + + tasklet_schedule(&udc->rx_tasklet); + ep->enable_tasklet = 1; + + return 0; +} + +/* send data from a frame, no matter what tx_req */ +static int qe_ep_tx(struct qe_ep *ep, struct qe_frame *frame) +{ + struct qe_udc *udc = ep->udc; + struct qe_bd __iomem *bd; + u16 saveusbmr; + u32 bdstatus, pidmask; + u32 paddr; + + if (ep->dir == USB_DIR_OUT) { + dev_err(udc->dev, "receive ep passed to tx function\n"); + return -EINVAL; + } + + /* Disable the Tx interrupt */ + saveusbmr = in_be16(&udc->usb_regs->usb_usbmr); + out_be16(&udc->usb_regs->usb_usbmr, + saveusbmr & ~(USB_E_TXB_MASK | USB_E_TXE_MASK)); + + bd = ep->n_txbd; + bdstatus = in_be32((u32 __iomem *)bd); + + if (!(bdstatus & (T_R | BD_LENGTH_MASK))) { + if (frame_get_length(frame) == 0) { + frame_set_data(frame, udc->nullbuf); + frame_set_length(frame, 2); + frame->info |= (ZLP | NO_CRC); + dev_vdbg(udc->dev, "the frame size = 0\n"); + } + paddr = virt_to_phys((void *)frame->data); + out_be32(&bd->buf, paddr); + bdstatus = (bdstatus&T_W); + if (!(frame_get_info(frame) & NO_CRC)) + bdstatus |= T_R | T_I | T_L | T_TC + | frame_get_length(frame); + else + bdstatus |= T_R | T_I | T_L | frame_get_length(frame); + + /* if the packet is a ZLP in status phase */ + if ((ep->epnum == 0) && (udc->ep0_state == DATA_STATE_NEED_ZLP)) + ep->data01 = 0x1; + + if (ep->data01) { + pidmask = T_PID_DATA1; + frame->info |= PID_DATA1; + } else { + pidmask = T_PID_DATA0; + frame->info |= PID_DATA0; + } + bdstatus |= T_CNF; + bdstatus |= pidmask; + out_be32((u32 __iomem *)bd, bdstatus); + qe_ep_filltxfifo(ep); + + /* enable the TX interrupt */ + out_be16(&udc->usb_regs->usb_usbmr, saveusbmr); + + qe_ep_toggledata01(ep); + if (bdstatus & T_W) + ep->n_txbd = ep->txbase; + else + ep->n_txbd++; + + return 0; + } else { + out_be16(&udc->usb_regs->usb_usbmr, saveusbmr); + dev_vdbg(udc->dev, "The tx bd is not ready!\n"); + return -EBUSY; + } +} + +/* when a bd was transmitted, the function can + * handle the tx_req, not include ep0 */ +static int txcomplete(struct qe_ep *ep, unsigned char restart) +{ + if (ep->tx_req != NULL) { + if (!restart) { + int asent = ep->last; + ep->sent += asent; + ep->last -= asent; + } else { + ep->last = 0; + } + + /* a request already were transmitted completely */ + if ((ep->tx_req->req.length - ep->sent) <= 0) { + ep->tx_req->req.actual = (unsigned int)ep->sent; + done(ep, ep->tx_req, 0); + ep->tx_req = NULL; + ep->last = 0; + ep->sent = 0; + } + } + + /* we should gain a new tx_req fot this endpoint */ + if (ep->tx_req == NULL) { + if (!list_empty(&ep->queue)) { + ep->tx_req = list_entry(ep->queue.next, struct qe_req, + queue); + ep->last = 0; + ep->sent = 0; + } + } + + return 0; +} + +/* give a frame and a tx_req, send some data */ +static int qe_usb_senddata(struct qe_ep *ep, struct qe_frame *frame) +{ + unsigned int size; + u8 *buf; + + qe_frame_clean(frame); + size = min_t(u32, (ep->tx_req->req.length - ep->sent), + ep->ep.maxpacket); + buf = (u8 *)ep->tx_req->req.buf + ep->sent; + if (buf && size) { + ep->last = size; + frame_set_data(frame, buf); + frame_set_length(frame, size); + frame_set_status(frame, FRAME_OK); + frame_set_info(frame, 0); + return qe_ep_tx(ep, frame); + } + return -EIO; +} + +/* give a frame struct,send a ZLP */ +static int sendnulldata(struct qe_ep *ep, struct qe_frame *frame, uint infor) +{ + struct qe_udc *udc = ep->udc; + + if (frame == NULL) + return -ENODEV; + + qe_frame_clean(frame); + frame_set_data(frame, (u8 *)udc->nullbuf); + frame_set_length(frame, 2); + frame_set_status(frame, FRAME_OK); + frame_set_info(frame, (ZLP | NO_CRC | infor)); + + return qe_ep_tx(ep, frame); +} + +static int frame_create_tx(struct qe_ep *ep, struct qe_frame *frame) +{ + struct qe_req *req = ep->tx_req; + int reval; + + if (req == NULL) + return -ENODEV; + + if ((req->req.length - ep->sent) > 0) + reval = qe_usb_senddata(ep, frame); + else + reval = sendnulldata(ep, frame, 0); + + return reval; +} + +/* if direction is DIR_IN, the status is Device->Host + * if direction is DIR_OUT, the status transaction is Device<-Host + * in status phase, udc create a request and gain status */ +static int ep0_prime_status(struct qe_udc *udc, int direction) +{ + + struct qe_ep *ep = &udc->eps[0]; + + if (direction == USB_DIR_IN) { + udc->ep0_state = DATA_STATE_NEED_ZLP; + udc->ep0_dir = USB_DIR_IN; + sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ); + } else { + udc->ep0_dir = USB_DIR_OUT; + udc->ep0_state = WAIT_FOR_OUT_STATUS; + } + + return 0; +} + +/* a request complete in ep0, whether gadget request or udc request */ +static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req) +{ + struct qe_ep *ep = &udc->eps[0]; + /* because usb and ep's status already been set in ch9setaddress() */ + + switch (udc->ep0_state) { + case DATA_STATE_XMIT: + done(ep, req, 0); + /* receive status phase */ + if (ep0_prime_status(udc, USB_DIR_OUT)) + qe_ep0_stall(udc); + break; + + case DATA_STATE_NEED_ZLP: + done(ep, req, 0); + udc->ep0_state = WAIT_FOR_SETUP; + break; + + case DATA_STATE_RECV: + done(ep, req, 0); + /* send status phase */ + if (ep0_prime_status(udc, USB_DIR_IN)) + qe_ep0_stall(udc); + break; + + case WAIT_FOR_OUT_STATUS: + done(ep, req, 0); + udc->ep0_state = WAIT_FOR_SETUP; + break; + + case WAIT_FOR_SETUP: + dev_vdbg(udc->dev, "Unexpected interrupt\n"); + break; + + default: + qe_ep0_stall(udc); + break; + } +} + +static int ep0_txcomplete(struct qe_ep *ep, unsigned char restart) +{ + struct qe_req *tx_req = NULL; + struct qe_frame *frame = ep->txframe; + + if ((frame_get_info(frame) & (ZLP | NO_REQ)) == (ZLP | NO_REQ)) { + if (!restart) + ep->udc->ep0_state = WAIT_FOR_SETUP; + else + sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ); + return 0; + } + + tx_req = ep->tx_req; + if (tx_req != NULL) { + if (!restart) { + int asent = ep->last; + ep->sent += asent; + ep->last -= asent; + } else { + ep->last = 0; + } + + /* a request already were transmitted completely */ + if ((ep->tx_req->req.length - ep->sent) <= 0) { + ep->tx_req->req.actual = (unsigned int)ep->sent; + ep0_req_complete(ep->udc, ep->tx_req); + ep->tx_req = NULL; + ep->last = 0; + ep->sent = 0; + } + } else { + dev_vdbg(ep->udc->dev, "the ep0_controller have no req\n"); + } + + return 0; +} + +static int ep0_txframe_handle(struct qe_ep *ep) +{ + /* if have error, transmit again */ + if (frame_get_status(ep->txframe) & FRAME_ERROR) { + qe_ep_flushtxfifo(ep); + dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n"); + if (frame_get_info(ep->txframe) & PID_DATA0) + ep->data01 = 0; + else + ep->data01 = 1; + + ep0_txcomplete(ep, 1); + } else + ep0_txcomplete(ep, 0); + + frame_create_tx(ep, ep->txframe); + return 0; +} + +static int qe_ep0_txconf(struct qe_ep *ep) +{ + struct qe_bd __iomem *bd; + struct qe_frame *pframe; + u32 bdstatus; + + bd = ep->c_txbd; + bdstatus = in_be32((u32 __iomem *)bd); + while (!(bdstatus & T_R) && (bdstatus & ~T_W)) { + pframe = ep->txframe; + + /* clear and recycle the BD */ + out_be32((u32 __iomem *)bd, bdstatus & T_W); + out_be32(&bd->buf, 0); + if (bdstatus & T_W) + ep->c_txbd = ep->txbase; + else + ep->c_txbd++; + + if (ep->c_txbd == ep->n_txbd) { + if (bdstatus & DEVICE_T_ERROR) { + frame_set_status(pframe, FRAME_ERROR); + if (bdstatus & T_TO) + pframe->status |= TX_ER_TIMEOUT; + if (bdstatus & T_UN) + pframe->status |= TX_ER_UNDERUN; + } + ep0_txframe_handle(ep); + } + + bd = ep->c_txbd; + bdstatus = in_be32((u32 __iomem *)bd); + } + + return 0; +} + +static int ep_txframe_handle(struct qe_ep *ep) +{ + if (frame_get_status(ep->txframe) & FRAME_ERROR) { + qe_ep_flushtxfifo(ep); + dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n"); + if (frame_get_info(ep->txframe) & PID_DATA0) + ep->data01 = 0; + else + ep->data01 = 1; + + txcomplete(ep, 1); + } else + txcomplete(ep, 0); + + frame_create_tx(ep, ep->txframe); /* send the data */ + return 0; +} + +/* confirm the already trainsmited bd */ +static int qe_ep_txconf(struct qe_ep *ep) +{ + struct qe_bd __iomem *bd; + struct qe_frame *pframe = NULL; + u32 bdstatus; + unsigned char breakonrxinterrupt = 0; + + bd = ep->c_txbd; + bdstatus = in_be32((u32 __iomem *)bd); + while (!(bdstatus & T_R) && (bdstatus & ~T_W)) { + pframe = ep->txframe; + if (bdstatus & DEVICE_T_ERROR) { + frame_set_status(pframe, FRAME_ERROR); + if (bdstatus & T_TO) + pframe->status |= TX_ER_TIMEOUT; + if (bdstatus & T_UN) + pframe->status |= TX_ER_UNDERUN; + } + + /* clear and recycle the BD */ + out_be32((u32 __iomem *)bd, bdstatus & T_W); + out_be32(&bd->buf, 0); + if (bdstatus & T_W) + ep->c_txbd = ep->txbase; + else + ep->c_txbd++; + + /* handle the tx frame */ + ep_txframe_handle(ep); + bd = ep->c_txbd; + bdstatus = in_be32((u32 __iomem *)bd); + } + if (breakonrxinterrupt) + return -EIO; + else + return 0; +} + +/* Add a request in queue, and try to transmit a packet */ +static int ep_req_send(struct qe_ep *ep, struct qe_req *req) +{ + int reval = 0; + + if (ep->tx_req == NULL) { + ep->sent = 0; + ep->last = 0; + txcomplete(ep, 0); /* can gain a new tx_req */ + reval = frame_create_tx(ep, ep->txframe); + } + return reval; +} + +/* Maybe this is a good ideal */ +static int ep_req_rx(struct qe_ep *ep, struct qe_req *req) +{ + struct qe_udc *udc = ep->udc; + struct qe_frame *pframe = NULL; + struct qe_bd __iomem *bd; + u32 bdstatus, length; + u32 vaddr, fsize; + u8 *cp; + u8 finish_req = 0; + u8 framepid; + + if (list_empty(&ep->queue)) { + dev_vdbg(udc->dev, "the req already finish!\n"); + return 0; + } + pframe = ep->rxframe; + + bd = ep->n_rxbd; + bdstatus = in_be32((u32 __iomem *)bd); + length = bdstatus & BD_LENGTH_MASK; + + while (!(bdstatus & R_E) && length) { + if (finish_req) + break; + if ((bdstatus & R_F) && (bdstatus & R_L) + && !(bdstatus & R_ERROR)) { + qe_frame_clean(pframe); + vaddr = (u32)phys_to_virt(in_be32(&bd->buf)); + frame_set_data(pframe, (u8 *)vaddr); + frame_set_length(pframe, (length - USB_CRC_SIZE)); + frame_set_status(pframe, FRAME_OK); + switch (bdstatus & R_PID) { + case R_PID_DATA1: + frame_set_info(pframe, PID_DATA1); break; + default: + frame_set_info(pframe, PID_DATA0); break; + } + /* handle the rx frame */ + + if (frame_get_info(pframe) & PID_DATA1) + framepid = 0x1; + else + framepid = 0; + + if (framepid != ep->data01) { + dev_vdbg(udc->dev, "the data01 error!\n"); + } else { + fsize = frame_get_length(pframe); + + cp = (u8 *)(req->req.buf) + req->req.actual; + if (cp) { + memcpy(cp, pframe->data, fsize); + req->req.actual += fsize; + if ((fsize < ep->ep.maxpacket) + || (req->req.actual >= + req->req.length)) { + finish_req = 1; + done(ep, req, 0); + if (list_empty(&ep->queue)) + qe_eprx_nack(ep); + } + } + qe_ep_toggledata01(ep); + } + } else { + dev_err(udc->dev, "The receive frame with error!\n"); + } + + /* note: don't clear the rxbd's buffer address * + * only Clear the length */ + out_be32((u32 __iomem *)bd, (bdstatus & BD_STATUS_MASK)); + ep->has_data--; + + /* Get next BD */ + if (bdstatus & R_W) + bd = ep->rxbase; + else + bd++; + + bdstatus = in_be32((u32 __iomem *)bd); + length = bdstatus & BD_LENGTH_MASK; + } + + ep->n_rxbd = bd; + ep_recycle_rxbds(ep); + + return 0; +} + +/* only add the request in queue */ +static int ep_req_receive(struct qe_ep *ep, struct qe_req *req) +{ + if (ep->state == EP_STATE_NACK) { + if (ep->has_data <= 0) { + /* Enable rx and unmask rx interrupt */ + qe_eprx_normal(ep); + } else { + /* Copy the exist BD data */ + ep_req_rx(ep, req); + } + } + + return 0; +} + +/******************************************************************** + Internal Used Function End +********************************************************************/ + +/*----------------------------------------------------------------------- + Endpoint Management Functions For Gadget + -----------------------------------------------------------------------*/ +static int qe_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) +{ + struct qe_udc *udc; + struct qe_ep *ep; + int retval = 0; + unsigned char epnum; + + ep = container_of(_ep, struct qe_ep, ep); + + /* catch various bogus parameters */ + if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] || + (desc->bDescriptorType != USB_DT_ENDPOINT)) + return -EINVAL; + + udc = ep->udc; + if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) + return -ESHUTDOWN; + + epnum = (u8)desc->bEndpointAddress & 0xF; + + retval = qe_ep_init(udc, epnum, desc); + if (retval != 0) { + cpm_muram_free(cpm_muram_offset(ep->rxbase)); + dev_dbg(udc->dev, "enable ep%d failed\n", ep->epnum); + return -EINVAL; + } + dev_dbg(udc->dev, "enable ep%d successful\n", ep->epnum); + return 0; +} + +static int qe_ep_disable(struct usb_ep *_ep) +{ + struct qe_udc *udc; + struct qe_ep *ep; + unsigned long flags; + unsigned int size; + + ep = container_of(_ep, struct qe_ep, ep); + udc = ep->udc; + + if (!_ep || !ep->desc) { + dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL); + return -EINVAL; + } + + spin_lock_irqsave(&udc->lock, flags); + /* Nuke all pending requests (does flush) */ + nuke(ep, -ESHUTDOWN); + ep->desc = NULL; + ep->stopped = 1; + spin_unlock_irqrestore(&udc->lock, flags); + + cpm_muram_free(cpm_muram_offset(ep->rxbase)); + + if (ep->dir == USB_DIR_OUT) + size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * + (USB_BDRING_LEN_RX + 1); + else + size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * + (USB_BDRING_LEN + 1); + + if (ep->dir != USB_DIR_IN) { + kfree(ep->rxframe); + if (ep->rxbufmap) { + dma_unmap_single(udc_controller->gadget.dev.parent, + ep->rxbuf_d, size, + DMA_FROM_DEVICE); + ep->rxbuf_d = DMA_ADDR_INVALID; + } else { + dma_sync_single_for_cpu( + udc_controller->gadget.dev.parent, + ep->rxbuf_d, size, + DMA_FROM_DEVICE); + } + kfree(ep->rxbuffer); + } + + if (ep->dir != USB_DIR_OUT) + kfree(ep->txframe); + + dev_dbg(udc->dev, "disabled %s OK\n", _ep->name); + return 0; +} + +static struct usb_request *qe_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) +{ + struct qe_req *req; + + req = kzalloc(sizeof(*req), gfp_flags); + if (!req) + return NULL; + + req->req.dma = DMA_ADDR_INVALID; + + INIT_LIST_HEAD(&req->queue); + + return &req->req; +} + +static void qe_free_request(struct usb_ep *_ep, struct usb_request *_req) +{ + struct qe_req *req; + + req = container_of(_req, struct qe_req, req); + + if (_req) + kfree(req); +} + +/* queues (submits) an I/O request to an endpoint */ +static int qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req, + gfp_t gfp_flags) +{ + struct qe_ep *ep = container_of(_ep, struct qe_ep, ep); + struct qe_req *req = container_of(_req, struct qe_req, req); + struct qe_udc *udc; + unsigned long flags; + int reval; + + udc = ep->udc; + /* catch various bogus parameters */ + if (!_req || !req->req.complete || !req->req.buf + || !list_empty(&req->queue)) { + dev_dbg(udc->dev, "bad params\n"); + return -EINVAL; + } + if (!_ep || (!ep->desc && ep_index(ep))) { + dev_dbg(udc->dev, "bad ep\n"); + return -EINVAL; + } + + if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + req->ep = ep; + + /* map virtual address to hardware */ + if (req->req.dma == DMA_ADDR_INVALID) { + req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, + req->req.buf, + req->req.length, + ep_is_in(ep) + ? DMA_TO_DEVICE : + DMA_FROM_DEVICE); + req->mapped = 1; + } else { + dma_sync_single_for_device(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + ep_is_in(ep) + ? DMA_TO_DEVICE : + DMA_FROM_DEVICE); + req->mapped = 0; + } + + req->req.status = -EINPROGRESS; + req->req.actual = 0; + + list_add_tail(&req->queue, &ep->queue); + dev_vdbg(udc->dev, "gadget have request in %s! %d\n", + ep->name, req->req.length); + spin_lock_irqsave(&udc->lock, flags); + /* push the request to device */ + if (ep_is_in(ep)) + reval = ep_req_send(ep, req); + + /* EP0 */ + if (ep_index(ep) == 0 && req->req.length > 0) { + if (ep_is_in(ep)) + udc->ep0_state = DATA_STATE_XMIT; + else + udc->ep0_state = DATA_STATE_RECV; + } + + if (ep->dir == USB_DIR_OUT) + reval = ep_req_receive(ep, req); + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +/* dequeues (cancels, unlinks) an I/O request from an endpoint */ +static int qe_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct qe_ep *ep = container_of(_ep, struct qe_ep, ep); + struct qe_req *req; + unsigned long flags; + + if (!_ep || !_req) + return -EINVAL; + + spin_lock_irqsave(&ep->udc->lock, flags); + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + + if (&req->req != _req) { + spin_unlock_irqrestore(&ep->udc->lock, flags); + return -EINVAL; + } + + done(ep, req, -ECONNRESET); + + spin_unlock_irqrestore(&ep->udc->lock, flags); + return 0; +} + +/*----------------------------------------------------------------- + * modify the endpoint halt feature + * @ep: the non-isochronous endpoint being stalled + * @value: 1--set halt 0--clear halt + * Returns zero, or a negative error code. +*----------------------------------------------------------------*/ +static int qe_ep_set_halt(struct usb_ep *_ep, int value) +{ + struct qe_ep *ep; + unsigned long flags; + int status = -EOPNOTSUPP; + struct qe_udc *udc; + + ep = container_of(_ep, struct qe_ep, ep); + if (!_ep || !ep->desc) { + status = -EINVAL; + goto out; + } + + udc = ep->udc; + /* Attempt to halt IN ep will fail if any transfer requests + * are still queue */ + if (value && ep_is_in(ep) && !list_empty(&ep->queue)) { + status = -EAGAIN; + goto out; + } + + status = 0; + spin_lock_irqsave(&ep->udc->lock, flags); + qe_eptx_stall_change(ep, value); + qe_eprx_stall_change(ep, value); + spin_unlock_irqrestore(&ep->udc->lock, flags); + + if (ep->epnum == 0) { + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; + } + + /* set data toggle to DATA0 on clear halt */ + if (value == 0) + ep->data01 = 0; +out: + dev_vdbg(udc->dev, "%s %s halt stat %d\n", ep->ep.name, + value ? "set" : "clear", status); + + return status; +} + +static struct usb_ep_ops qe_ep_ops = { + .enable = qe_ep_enable, + .disable = qe_ep_disable, + + .alloc_request = qe_alloc_request, + .free_request = qe_free_request, + + .queue = qe_ep_queue, + .dequeue = qe_ep_dequeue, + + .set_halt = qe_ep_set_halt, +}; + +/*------------------------------------------------------------------------ + Gadget Driver Layer Operations + ------------------------------------------------------------------------*/ + +/* Get the current frame number */ +static int qe_get_frame(struct usb_gadget *gadget) +{ + u16 tmp; + + tmp = in_be16(&udc_controller->usb_param->frame_n); + if (tmp & 0x8000) + tmp = tmp & 0x07ff; + else + tmp = -EINVAL; + + return (int)tmp; +} + +/* Tries to wake up the host connected to this gadget + * + * Return : 0-success + * Negative-this feature not enabled by host or not supported by device hw + */ +static int qe_wakeup(struct usb_gadget *gadget) +{ + return -ENOTSUPP; +} + +/* Notify controller that VBUS is powered, Called by whatever + detects VBUS sessions */ +static int qe_vbus_session(struct usb_gadget *gadget, int is_active) +{ + return -ENOTSUPP; +} + +/* constrain controller's VBUS power usage + * This call is used by gadget drivers during SET_CONFIGURATION calls, + * reporting how much power the device may consume. For example, this + * could affect how quickly batteries are recharged. + * + * Returns zero on success, else negative errno. + */ +static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA) +{ + return -ENOTSUPP; +} + +/* Change Data+ pullup status + * this func is used by usb_gadget_connect/disconnect + */ +static int qe_pullup(struct usb_gadget *gadget, int is_on) +{ + return -ENOTSUPP; +} + +/* defined in usb_gadget.h */ +static struct usb_gadget_ops qe_gadget_ops = { + .get_frame = qe_get_frame, + .wakeup = qe_wakeup, +/* .set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */ + .vbus_session = qe_vbus_session, + .vbus_draw = qe_vbus_draw, + .pullup = qe_pullup, +}; + +/*------------------------------------------------------------------------- + USB ep0 Setup process in BUS Enumeration + -------------------------------------------------------------------------*/ +static int udc_reset_ep_queue(struct qe_udc *udc, u8 pipe) +{ + struct qe_ep *ep = &udc->eps[pipe]; + + nuke(ep, -ECONNRESET); + ep->tx_req = NULL; + return 0; +} + +static int reset_queues(struct qe_udc *udc) +{ + u8 pipe; + + for (pipe = 0; pipe < USB_MAX_ENDPOINTS; pipe++) + udc_reset_ep_queue(udc, pipe); + + /* report disconnect; the driver is already quiesced */ + spin_unlock(&udc->lock); + udc->driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); + + return 0; +} + +static void ch9setaddress(struct qe_udc *udc, u16 value, u16 index, + u16 length) +{ + /* Save the new address to device struct */ + udc->device_address = (u8) value; + /* Update usb state */ + udc->usb_state = USB_STATE_ADDRESS; + + /* Status phase , send a ZLP */ + if (ep0_prime_status(udc, USB_DIR_IN)) + qe_ep0_stall(udc); +} + +static void ownercomplete(struct usb_ep *_ep, struct usb_request *_req) +{ + struct qe_req *req = container_of(_req, struct qe_req, req); + + req->req.buf = NULL; + kfree(req); +} + +static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value, + u16 index, u16 length) +{ + u16 usb_status = 0; + struct qe_req *req; + struct qe_ep *ep; + int status = 0; + + ep = &udc->eps[0]; + if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) { + /* Get device status */ + usb_status = 1 << USB_DEVICE_SELF_POWERED; + } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { + /* Get interface status */ + /* We don't have interface information in udc driver */ + usb_status = 0; + } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) { + /* Get endpoint status */ + int pipe = index & USB_ENDPOINT_NUMBER_MASK; + struct qe_ep *target_ep = &udc->eps[pipe]; + u16 usep; + + /* stall if endpoint doesn't exist */ + if (!target_ep->desc) + goto stall; + + usep = in_be16(&udc->usb_regs->usb_usep[pipe]); + if (index & USB_DIR_IN) { + if (target_ep->dir != USB_DIR_IN) + goto stall; + if ((usep & USB_THS_MASK) == USB_THS_STALL) + usb_status = 1 << USB_ENDPOINT_HALT; + } else { + if (target_ep->dir != USB_DIR_OUT) + goto stall; + if ((usep & USB_RHS_MASK) == USB_RHS_STALL) + usb_status = 1 << USB_ENDPOINT_HALT; + } + } + + req = container_of(qe_alloc_request(&ep->ep, GFP_KERNEL), + struct qe_req, req); + req->req.length = 2; + req->req.buf = udc->statusbuf; + *(u16 *)req->req.buf = cpu_to_le16(usb_status); + req->req.status = -EINPROGRESS; + req->req.actual = 0; + req->req.complete = ownercomplete; + + udc->ep0_dir = USB_DIR_IN; + + /* data phase */ + status = qe_ep_queue(&ep->ep, &req->req, GFP_ATOMIC); + + if (status == 0) + return; +stall: + dev_err(udc->dev, "Can't respond to getstatus request \n"); + qe_ep0_stall(udc); +} + +/* only handle the setup request, suppose the device in normal status */ +static void setup_received_handle(struct qe_udc *udc, + struct usb_ctrlrequest *setup) +{ + /* Fix Endian (udc->local_setup_buff is cpu Endian now)*/ + u16 wValue = le16_to_cpu(setup->wValue); + u16 wIndex = le16_to_cpu(setup->wIndex); + u16 wLength = le16_to_cpu(setup->wLength); + + /* clear the previous request in the ep0 */ + udc_reset_ep_queue(udc, 0); + + if (setup->bRequestType & USB_DIR_IN) + udc->ep0_dir = USB_DIR_IN; + else + udc->ep0_dir = USB_DIR_OUT; + + switch (setup->bRequest) { + case USB_REQ_GET_STATUS: + /* Data+Status phase form udc */ + if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK)) + != (USB_DIR_IN | USB_TYPE_STANDARD)) + break; + ch9getstatus(udc, setup->bRequestType, wValue, wIndex, + wLength); + return; + + case USB_REQ_SET_ADDRESS: + /* Status phase from udc */ + if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | + USB_RECIP_DEVICE)) + break; + ch9setaddress(udc, wValue, wIndex, wLength); + return; + + case USB_REQ_CLEAR_FEATURE: + case USB_REQ_SET_FEATURE: + /* Requests with no data phase, status phase from udc */ + if ((setup->bRequestType & USB_TYPE_MASK) + != USB_TYPE_STANDARD) + break; + + if ((setup->bRequestType & USB_RECIP_MASK) + == USB_RECIP_ENDPOINT) { + int pipe = wIndex & USB_ENDPOINT_NUMBER_MASK; + struct qe_ep *ep; + + if (wValue != 0 || wLength != 0 + || pipe > USB_MAX_ENDPOINTS) + break; + ep = &udc->eps[pipe]; + + spin_unlock(&udc->lock); + qe_ep_set_halt(&ep->ep, + (setup->bRequest == USB_REQ_SET_FEATURE) + ? 1 : 0); + spin_lock(&udc->lock); + } + + ep0_prime_status(udc, USB_DIR_IN); + + return; + + default: + break; + } + + if (wLength) { + /* Data phase from gadget, status phase from udc */ + if (setup->bRequestType & USB_DIR_IN) { + udc->ep0_state = DATA_STATE_XMIT; + udc->ep0_dir = USB_DIR_IN; + } else { + udc->ep0_state = DATA_STATE_RECV; + udc->ep0_dir = USB_DIR_OUT; + } + spin_unlock(&udc->lock); + if (udc->driver->setup(&udc->gadget, + &udc->local_setup_buff) < 0) + qe_ep0_stall(udc); + spin_lock(&udc->lock); + } else { + /* No data phase, IN status from gadget */ + udc->ep0_dir = USB_DIR_IN; + spin_unlock(&udc->lock); + if (udc->driver->setup(&udc->gadget, + &udc->local_setup_buff) < 0) + qe_ep0_stall(udc); + spin_lock(&udc->lock); + udc->ep0_state = DATA_STATE_NEED_ZLP; + } +} + +/*------------------------------------------------------------------------- + USB Interrupt handlers + -------------------------------------------------------------------------*/ +static void suspend_irq(struct qe_udc *udc) +{ + udc->resume_state = udc->usb_state; + udc->usb_state = USB_STATE_SUSPENDED; + + /* report suspend to the driver ,serial.c not support this*/ + if (udc->driver->suspend) + udc->driver->suspend(&udc->gadget); +} + +static void resume_irq(struct qe_udc *udc) +{ + udc->usb_state = udc->resume_state; + udc->resume_state = 0; + + /* report resume to the driver , serial.c not support this*/ + if (udc->driver->resume) + udc->driver->resume(&udc->gadget); +} + +static void idle_irq(struct qe_udc *udc) +{ + u8 usbs; + + usbs = in_8(&udc->usb_regs->usb_usbs); + if (usbs & USB_IDLE_STATUS_MASK) { + if ((udc->usb_state) != USB_STATE_SUSPENDED) + suspend_irq(udc); + } else { + if (udc->usb_state == USB_STATE_SUSPENDED) + resume_irq(udc); + } +} + +static int reset_irq(struct qe_udc *udc) +{ + unsigned char i; + + qe_usb_disable(); + out_8(&udc->usb_regs->usb_usadr, 0); + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) { + if (udc->eps[i].init) + qe_ep_reset(udc, i); + } + + reset_queues(udc); + udc->usb_state = USB_STATE_DEFAULT; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = USB_DIR_OUT; + qe_usb_enable(); + return 0; +} + +static int bsy_irq(struct qe_udc *udc) +{ + return 0; +} + +static int txe_irq(struct qe_udc *udc) +{ + return 0; +} + +/* ep0 tx interrupt also in here */ +static int tx_irq(struct qe_udc *udc) +{ + struct qe_ep *ep; + struct qe_bd __iomem *bd; + int i, res = 0; + + if ((udc->usb_state == USB_STATE_ADDRESS) + && (in_8(&udc->usb_regs->usb_usadr) == 0)) + out_8(&udc->usb_regs->usb_usadr, udc->device_address); + + for (i = (USB_MAX_ENDPOINTS-1); ((i >= 0) && (res == 0)); i--) { + ep = &udc->eps[i]; + if (ep && ep->init && (ep->dir != USB_DIR_OUT)) { + bd = ep->c_txbd; + if (!(in_be32((u32 __iomem *)bd) & T_R) + && (in_be32(&bd->buf))) { + /* confirm the transmitted bd */ + if (ep->epnum == 0) + res = qe_ep0_txconf(ep); + else + res = qe_ep_txconf(ep); + } + } + } + return res; +} + + +/* setup packect's rx is handle in the function too */ +static void rx_irq(struct qe_udc *udc) +{ + struct qe_ep *ep; + struct qe_bd __iomem *bd; + int i; + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) { + ep = &udc->eps[i]; + if (ep && ep->init && (ep->dir != USB_DIR_IN)) { + bd = ep->n_rxbd; + if (!(in_be32((u32 __iomem *)bd) & R_E) + && (in_be32(&bd->buf))) { + if (ep->epnum == 0) { + qe_ep0_rx(udc); + } else { + /*non-setup package receive*/ + qe_ep_rx(ep); + } + } + } + } +} + +static irqreturn_t qe_udc_irq(int irq, void *_udc) +{ + struct qe_udc *udc = (struct qe_udc *)_udc; + u16 irq_src; + irqreturn_t status = IRQ_NONE; + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + + irq_src = in_be16(&udc->usb_regs->usb_usber) & + in_be16(&udc->usb_regs->usb_usbmr); + /* Clear notification bits */ + out_be16(&udc->usb_regs->usb_usber, irq_src); + /* USB Interrupt */ + if (irq_src & USB_E_IDLE_MASK) { + idle_irq(udc); + irq_src &= ~USB_E_IDLE_MASK; + status = IRQ_HANDLED; + } + + if (irq_src & USB_E_TXB_MASK) { + tx_irq(udc); + irq_src &= ~USB_E_TXB_MASK; + status = IRQ_HANDLED; + } + + if (irq_src & USB_E_RXB_MASK) { + rx_irq(udc); + irq_src &= ~USB_E_RXB_MASK; + status = IRQ_HANDLED; + } + + if (irq_src & USB_E_RESET_MASK) { + reset_irq(udc); + irq_src &= ~USB_E_RESET_MASK; + status = IRQ_HANDLED; + } + + if (irq_src & USB_E_BSY_MASK) { + bsy_irq(udc); + irq_src &= ~USB_E_BSY_MASK; + status = IRQ_HANDLED; + } + + if (irq_src & USB_E_TXE_MASK) { + txe_irq(udc); + irq_src &= ~USB_E_TXE_MASK; + status = IRQ_HANDLED; + } + + spin_unlock_irqrestore(&udc->lock, flags); + + return status; +} + +/*------------------------------------------------------------------------- + Gadget driver register and unregister. + --------------------------------------------------------------------------*/ +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + int retval; + unsigned long flags = 0; + + /* standard operations */ + if (!udc_controller) + return -ENODEV; + + if (!driver || (driver->speed != USB_SPEED_FULL + && driver->speed != USB_SPEED_HIGH) + || !driver->bind || !driver->disconnect + || !driver->setup) + return -EINVAL; + + if (udc_controller->driver) + return -EBUSY; + + /* lock is needed but whether should use this lock or another */ + spin_lock_irqsave(&udc_controller->lock, flags); + + driver->driver.bus = NULL; + /* hook up the driver */ + udc_controller->driver = driver; + udc_controller->gadget.dev.driver = &driver->driver; + udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed); + spin_unlock_irqrestore(&udc_controller->lock, flags); + + retval = driver->bind(&udc_controller->gadget); + if (retval) { + dev_err(udc_controller->dev, "bind to %s --> %d", + driver->driver.name, retval); + udc_controller->gadget.dev.driver = NULL; + udc_controller->driver = NULL; + return retval; + } + + /* Enable IRQ reg and Set usbcmd reg EN bit */ + qe_usb_enable(); + + out_be16(&udc_controller->usb_regs->usb_usber, 0xffff); + out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE); + udc_controller->usb_state = USB_STATE_ATTACHED; + udc_controller->ep0_state = WAIT_FOR_SETUP; + udc_controller->ep0_dir = USB_DIR_OUT; + dev_info(udc_controller->dev, "%s bind to driver %s \n", + udc_controller->gadget.name, driver->driver.name); + return 0; +} +EXPORT_SYMBOL(usb_gadget_register_driver); + +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct qe_ep *loop_ep; + unsigned long flags; + + if (!udc_controller) + return -ENODEV; + + if (!driver || driver != udc_controller->driver) + return -EINVAL; + + /* stop usb controller, disable intr */ + qe_usb_disable(); + + /* in fact, no needed */ + udc_controller->usb_state = USB_STATE_ATTACHED; + udc_controller->ep0_state = WAIT_FOR_SETUP; + udc_controller->ep0_dir = 0; + + /* stand operation */ + spin_lock_irqsave(&udc_controller->lock, flags); + udc_controller->gadget.speed = USB_SPEED_UNKNOWN; + nuke(&udc_controller->eps[0], -ESHUTDOWN); + list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list, + ep.ep_list) + nuke(loop_ep, -ESHUTDOWN); + spin_unlock_irqrestore(&udc_controller->lock, flags); + + /* unbind gadget and unhook driver. */ + driver->unbind(&udc_controller->gadget); + udc_controller->gadget.dev.driver = NULL; + udc_controller->driver = NULL; + + dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n", + driver->driver.name); + return 0; +} +EXPORT_SYMBOL(usb_gadget_unregister_driver); + +/* udc structure's alloc and setup, include ep-param alloc */ +static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) +{ + struct qe_udc *udc; + struct device_node *np = ofdev->node; + unsigned int tmp_addr = 0; + struct usb_device_para __iomem *usbpram; + unsigned int i; + u64 size; + u32 offset; + + udc = kzalloc(sizeof(*udc), GFP_KERNEL); + if (udc == NULL) { + dev_err(&ofdev->dev, "malloc udc failed\n"); + goto cleanup; + } + + udc->dev = &ofdev->dev; + + /* get default address of usb parameter in MURAM from device tree */ + offset = *of_get_address(np, 1, &size, NULL); + udc->usb_param = cpm_muram_addr(offset); + memset_io(udc->usb_param, 0, size); + + usbpram = udc->usb_param; + out_be16(&usbpram->frame_n, 0); + out_be32(&usbpram->rstate, 0); + + tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS * + sizeof(struct usb_ep_para)), + USB_EP_PARA_ALIGNMENT); + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) { + out_be16(&usbpram->epptr[i], (u16)tmp_addr); + udc->ep_param[i] = cpm_muram_addr(tmp_addr); + tmp_addr += 32; + } + + memset_io(udc->ep_param[0], 0, + USB_MAX_ENDPOINTS * sizeof(struct usb_ep_para)); + + udc->resume_state = USB_STATE_NOTATTACHED; + udc->usb_state = USB_STATE_POWERED; + udc->ep0_dir = 0; + + spin_lock_init(&udc->lock); + return udc; + +cleanup: + kfree(udc); + return NULL; +} + +/* USB Controller register init */ +static int __devinit qe_udc_reg_init(struct qe_udc *udc) +{ + struct usb_ctlr __iomem *qe_usbregs; + qe_usbregs = udc->usb_regs; + + /* Init the usb register */ + out_8(&qe_usbregs->usb_usmod, 0x01); + out_be16(&qe_usbregs->usb_usbmr, 0); + out_8(&qe_usbregs->usb_uscom, 0); + out_be16(&qe_usbregs->usb_usber, USBER_ALL_CLEAR); + + return 0; +} + +static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) +{ + struct qe_ep *ep = &udc->eps[pipe_num]; + + ep->udc = udc; + strcpy(ep->name, ep_name[pipe_num]); + ep->ep.name = ep_name[pipe_num]; + + ep->ep.ops = &qe_ep_ops; + ep->stopped = 1; + ep->ep.maxpacket = (unsigned short) ~0; + ep->desc = NULL; + ep->dir = 0xff; + ep->epnum = (u8)pipe_num; + ep->sent = 0; + ep->last = 0; + ep->init = 0; + ep->rxframe = NULL; + ep->txframe = NULL; + ep->tx_req = NULL; + ep->state = EP_STATE_IDLE; + ep->has_data = 0; + + /* the queue lists any req for this ep */ + INIT_LIST_HEAD(&ep->queue); + + /* gagdet.ep_list used for ep_autoconfig so no ep0*/ + if (pipe_num != 0) + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + + ep->gadget = &udc->gadget; + + return 0; +} + +/*----------------------------------------------------------------------- + * UDC device Driver operation functions * + *----------------------------------------------------------------------*/ +static void qe_udc_release(struct device *dev) +{ + int i = 0; + + complete(udc_controller->done); + cpm_muram_free(cpm_muram_offset(udc_controller->ep_param[0])); + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + udc_controller->ep_param[i] = NULL; + + kfree(udc_controller); + udc_controller = NULL; +} + +/* Driver probe functions */ +static int __devinit qe_udc_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + struct device_node *np = ofdev->node; + struct qe_ep *ep; + unsigned int ret = 0; + unsigned int i; + const void *prop; + + prop = of_get_property(np, "mode", NULL); + if (!prop || strcmp(prop, "peripheral")) + return -ENODEV; + + /* Initialize the udc structure including QH member and other member */ + udc_controller = qe_udc_config(ofdev); + if (!udc_controller) { + dev_dbg(&ofdev->dev, "udc_controll is NULL\n"); + return -ENOMEM; + } + + udc_controller->soc_type = (unsigned long)match->data; + udc_controller->usb_regs = of_iomap(np, 0); + if (!udc_controller->usb_regs) { + ret = -ENOMEM; + goto err1; + } + + /* initialize usb hw reg except for regs for EP, + * leave usbintr reg untouched*/ + qe_udc_reg_init(udc_controller); + + /* here comes the stand operations for probe + * set the qe_udc->gadget.xxx */ + udc_controller->gadget.ops = &qe_gadget_ops; + + /* gadget.ep0 is a pointer */ + udc_controller->gadget.ep0 = &udc_controller->eps[0].ep; + + INIT_LIST_HEAD(&udc_controller->gadget.ep_list); + + /* modify in register gadget process */ + udc_controller->gadget.speed = USB_SPEED_UNKNOWN; + + /* name: Identifies the controller hardware type. */ + udc_controller->gadget.name = driver_name; + + device_initialize(&udc_controller->gadget.dev); + + strcpy(udc_controller->gadget.dev.bus_id, "gadget"); + + udc_controller->gadget.dev.release = qe_udc_release; + udc_controller->gadget.dev.parent = &ofdev->dev; + + /* initialize qe_ep struct */ + for (i = 0; i < USB_MAX_ENDPOINTS ; i++) { + /* because the ep type isn't decide here so + * qe_ep_init() should be called in ep_enable() */ + + /* setup the qe_ep struct and link ep.ep.list + * into gadget.ep_list */ + qe_ep_config(udc_controller, (unsigned char)i); + } + + /* ep0 initialization in here */ + ret = qe_ep_init(udc_controller, 0, &qe_ep0_desc); + if (ret) + goto err2; + + /* create a buf for ZLP send, need to remain zeroed */ + udc_controller->nullbuf = kzalloc(256, GFP_KERNEL); + if (udc_controller->nullbuf == NULL) { + dev_dbg(udc_controller->dev, "cannot alloc nullbuf\n"); + ret = -ENOMEM; + goto err3; + } + + /* buffer for data of get_status request */ + udc_controller->statusbuf = kzalloc(2, GFP_KERNEL); + if (udc_controller->statusbuf == NULL) { + ret = -ENOMEM; + goto err4; + } + + udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf); + if (udc_controller->nullp == DMA_ADDR_INVALID) { + udc_controller->nullp = dma_map_single( + udc_controller->gadget.dev.parent, + udc_controller->nullbuf, + 256, + DMA_TO_DEVICE); + udc_controller->nullmap = 1; + } else { + dma_sync_single_for_device(udc_controller->gadget.dev.parent, + udc_controller->nullp, 256, + DMA_TO_DEVICE); + } + + tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet, + (unsigned long)udc_controller); + /* request irq and disable DR */ + udc_controller->usb_irq = irq_of_parse_and_map(np, 0); + + ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0, + driver_name, udc_controller); + if (ret) { + dev_err(udc_controller->dev, "cannot request irq %d err %d \n", + udc_controller->usb_irq, ret); + goto err5; + } + + ret = device_add(&udc_controller->gadget.dev); + if (ret) + goto err6; + + dev_info(udc_controller->dev, + "%s USB controller initialized as device\n", + (udc_controller->soc_type == PORT_QE) ? "QE" : "CPM"); + return 0; + +err6: + free_irq(udc_controller->usb_irq, udc_controller); +err5: + if (udc_controller->nullmap) { + dma_unmap_single(udc_controller->gadget.dev.parent, + udc_controller->nullp, 256, + DMA_TO_DEVICE); + udc_controller->nullp = DMA_ADDR_INVALID; + } else { + dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, + udc_controller->nullp, 256, + DMA_TO_DEVICE); + } + kfree(udc_controller->statusbuf); +err4: + kfree(udc_controller->nullbuf); +err3: + ep = &udc_controller->eps[0]; + cpm_muram_free(cpm_muram_offset(ep->rxbase)); + kfree(ep->rxframe); + kfree(ep->rxbuffer); + kfree(ep->txframe); +err2: + iounmap(udc_controller->usb_regs); +err1: + kfree(udc_controller); + + return ret; +} + +#ifdef CONFIG_PM +static int qe_udc_suspend(struct of_device *dev, pm_message_t state) +{ + return -ENOTSUPP; +} + +static int qe_udc_resume(struct of_device *dev) +{ + return -ENOTSUPP; +} +#endif + +static int __devexit qe_udc_remove(struct of_device *ofdev) +{ + struct qe_ep *ep; + unsigned int size; + + DECLARE_COMPLETION(done); + + if (!udc_controller) + return -ENODEV; + + udc_controller->done = &done; + tasklet_disable(&udc_controller->rx_tasklet); + + if (udc_controller->nullmap) { + dma_unmap_single(udc_controller->gadget.dev.parent, + udc_controller->nullp, 256, + DMA_TO_DEVICE); + udc_controller->nullp = DMA_ADDR_INVALID; + } else { + dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, + udc_controller->nullp, 256, + DMA_TO_DEVICE); + } + kfree(udc_controller->statusbuf); + kfree(udc_controller->nullbuf); + + ep = &udc_controller->eps[0]; + cpm_muram_free(cpm_muram_offset(ep->rxbase)); + size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1); + + kfree(ep->rxframe); + if (ep->rxbufmap) { + dma_unmap_single(udc_controller->gadget.dev.parent, + ep->rxbuf_d, size, + DMA_FROM_DEVICE); + ep->rxbuf_d = DMA_ADDR_INVALID; + } else { + dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, + ep->rxbuf_d, size, + DMA_FROM_DEVICE); + } + + kfree(ep->rxbuffer); + kfree(ep->txframe); + + free_irq(udc_controller->usb_irq, udc_controller); + + tasklet_kill(&udc_controller->rx_tasklet); + + iounmap(udc_controller->usb_regs); + + device_unregister(&udc_controller->gadget.dev); + /* wait for release() of gadget.dev to free udc */ + wait_for_completion(&done); + + return 0; +} + +/*-------------------------------------------------------------------------*/ +static struct of_device_id __devinitdata qe_udc_match[] = { + { + .compatible = "fsl,mpc8360-qe-usb", + .data = (void *)PORT_QE, + }, + { + .compatible = "fsl,mpc8272-cpm-usb", + .data = (void *)PORT_CPM, + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, qe_udc_match); + +static struct of_platform_driver udc_driver = { + .name = (char *)driver_name, + .match_table = qe_udc_match, + .probe = qe_udc_probe, + .remove = __devexit_p(qe_udc_remove), +#ifdef CONFIG_PM + .suspend = qe_udc_suspend, + .resume = qe_udc_resume, +#endif +}; + +static int __init qe_udc_init(void) +{ + printk(KERN_INFO "%s: %s, %s\n", driver_name, driver_desc, + DRIVER_VERSION); + return of_register_platform_driver(&udc_driver); +} + +static void __exit qe_udc_exit(void) +{ + of_unregister_platform_driver(&udc_driver); +} + +module_init(qe_udc_init); +module_exit(qe_udc_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); + diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h new file mode 100644 index 000000000000..31b2710882e4 --- /dev/null +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -0,0 +1,437 @@ +/* + * drivers/usb/gadget/qe_udc.h + * + * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Xiaobo Xie <X.Xie@freescale.com> + * Li Yang <leoli@freescale.com> + * + * Description: + * Freescale USB device/endpoint management registers + * + * 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. + */ + +#ifndef __FSL_QE_UDC_H +#define __FSL_QE_UDC_H + +/* SoC type */ +#define PORT_CPM 0 +#define PORT_QE 1 + +#define USB_MAX_ENDPOINTS 4 +#define USB_MAX_PIPES USB_MAX_ENDPOINTS +#define USB_EP0_MAX_SIZE 64 +#define USB_MAX_CTRL_PAYLOAD 0x4000 +#define USB_BDRING_LEN 16 +#define USB_BDRING_LEN_RX 256 +#define USB_BDRING_LEN_TX 16 +#define MIN_EMPTY_BDS 128 +#define MAX_DATA_BDS 8 +#define USB_CRC_SIZE 2 +#define USB_DIR_BOTH 0x88 +#define R_BUF_MAXSIZE 0x800 +#define USB_EP_PARA_ALIGNMENT 32 + +/* USB Mode Register bit define */ +#define USB_MODE_EN 0x01 +#define USB_MODE_HOST 0x02 +#define USB_MODE_TEST 0x04 +#define USB_MODE_SFTE 0x08 +#define USB_MODE_RESUME 0x40 +#define USB_MODE_LSS 0x80 + +/* USB Slave Address Register Mask */ +#define USB_SLVADDR_MASK 0x7F + +/* USB Endpoint register define */ +#define USB_EPNUM_MASK 0xF000 +#define USB_EPNUM_SHIFT 12 + +#define USB_TRANS_MODE_SHIFT 8 +#define USB_TRANS_CTR 0x0000 +#define USB_TRANS_INT 0x0100 +#define USB_TRANS_BULK 0x0200 +#define USB_TRANS_ISO 0x0300 + +#define USB_EP_MF 0x0020 +#define USB_EP_RTE 0x0010 + +#define USB_THS_SHIFT 2 +#define USB_THS_MASK 0x000c +#define USB_THS_NORMAL 0x0 +#define USB_THS_IGNORE_IN 0x0004 +#define USB_THS_NACK 0x0008 +#define USB_THS_STALL 0x000c + +#define USB_RHS_SHIFT 0 +#define USB_RHS_MASK 0x0003 +#define USB_RHS_NORMAL 0x0 +#define USB_RHS_IGNORE_OUT 0x0001 +#define USB_RHS_NACK 0x0002 +#define USB_RHS_STALL 0x0003 + +#define USB_RTHS_MASK 0x000f + +/* USB Command Register define */ +#define USB_CMD_STR_FIFO 0x80 +#define USB_CMD_FLUSH_FIFO 0x40 +#define USB_CMD_ISFT 0x20 +#define USB_CMD_DSFT 0x10 +#define USB_CMD_EP_MASK 0x03 + +/* USB Event and Mask Register define */ +#define USB_E_MSF_MASK 0x0800 +#define USB_E_SFT_MASK 0x0400 +#define USB_E_RESET_MASK 0x0200 +#define USB_E_IDLE_MASK 0x0100 +#define USB_E_TXE4_MASK 0x0080 +#define USB_E_TXE3_MASK 0x0040 +#define USB_E_TXE2_MASK 0x0020 +#define USB_E_TXE1_MASK 0x0010 +#define USB_E_SOF_MASK 0x0008 +#define USB_E_BSY_MASK 0x0004 +#define USB_E_TXB_MASK 0x0002 +#define USB_E_RXB_MASK 0x0001 +#define USBER_ALL_CLEAR 0x0fff + +#define USB_E_DEFAULT_DEVICE (USB_E_RESET_MASK | USB_E_TXE4_MASK | \ + USB_E_TXE3_MASK | USB_E_TXE2_MASK | \ + USB_E_TXE1_MASK | USB_E_BSY_MASK | \ + USB_E_TXB_MASK | USB_E_RXB_MASK) + +#define USB_E_TXE_MASK (USB_E_TXE4_MASK | USB_E_TXE3_MASK|\ + USB_E_TXE2_MASK | USB_E_TXE1_MASK) +/* USB Status Register define */ +#define USB_IDLE_STATUS_MASK 0x01 + +/* USB Start of Frame Timer */ +#define USB_USSFT_MASK 0x3FFF + +/* USB Frame Number Register */ +#define USB_USFRN_MASK 0xFFFF + +struct usb_device_para{ + u16 epptr[4]; + u32 rstate; + u32 rptr; + u16 frame_n; + u16 rbcnt; + u32 rtemp; + u32 rxusb_data; + u16 rxuptr; + u8 reso[2]; + u32 softbl; + u8 sofucrctemp; +}; + +struct usb_ep_para{ + u16 rbase; + u16 tbase; + u8 rbmr; + u8 tbmr; + u16 mrblr; + u16 rbptr; + u16 tbptr; + u32 tstate; + u32 tptr; + u16 tcrc; + u16 tbcnt; + u32 ttemp; + u16 txusbu_ptr; + u8 reserve[2]; +}; + +#define USB_BUSMODE_GBL 0x20 +#define USB_BUSMODE_BO_MASK 0x18 +#define USB_BUSMODE_BO_SHIFT 0x3 +#define USB_BUSMODE_BE 0x2 +#define USB_BUSMODE_CETM 0x04 +#define USB_BUSMODE_DTB 0x02 + +/* Endpoint basic handle */ +#define ep_index(EP) ((EP)->desc->bEndpointAddress & 0xF) +#define ep_maxpacket(EP) ((EP)->ep.maxpacket) +#define ep_is_in(EP) ((ep_index(EP) == 0) ? (EP->udc->ep0_dir == \ + USB_DIR_IN) : ((EP)->desc->bEndpointAddress \ + & USB_DIR_IN) == USB_DIR_IN) + +/* ep0 transfer state */ +#define WAIT_FOR_SETUP 0 +#define DATA_STATE_XMIT 1 +#define DATA_STATE_NEED_ZLP 2 +#define WAIT_FOR_OUT_STATUS 3 +#define DATA_STATE_RECV 4 + +/* ep tramsfer mode */ +#define USBP_TM_CTL 0 +#define USBP_TM_ISO 1 +#define USBP_TM_BULK 2 +#define USBP_TM_INT 3 + +/*----------------------------------------------------------------------------- + USB RX And TX DATA Frame + -----------------------------------------------------------------------------*/ +struct qe_frame{ + u8 *data; + u32 len; + u32 status; + u32 info; + + void *privdata; + struct list_head node; +}; + +/* Frame structure, info field. */ +#define PID_DATA0 0x80000000 /* Data toggle zero */ +#define PID_DATA1 0x40000000 /* Data toggle one */ +#define PID_SETUP 0x20000000 /* setup bit */ +#define SETUP_STATUS 0x10000000 /* setup status bit */ +#define SETADDR_STATUS 0x08000000 /* setupup address status bit */ +#define NO_REQ 0x04000000 /* Frame without request */ +#define HOST_DATA 0x02000000 /* Host data frame */ +#define FIRST_PACKET_IN_FRAME 0x01000000 /* first packet in the frame */ +#define TOKEN_FRAME 0x00800000 /* Host token frame */ +#define ZLP 0x00400000 /* Zero length packet */ +#define IN_TOKEN_FRAME 0x00200000 /* In token package */ +#define OUT_TOKEN_FRAME 0x00100000 /* Out token package */ +#define SETUP_TOKEN_FRAME 0x00080000 /* Setup token package */ +#define STALL_FRAME 0x00040000 /* Stall handshake */ +#define NACK_FRAME 0x00020000 /* Nack handshake */ +#define NO_PID 0x00010000 /* No send PID */ +#define NO_CRC 0x00008000 /* No send CRC */ +#define HOST_COMMAND 0x00004000 /* Host command frame */ + +/* Frame status field */ +/* Receive side */ +#define FRAME_OK 0x00000000 /* Frame tranmitted or received OK */ +#define FRAME_ERROR 0x80000000 /* Error occured on frame */ +#define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */ +#define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */ +#define RX_ER_NONOCT 0x10000000 /* Rx Non Octet Aligned Packet */ +#define RX_ER_BITSTUFF 0x08000000 /* Frame Aborted --Received packet + with bit stuff error */ +#define RX_ER_CRC 0x04000000 /* Received packet with CRC error */ +#define RX_ER_OVERUN 0x02000000 /* Over-run occured on reception */ +#define RX_ER_PID 0x01000000 /* Wrong PID received */ +/* Tranmit side */ +#define TX_ER_NAK 0x00800000 /* Received NAK handshake */ +#define TX_ER_STALL 0x00400000 /* Received STALL handshake */ +#define TX_ER_TIMEOUT 0x00200000 /* Transmit time out */ +#define TX_ER_UNDERUN 0x00100000 /* Transmit underrun */ +#define FRAME_INPROGRESS 0x00080000 /* Frame is being transmitted */ +#define ER_DATA_UNDERUN 0x00040000 /* Frame is shorter then expected */ +#define ER_DATA_OVERUN 0x00020000 /* Frame is longer then expected */ + +/* QE USB frame operation functions */ +#define frame_get_length(frm) (frm->len) +#define frame_set_length(frm, leng) (frm->len = leng) +#define frame_get_data(frm) (frm->data) +#define frame_set_data(frm, dat) (frm->data = dat) +#define frame_get_info(frm) (frm->info) +#define frame_set_info(frm, inf) (frm->info = inf) +#define frame_get_status(frm) (frm->status) +#define frame_set_status(frm, stat) (frm->status = stat) +#define frame_get_privdata(frm) (frm->privdata) +#define frame_set_privdata(frm, dat) (frm->privdata = dat) + +static inline void qe_frame_clean(struct qe_frame *frm) +{ + frame_set_data(frm, NULL); + frame_set_length(frm, 0); + frame_set_status(frm, FRAME_OK); + frame_set_info(frm, 0); + frame_set_privdata(frm, NULL); +} + +static inline void qe_frame_init(struct qe_frame *frm) +{ + qe_frame_clean(frm); + INIT_LIST_HEAD(&(frm->node)); +} + +struct qe_req { + struct usb_request req; + struct list_head queue; + /* ep_queue() func will add + a request->queue into a udc_ep->queue 'd tail */ + struct qe_ep *ep; + unsigned mapped:1; +}; + +struct qe_ep { + struct usb_ep ep; + struct list_head queue; + struct qe_udc *udc; + const struct usb_endpoint_descriptor *desc; + struct usb_gadget *gadget; + + u8 state; + + struct qe_bd __iomem *rxbase; + struct qe_bd __iomem *n_rxbd; + struct qe_bd __iomem *e_rxbd; + + struct qe_bd __iomem *txbase; + struct qe_bd __iomem *n_txbd; + struct qe_bd __iomem *c_txbd; + + struct qe_frame *rxframe; + u8 *rxbuffer; + dma_addr_t rxbuf_d; + u8 rxbufmap; + unsigned char localnack; + int has_data; + + struct qe_frame *txframe; + struct qe_req *tx_req; + int sent; /*data already sent */ + int last; /*data sent in the last time*/ + + u8 dir; + u8 epnum; + u8 tm; /* transfer mode */ + u8 data01; + u8 init; + + u8 already_seen; + u8 enable_tasklet; + u8 setup_stage; + u32 last_io; /* timestamp */ + + char name[14]; + + unsigned double_buf:1; + unsigned stopped:1; + unsigned fnf:1; + unsigned has_dma:1; + + u8 ackwait; + u8 dma_channel; + u16 dma_counter; + int lch; + + struct timer_list timer; +}; + +struct qe_udc { + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + struct device *dev; + struct qe_ep eps[USB_MAX_ENDPOINTS]; + struct usb_ctrlrequest local_setup_buff; + spinlock_t lock; /* lock for set/config qe_udc */ + unsigned long soc_type; /* QE or CPM soc */ + + struct qe_req *status_req; /* ep0 status request */ + + /* USB and EP Parameter Block pointer */ + struct usb_device_para __iomem *usb_param; + struct usb_ep_para __iomem *ep_param[4]; + + u32 max_pipes; /* Device max pipes */ + u32 max_use_endpts; /* Max endpointes to be used */ + u32 bus_reset; /* Device is bus reseting */ + u32 resume_state; /* USB state to resume*/ + u32 usb_state; /* USB current state */ + u32 usb_next_state; /* USB next state */ + u32 ep0_state; /* Enpoint zero state */ + u32 ep0_dir; /* Enpoint zero direction: can be + USB_DIR_IN or USB_DIR_OUT*/ + u32 usb_sof_count; /* SOF count */ + u32 errors; /* USB ERRORs count */ + + u8 *tmpbuf; + u32 c_start; + u32 c_end; + + u8 *nullbuf; + u8 *statusbuf; + dma_addr_t nullp; + u8 nullmap; + u8 device_address; /* Device USB address */ + + unsigned int usb_clock; + unsigned int usb_irq; + struct usb_ctlr __iomem *usb_regs; + + struct tasklet_struct rx_tasklet; + + struct completion *done; /* to make sure release() is done */ +}; + +#define EP_STATE_IDLE 0 +#define EP_STATE_NACK 1 +#define EP_STATE_STALL 2 + +/* + * transmit BD's status + */ +#define T_R 0x80000000 /* ready bit */ +#define T_W 0x20000000 /* wrap bit */ +#define T_I 0x10000000 /* interrupt on completion */ +#define T_L 0x08000000 /* last */ +#define T_TC 0x04000000 /* transmit CRC */ +#define T_CNF 0x02000000 /* wait for transmit confirm */ +#define T_LSP 0x01000000 /* Low-speed transaction */ +#define T_PID 0x00c00000 /* packet id */ +#define T_NAK 0x00100000 /* No ack. */ +#define T_STAL 0x00080000 /* Stall recieved */ +#define T_TO 0x00040000 /* time out */ +#define T_UN 0x00020000 /* underrun */ + +#define DEVICE_T_ERROR (T_UN | T_TO) +#define HOST_T_ERROR (T_UN | T_TO | T_NAK | T_STAL) +#define DEVICE_T_BD_MASK DEVICE_T_ERROR +#define HOST_T_BD_MASK HOST_T_ERROR + +#define T_PID_SHIFT 6 +#define T_PID_DATA0 0x00800000 /* Data 0 toggle */ +#define T_PID_DATA1 0x00c00000 /* Data 1 toggle */ + +/* + * receive BD's status + */ +#define R_E 0x80000000 /* buffer empty */ +#define R_W 0x20000000 /* wrap bit */ +#define R_I 0x10000000 /* interrupt on reception */ +#define R_L 0x08000000 /* last */ +#define R_F 0x04000000 /* first */ +#define R_PID 0x00c00000 /* packet id */ +#define R_NO 0x00100000 /* Rx Non Octet Aligned Packet */ +#define R_AB 0x00080000 /* Frame Aborted */ +#define R_CR 0x00040000 /* CRC Error */ +#define R_OV 0x00020000 /* Overrun */ + +#define R_ERROR (R_NO | R_AB | R_CR | R_OV) +#define R_BD_MASK R_ERROR + +#define R_PID_DATA0 0x00000000 +#define R_PID_DATA1 0x00400000 +#define R_PID_SETUP 0x00800000 + +#define CPM_USB_STOP_TX 0x2e600000 +#define CPM_USB_RESTART_TX 0x2e600000 +#define CPM_USB_STOP_TX_OPCODE 0x0a +#define CPM_USB_RESTART_TX_OPCODE 0x0b +#define CPM_USB_EP_SHIFT 5 + +#ifndef CONFIG_CPM +inline int cpm_command(u32 command, u8 opcode) +{ + return -EOPNOTSUPP; +} +#endif + +#ifndef CONFIG_QUICC_ENGINE +inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, + u32 cmd_input) +{ + return -EOPNOTSUPP; +} +#endif + +#endif /* __FSL_QE_UDC_H */ diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 45ad556169f1..091bb55c9aa7 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -23,11 +23,8 @@ #include <linux/ioport.h> #include <linux/types.h> #include <linux/errno.h> -#include <linux/delay.h> -#include <linux/sched.h> #include <linux/slab.h> #include <linux/init.h> -#include <linux/timer.h> #include <linux/list.h> #include <linux/interrupt.h> #include <linux/proc_fs.h> @@ -44,11 +41,9 @@ #include <asm/byteorder.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/system.h> #include <asm/unaligned.h> #include <asm/dma.h> -#include <asm/cacheflush.h> #include "fsl_usb2_udc.h" @@ -61,8 +56,8 @@ static const char driver_name[] = "fsl-usb2-udc"; static const char driver_desc[] = DRIVER_DESC; -volatile static struct usb_dr_device *dr_regs = NULL; -volatile static struct usb_sys_interface *usb_sys_regs = NULL; +static struct usb_dr_device *dr_regs; +static struct usb_sys_interface *usb_sys_regs; /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; @@ -76,16 +71,14 @@ fsl_ep0_desc = { .wMaxPacketSize = USB_MAX_CTRL_PAYLOAD, }; -static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state); -static int fsl_udc_resume(struct platform_device *pdev); static void fsl_ep_fifo_flush(struct usb_ep *_ep); #ifdef CONFIG_PPC32 #define fsl_readl(addr) in_le32(addr) -#define fsl_writel(addr, val32) out_le32(val32, addr) +#define fsl_writel(val32, addr) out_le32(addr, val32) #else #define fsl_readl(addr) readl(addr) -#define fsl_writel(addr, val32) writel(addr, val32) +#define fsl_writel(val32, addr) writel(val32, addr) #endif /******************************************************************** @@ -185,10 +178,6 @@ static int dr_controller_setup(struct fsl_udc *udc) unsigned long timeout; #define FSL_UDC_RESET_TIMEOUT 1000 - /* before here, make sure dr_regs has been initialized */ - if (!udc) - return -EINVAL; - /* Stop and reset the usb controller */ tmp = fsl_readl(&dr_regs->usbcmd); tmp &= ~USB_CMD_RUN_STOP; @@ -202,7 +191,7 @@ static int dr_controller_setup(struct fsl_udc *udc) timeout = jiffies + FSL_UDC_RESET_TIMEOUT; while (fsl_readl(&dr_regs->usbcmd) & USB_CMD_CTRL_RESET) { if (time_after(jiffies, timeout)) { - ERR("udc reset timeout! \n"); + ERR("udc reset timeout!\n"); return -ETIMEDOUT; } cpu_relax(); @@ -315,7 +304,8 @@ static void dr_controller_stop(struct fsl_udc *udc) return; } -void dr_ep_setup(unsigned char ep_num, unsigned char dir, unsigned char ep_type) +static void dr_ep_setup(unsigned char ep_num, unsigned char dir, + unsigned char ep_type) { unsigned int tmp_epctrl = 0; @@ -563,7 +553,7 @@ static int fsl_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = 0; + ep->desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); @@ -602,7 +592,7 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req) } /*-------------------------------------------------------------------------*/ -static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) +static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) { int i = ep_index(ep) * 2 + ep_is_in(ep); u32 temp, bitmask, tmp_stat; @@ -653,13 +643,16 @@ static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) | EP_QUEUE_HEAD_STATUS_HALT)); dQH->size_ioc_int_sts &= temp; + /* Ensure that updates to the QH will occure before priming. */ + wmb(); + /* Prime endpoint by writing 1 to ENDPTPRIME */ temp = ep_is_in(ep) ? (1 << (ep_index(ep) + 16)) : (1 << (ep_index(ep))); fsl_writel(temp, &dr_regs->endpointprime); out: - return 0; + return; } /* Fill in the dTD structure @@ -710,7 +703,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, *is_last = 0; if ((*is_last) == 0) - VDBG("multi-dtd request!\n"); + VDBG("multi-dtd request!"); /* Fill in the transfer size; set active bit */ swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE); @@ -773,11 +766,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* catch various bogus parameters */ if (!_req || !req->req.complete || !req->req.buf || !list_empty(&req->queue)) { - VDBG("%s, bad params\n", __func__); + VDBG("%s, bad params", __func__); return -EINVAL; } if (unlikely(!_ep || !ep->desc)) { - VDBG("%s, bad ep\n", __func__); + VDBG("%s, bad ep", __func__); return -EINVAL; } if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { @@ -1069,7 +1062,7 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active) udc = container_of(gadget, struct fsl_udc, gadget); spin_lock_irqsave(&udc->lock, flags); - VDBG("VBUS %s\n", is_active ? "on" : "off"); + VDBG("VBUS %s", is_active ? "on" : "off"); udc->vbus_active = (is_active != 0); if (can_pullup(udc)) fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP), @@ -1146,7 +1139,6 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) { struct fsl_req *req = udc->status_req; struct fsl_ep *ep; - int status = 0; if (direction == EP_DIR_IN) udc->ep0_dir = USB_DIR_IN; @@ -1164,27 +1156,21 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) req->dtd_count = 0; if (fsl_req_to_dtd(req) == 0) - status = fsl_queue_td(ep, req); + fsl_queue_td(ep, req); else return -ENOMEM; - if (status) - ERR("Can't queue ep0 status request \n"); list_add_tail(&req->queue, &ep->queue); - return status; + return 0; } -static inline int udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe) +static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe) { struct fsl_ep *ep = get_ep_by_pipe(udc, pipe); - if (!ep->name) - return 0; - - nuke(ep, -ESHUTDOWN); - - return 0; + if (ep->name) + nuke(ep, -ESHUTDOWN); } /* @@ -1208,10 +1194,8 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, u16 index, u16 length) { u16 tmp = 0; /* Status, cpu endian */ - struct fsl_req *req; struct fsl_ep *ep; - int status = 0; ep = &udc->eps[0]; @@ -1250,14 +1234,10 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, /* prime the data phase */ if ((fsl_req_to_dtd(req) == 0)) - status = fsl_queue_td(ep, req); + fsl_queue_td(ep, req); else /* no mem */ goto stall; - if (status) { - ERR("Can't respond to getstatus request \n"); - goto stall; - } list_add_tail(&req->queue, &ep->queue); udc->ep0_state = DATA_STATE_XMIT; return; @@ -1397,7 +1377,7 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0, udc->ep0_state = WAIT_FOR_SETUP; break; case WAIT_FOR_SETUP: - ERR("Unexpect ep0 packets \n"); + ERR("Unexpect ep0 packets\n"); break; default: ep0stall(udc); @@ -1476,7 +1456,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, status = -EILSEQ; break; } else - ERR("Unknown error has occured (0x%x)!\r\n", + ERR("Unknown error has occured (0x%x)!\n", errors); } else if (le32_to_cpu(curr_td->size_ioc_sts) @@ -1495,7 +1475,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, } } else { td_complete++; - VDBG("dTD transmitted successful "); + VDBG("dTD transmitted successful"); } if (j != curr_req->dtd_count - 1) @@ -1568,9 +1548,6 @@ static void port_change_irq(struct fsl_udc *udc) { u32 speed; - if (udc->bus_reset) - udc->bus_reset = 0; - /* Bus resetting is finished */ if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { /* Get the speed */ @@ -1678,8 +1655,6 @@ static void reset_irq(struct fsl_udc *udc) if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) { VDBG("Bus reset"); - /* Bus is reseting */ - udc->bus_reset = 1; /* Reset all the queues, include XD, dTD, EP queue * head and TR Queue */ reset_queues(udc); @@ -1768,7 +1743,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc) } if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) { - VDBG("Error IRQ %x ", irq_src); + VDBG("Error IRQ %x", irq_src); } spin_unlock_irqrestore(&udc->lock, flags); @@ -1799,7 +1774,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) /* lock is needed but whether should use this lock or another */ spin_lock_irqsave(&udc_controller->lock, flags); - driver->driver.bus = 0; + driver->driver.bus = NULL; /* hook up the driver */ udc_controller->driver = driver; udc_controller->gadget.dev.driver = &driver->driver; @@ -1809,8 +1784,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) retval = driver->bind(&udc_controller->gadget); if (retval) { VDBG("bind to %s --> %d", driver->driver.name, retval); - udc_controller->gadget.dev.driver = 0; - udc_controller->driver = 0; + udc_controller->gadget.dev.driver = NULL; + udc_controller->driver = NULL; goto out; } @@ -1819,12 +1794,12 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) udc_controller->usb_state = USB_STATE_ATTACHED; udc_controller->ep0_state = WAIT_FOR_SETUP; udc_controller->ep0_dir = 0; - printk(KERN_INFO "%s: bind to driver %s \n", + printk(KERN_INFO "%s: bind to driver %s\n", udc_controller->gadget.name, driver->driver.name); out: if (retval) - printk("retval %d \n", retval); + printk("gadget driver register failed %d\n", retval); return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -1842,7 +1817,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) return -EINVAL; if (udc_controller->transceiver) - (void)otg_set_peripheral(udc_controller->transceiver, 0); + otg_set_peripheral(udc_controller->transceiver, NULL); /* stop DR, disable intr */ dr_controller_stop(udc_controller); @@ -1863,10 +1838,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) /* unbind gadget and unhook driver. */ driver->unbind(&udc_controller->gadget); - udc_controller->gadget.dev.driver = 0; - udc_controller->driver = 0; + udc_controller->gadget.dev.driver = NULL; + udc_controller->driver = NULL; - printk("unregistered gadget driver '%s'\r\n", driver->driver.name); + printk("unregistered gadget driver '%s'\n", driver->driver.name); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -1922,7 +1897,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, tmp_reg = fsl_readl(&dr_regs->usbsts); t = scnprintf(next, size, "USB Status Reg:\n" - "Dr Suspend: %d" "Reset Received: %d" "System Error: %s" + "Dr Suspend: %d Reset Received: %d System Error: %s " "USB Error Interrupt: %s\n\n", (tmp_reg & USB_STS_SUSPEND) ? 1 : 0, (tmp_reg & USB_STS_RESET) ? 1 : 0, @@ -1934,11 +1909,11 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, tmp_reg = fsl_readl(&dr_regs->usbintr); t = scnprintf(next, size, "USB Intrrupt Enable Reg:\n" - "Sleep Enable: %d" "SOF Received Enable: %d" + "Sleep Enable: %d SOF Received Enable: %d " "Reset Enable: %d\n" - "System Error Enable: %d" + "System Error Enable: %d " "Port Change Dectected Enable: %d\n" - "USB Error Intr Enable: %d" "USB Intr Enable: %d\n\n", + "USB Error Intr Enable: %d USB Intr Enable: %d\n\n", (tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0, (tmp_reg & USB_INTR_SOF_EN) ? 1 : 0, (tmp_reg & USB_INTR_RESET_EN) ? 1 : 0, @@ -1951,21 +1926,21 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, tmp_reg = fsl_readl(&dr_regs->frindex); t = scnprintf(next, size, - "USB Frame Index Reg:" "Frame Number is 0x%x\n\n", + "USB Frame Index Reg: Frame Number is 0x%x\n\n", (tmp_reg & USB_FRINDEX_MASKS)); size -= t; next += t; tmp_reg = fsl_readl(&dr_regs->deviceaddr); t = scnprintf(next, size, - "USB Device Address Reg:" "Device Addr is 0x%x\n\n", + "USB Device Address Reg: Device Addr is 0x%x\n\n", (tmp_reg & USB_DEVICE_ADDRESS_MASK)); size -= t; next += t; tmp_reg = fsl_readl(&dr_regs->endpointlistaddr); t = scnprintf(next, size, - "USB Endpoint List Address Reg:" + "USB Endpoint List Address Reg: " "Device Addr is 0x%x\n\n", (tmp_reg & USB_EP_LIST_ADDRESS_MASK)); size -= t; @@ -1974,11 +1949,12 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, tmp_reg = fsl_readl(&dr_regs->portsc1); t = scnprintf(next, size, "USB Port Status&Control Reg:\n" - "Port Transceiver Type : %s" "Port Speed: %s \n" - "PHY Low Power Suspend: %s" "Port Reset: %s" - "Port Suspend Mode: %s \n" "Over-current Change: %s" + "Port Transceiver Type : %s Port Speed: %s\n" + "PHY Low Power Suspend: %s Port Reset: %s " + "Port Suspend Mode: %s\n" + "Over-current Change: %s " "Port Enable/Disable Change: %s\n" - "Port Enabled/Disabled: %s" + "Port Enabled/Disabled: %s " "Current Connect Status: %s\n\n", ( { char *s; switch (tmp_reg & PORTSCX_PTS_FSLS) { @@ -2023,7 +1999,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, tmp_reg = fsl_readl(&dr_regs->usbmode); t = scnprintf(next, size, - "USB Mode Reg:" "Controller Mode is : %s\n\n", ( { + "USB Mode Reg: Controller Mode is: %s\n\n", ( { char *s; switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) { case USB_MODE_CTRL_MODE_IDLE: @@ -2042,7 +2018,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, tmp_reg = fsl_readl(&dr_regs->endptsetupstat); t = scnprintf(next, size, - "Endpoint Setup Status Reg:" "SETUP on ep 0x%x\n\n", + "Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n", (tmp_reg & EP_SETUP_STATUS_MASK)); size -= t; next += t; @@ -2055,12 +2031,12 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, next += t; } tmp_reg = fsl_readl(&dr_regs->endpointprime); - t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n", tmp_reg); + t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n\n", tmp_reg); size -= t; next += t; tmp_reg = usb_sys_regs->snoop1; - t = scnprintf(next, size, "\nSnoop1 Reg : = [0x%x]\n\n", tmp_reg); + t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg); size -= t; next += t; @@ -2084,7 +2060,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, } else { list_for_each_entry(req, &ep->queue, queue) { t = scnprintf(next, size, - "req %p actual 0x%x length 0x%x buf %p\n", + "req %p actual 0x%x length 0x%x buf %p\n", &req->req, req->req.actual, req->req.length, req->req.buf); size -= t; @@ -2110,7 +2086,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, } else { list_for_each_entry(req, &ep->queue, queue) { t = scnprintf(next, size, - "req %p actual 0x%x length" + "req %p actual 0x%x length " "0x%x buf %p\n", &req->req, req->req.actual, req->req.length, req->req.buf); @@ -2202,7 +2178,6 @@ static int __init struct_udc_setup(struct fsl_udc *udc, udc->usb_state = USB_STATE_POWERED; udc->ep0_dir = 0; udc->remote_wakeup = 0; /* default to 0 on reset */ - spin_lock_init(&udc->lock); return 0; } @@ -2254,7 +2229,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) u32 dccparams; if (strcmp(pdev->name, driver_name)) { - VDBG("Wrong device\n"); + VDBG("Wrong device"); return -ENODEV; } @@ -2264,23 +2239,26 @@ static int __init fsl_udc_probe(struct platform_device *pdev) return -ENOMEM; } + spin_lock_init(&udc_controller->lock); + udc_controller->stopped = 1; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - kfree(udc_controller); - return -ENXIO; + ret = -ENXIO; + goto err_kfree; } if (!request_mem_region(res->start, res->end - res->start + 1, driver_name)) { - ERR("request mem region for %s failed \n", pdev->name); - kfree(udc_controller); - return -EBUSY; + ERR("request mem region for %s failed\n", pdev->name); + ret = -EBUSY; + goto err_kfree; } dr_regs = ioremap(res->start, res->end - res->start + 1); if (!dr_regs) { ret = -ENOMEM; - goto err1; + goto err_release_mem_region; } usb_sys_regs = (struct usb_sys_interface *) @@ -2291,7 +2269,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) if (!(dccparams & DCCPARAMS_DC)) { ERR("This SOC doesn't support device role\n"); ret = -ENODEV; - goto err2; + goto err_iounmap; } /* Get max device endpoints */ /* DEN is bidirectional ep number, max_ep doubles the number */ @@ -2300,22 +2278,22 @@ static int __init fsl_udc_probe(struct platform_device *pdev) udc_controller->irq = platform_get_irq(pdev, 0); if (!udc_controller->irq) { ret = -ENODEV; - goto err2; + goto err_iounmap; } ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED, driver_name, udc_controller); if (ret != 0) { - ERR("cannot request irq %d err %d \n", + ERR("cannot request irq %d err %d\n", udc_controller->irq, ret); - goto err2; + goto err_iounmap; } /* Initialize the udc structure including QH member and other member */ if (struct_udc_setup(udc_controller, pdev)) { ERR("Can't initialize udc data structure\n"); ret = -ENOMEM; - goto err3; + goto err_free_irq; } /* initialize usb hw reg except for regs for EP, @@ -2336,7 +2314,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) udc_controller->gadget.dev.parent = &pdev->dev; ret = device_register(&udc_controller->gadget.dev); if (ret < 0) - goto err3; + goto err_free_irq; /* setup QH and epctrl for ep0 */ ep0_setup(udc_controller); @@ -2366,20 +2344,22 @@ static int __init fsl_udc_probe(struct platform_device *pdev) DTD_ALIGNMENT, UDC_DMA_BOUNDARY); if (udc_controller->td_pool == NULL) { ret = -ENOMEM; - goto err4; + goto err_unregister; } create_proc_file(); return 0; -err4: +err_unregister: device_unregister(&udc_controller->gadget.dev); -err3: +err_free_irq: free_irq(udc_controller->irq, udc_controller); -err2: +err_iounmap: iounmap(dr_regs); -err1: +err_release_mem_region: release_mem_region(res->start, res->end - res->start + 1); +err_kfree: kfree(udc_controller); + udc_controller = NULL; return ret; } @@ -2469,7 +2449,7 @@ module_init(udc_init); static void __exit udc_exit(void) { platform_driver_unregister(&udc_driver); - printk("%s unregistered \n", driver_desc); + printk("%s unregistered\n", driver_desc); } module_exit(udc_exit); diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 6131752a38bc..e63ef12645f5 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -424,16 +424,6 @@ struct ep_td_struct { /* Controller dma boundary */ #define UDC_DMA_BOUNDARY 0x1000 -/* -----------------------------------------------------------------------*/ -/* ##### enum data -*/ -typedef enum { - e_ULPI, - e_UTMI_8BIT, - e_UTMI_16BIT, - e_SERIAL -} e_PhyInterface; - /*-------------------------------------------------------------------------*/ /* ### driver private data @@ -469,9 +459,9 @@ struct fsl_ep { #define EP_DIR_OUT 0 struct fsl_udc { - struct usb_gadget gadget; struct usb_gadget_driver *driver; + struct completion *done; /* to make sure release() is done */ struct fsl_ep *eps; unsigned int max_ep; unsigned int irq; @@ -492,20 +482,13 @@ struct fsl_udc { size_t ep_qh_size; /* size after alignment adjustment*/ dma_addr_t ep_qh_dma; /* dma address of QH */ - u32 max_pipes; /* Device max pipes */ - u32 max_use_endpts; /* Max endpointes to be used */ - u32 bus_reset; /* Device is bus reseting */ + u32 max_pipes; /* Device max pipes */ u32 resume_state; /* USB state to resume */ u32 usb_state; /* USB current state */ - u32 usb_next_state; /* USB next state */ u32 ep0_state; /* Endpoint zero state */ u32 ep0_dir; /* Endpoint zero direction: can be USB_DIR_IN or USB_DIR_OUT */ - u32 usb_sof_count; /* SOF count */ - u32 errors; /* USB ERRORs count */ u8 device_address; /* Device USB address */ - - struct completion *done; /* to make sure release() is done */ }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 17d9905101b7..4e3107dd2f34 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -151,6 +151,13 @@ #define gadget_is_m66592(g) 0 #endif +/* Freescale CPM/QE UDC SUPPORT */ +#ifdef CONFIG_USB_GADGET_FSL_QE +#define gadget_is_fsl_qe(g) !strcmp("fsl_qe_udc", (g)->name) +#else +#define gadget_is_fsl_qe(g) 0 +#endif + // CONFIG_USB_GADGET_SX2 // CONFIG_USB_GADGET_AU1X00 @@ -216,6 +223,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x20; else if (gadget_is_m66592(gadget)) return 0x21; + else if (gadget_is_fsl_qe(gadget)) + return 0x22; return -ENOENT; } diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index ea8651e3da1a..60d3f9e9b51f 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -35,6 +35,21 @@ #include "gadget_chips.h" + +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +/*-------------------------------------------------------------------------*/ + + MODULE_AUTHOR("Ben Williamson"); MODULE_LICENSE("GPL v2"); @@ -207,7 +222,7 @@ static struct usb_config_descriptor config_desc = { * power properties of the device. Is it selfpowered? */ .bmAttributes = USB_CONFIG_ATT_ONE, - .bMaxPower = 1, + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, }; /* B.3.1 Standard AC Interface Descriptor */ diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 5cfb5ebf3881..8ae70de2c37d 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -178,6 +178,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) /* ep_reset() has already been called */ ep->stopped = 0; + ep->wedged = 0; ep->out_overflow = 0; /* set speed-dependent max packet; may kick in high bandwidth */ @@ -1218,7 +1219,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) static int net2280_fifo_status (struct usb_ep *_ep); static int -net2280_set_halt (struct usb_ep *_ep, int value) +net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged) { struct net2280_ep *ep; unsigned long flags; @@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value) else if (ep->is_in && value && net2280_fifo_status (_ep) != 0) retval = -EAGAIN; else { - VDEBUG (ep->dev, "%s %s halt\n", _ep->name, - value ? "set" : "clear"); + VDEBUG (ep->dev, "%s %s %s\n", _ep->name, + value ? "set" : "clear", + wedged ? "wedge" : "halt"); /* set/clear, then synch memory views with the device */ if (value) { if (ep->num == 0) ep->dev->protocol_stall = 1; else set_halt (ep); - } else + if (wedged) + ep->wedged = 1; + } else { clear_halt (ep); + ep->wedged = 0; + } (void) readl (&ep->regs->ep_rsp); } spin_unlock_irqrestore (&ep->dev->lock, flags); @@ -1257,6 +1263,20 @@ net2280_set_halt (struct usb_ep *_ep, int value) } static int +net2280_set_halt(struct usb_ep *_ep, int value) +{ + return net2280_set_halt_and_wedge(_ep, value, 0); +} + +static int +net2280_set_wedge(struct usb_ep *_ep) +{ + if (!_ep || _ep->name == ep0name) + return -EINVAL; + return net2280_set_halt_and_wedge(_ep, 1, 1); +} + +static int net2280_fifo_status (struct usb_ep *_ep) { struct net2280_ep *ep; @@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = { .dequeue = net2280_dequeue, .set_halt = net2280_set_halt, + .set_wedge = net2280_set_wedge, .fifo_status = net2280_fifo_status, .fifo_flush = net2280_fifo_flush, }; @@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) goto do_stall; if ((e = get_ep_by_addr (dev, w_index)) == 0) goto do_stall; - clear_halt (e); + if (e->wedged) { + VDEBUG(dev, "%s wedged, halt not cleared\n", + ep->ep.name); + } else { + VDEBUG(dev, "%s clear halt\n", ep->ep.name); + clear_halt(e); + } allow_status (ep); - VDEBUG (dev, "%s clear halt\n", ep->ep.name); goto next_endpoints; } break; @@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) goto do_stall; if ((e = get_ep_by_addr (dev, w_index)) == 0) goto do_stall; + if (e->ep.name == ep0name) + goto do_stall; set_halt (e); allow_status (ep); VDEBUG (dev, "%s set halt\n", ep->ep.name); diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index 81a71dbdc2c6..c36852263d93 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h @@ -109,6 +109,7 @@ struct net2280_ep { in_fifo_validate : 1, out_overflow : 1, stopped : 1, + wedged : 1, is_in : 1, is_iso : 1, responded : 1; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index bb54cca4c543..34e9e393f929 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2313,6 +2313,13 @@ static int proc_otg_show(struct seq_file *s) tmp = omap_readl(OTG_REV); if (cpu_is_omap24xx()) { + /* + * REVISIT: Not clear how this works on OMAP2. trans + * is ANDed to produce bits 7 and 8, which might make + * sense for USB_TRANSCEIVER_CTRL on OMAP1, + * but with CONTROL_DEVCONF, these bits have something to + * do with the frame adjustment counter and McBSP2. + */ ctrl_name = "control_devconf"; trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); } else { diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index e0090085b78e..5a3034fdfe47 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -53,6 +53,20 @@ #include "gadget_chips.h" + +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +/*-------------------------------------------------------------------------*/ + #define DRIVER_DESC "Printer Gadget" #define DRIVER_VERSION "2007 OCT 06" @@ -238,7 +252,7 @@ static struct usb_config_descriptor config_desc = { .bConfigurationValue = DEV_CONFIG_VALUE, .iConfiguration = 0, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1 /* Self-Powered */ + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, }; static struct usb_interface_descriptor intf_desc = { @@ -1264,8 +1278,7 @@ unknown: /* respond with data transfer before status phase? */ if (value >= 0) { req->length = value; - req->zero = value < wLength - && (value % gadget->ep0->maxpacket) == 0; + req->zero = value < wLength; value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); if (value < 0) { DBG(dev, "ep_queue --> %d\n", value); @@ -1360,8 +1373,8 @@ printer_bind(struct usb_gadget *gadget) /* Setup the sysfs files for the printer gadget. */ - dev->pdev = device_create_drvdata(usb_gadget_class, NULL, - g_printer_devno, NULL, "g_printer"); + dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, + NULL, "g_printer"); if (IS_ERR(dev->pdev)) { ERROR(dev, "Failed to create device: g_printer\n"); goto fail; @@ -1463,7 +1476,6 @@ autoconf_fail: if (gadget->is_otg) { otg_desc.bmAttributes |= USB_OTG_HNP, config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - config_desc.bMaxPower = 4; } spin_lock_init(&dev->lock); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 7cbc78a6853d..bcf375ca3d72 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -22,7 +22,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> -#include <linux/version.h> #include <linux/errno.h> #include <linux/platform_device.h> #include <linux/delay.h> diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 7228e8562236..8c26f5ea2b83 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -57,11 +57,6 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging"); #define rndis_debug 0 #endif -#define DBG(str,args...) do { \ - if (rndis_debug) \ - pr_debug(str , ## args); \ - } while (0) - #define RNDIS_MAX_CONFIGS 1 @@ -183,9 +178,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, if (!resp) return -ENOMEM; if (buf_len && rndis_debug > 1) { - DBG("query OID %08x value, len %d:\n", OID, buf_len); + pr_debug("query OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { - DBG("%03d: %08x %08x %08x %08x\n", i, + pr_debug("%03d: %08x %08x %08x %08x\n", i, get_unaligned_le32(&buf[i]), get_unaligned_le32(&buf[i + 4]), get_unaligned_le32(&buf[i + 8]), @@ -209,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_SUPPORTED_LIST: - DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__); + pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__); length = sizeof (oid_supported_list); count = length / sizeof (u32); for (i = 0; i < count; i++) @@ -219,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_HARDWARE_STATUS: - DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__); + pr_debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__); /* Bogus question! * Hardware must be ready to receive high level protocols. * BTW: @@ -232,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_MEDIA_SUPPORTED: - DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__); + pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__); *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); retval = 0; break; /* mandatory */ case OID_GEN_MEDIA_IN_USE: - DBG("%s: OID_GEN_MEDIA_IN_USE\n", __func__); + pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__); /* one medium, one transport... (maybe you do it better) */ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); retval = 0; @@ -247,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_MAXIMUM_FRAME_SIZE: - DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__); + pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__); if (rndis_per_dev_params [configNr].dev) { *outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu); @@ -258,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_LINK_SPEED: if (rndis_debug > 1) - DBG("%s: OID_GEN_LINK_SPEED\n", __func__); + pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__); if (rndis_per_dev_params [configNr].media_state == NDIS_MEDIA_STATE_DISCONNECTED) *outbuf = __constant_cpu_to_le32 (0); @@ -270,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_TRANSMIT_BLOCK_SIZE: - DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__); + pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__); if (rndis_per_dev_params [configNr].dev) { *outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu); @@ -280,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_RECEIVE_BLOCK_SIZE: - DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__); + pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__); if (rndis_per_dev_params [configNr].dev) { *outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu); @@ -290,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_ID: - DBG("%s: OID_GEN_VENDOR_ID\n", __func__); + pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__); *outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].vendorID); retval = 0; @@ -298,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: - DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); + pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); length = strlen (rndis_per_dev_params [configNr].vendorDescr); memcpy (outbuf, rndis_per_dev_params [configNr].vendorDescr, length); @@ -306,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, break; case OID_GEN_VENDOR_DRIVER_VERSION: - DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__); + pr_debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__); /* Created as LE */ *outbuf = rndis_driver_version; retval = 0; @@ -314,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_CURRENT_PACKET_FILTER: - DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__); + pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__); *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); retval = 0; break; /* mandatory */ case OID_GEN_MAXIMUM_TOTAL_SIZE: - DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__); + pr_debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__); *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); retval = 0; break; @@ -329,14 +324,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_MEDIA_CONNECT_STATUS: if (rndis_debug > 1) - DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__); + pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__); *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .media_state); retval = 0; break; case OID_GEN_PHYSICAL_MEDIUM: - DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__); + pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; @@ -346,7 +341,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! */ case OID_GEN_MAC_OPTIONS: /* from WinME */ - DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__); + pr_debug("%s: OID_GEN_MAC_OPTIONS\n", __func__); *outbuf = __constant_cpu_to_le32( NDIS_MAC_OPTION_RECEIVE_SERIALIZED | NDIS_MAC_OPTION_FULL_DUPLEX); @@ -358,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_XMIT_OK: if (rndis_debug > 1) - DBG("%s: OID_GEN_XMIT_OK\n", __func__); + pr_debug("%s: OID_GEN_XMIT_OK\n", __func__); if (stats) { *outbuf = cpu_to_le32(stats->tx_packets - stats->tx_errors - stats->tx_dropped); @@ -369,7 +364,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_RCV_OK: if (rndis_debug > 1) - DBG("%s: OID_GEN_RCV_OK\n", __func__); + pr_debug("%s: OID_GEN_RCV_OK\n", __func__); if (stats) { *outbuf = cpu_to_le32(stats->rx_packets - stats->rx_errors - stats->rx_dropped); @@ -380,7 +375,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_XMIT_ERROR: if (rndis_debug > 1) - DBG("%s: OID_GEN_XMIT_ERROR\n", __func__); + pr_debug("%s: OID_GEN_XMIT_ERROR\n", __func__); if (stats) { *outbuf = cpu_to_le32(stats->tx_errors); retval = 0; @@ -390,7 +385,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_RCV_ERROR: if (rndis_debug > 1) - DBG("%s: OID_GEN_RCV_ERROR\n", __func__); + pr_debug("%s: OID_GEN_RCV_ERROR\n", __func__); if (stats) { *outbuf = cpu_to_le32(stats->rx_errors); retval = 0; @@ -399,7 +394,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_RCV_NO_BUFFER: - DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__); + pr_debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__); if (stats) { *outbuf = cpu_to_le32(stats->rx_dropped); retval = 0; @@ -410,7 +405,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_PERMANENT_ADDRESS: - DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__); + pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__); if (rndis_per_dev_params [configNr].dev) { length = ETH_ALEN; memcpy (outbuf, @@ -422,7 +417,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_CURRENT_ADDRESS: - DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__); + pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__); if (rndis_per_dev_params [configNr].dev) { length = ETH_ALEN; memcpy (outbuf, @@ -434,7 +429,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_MULTICAST_LIST: - DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__); + pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__); /* Multicast base address only */ *outbuf = __constant_cpu_to_le32 (0xE0000000); retval = 0; @@ -442,21 +437,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_MAXIMUM_LIST_SIZE: - DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__); + pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__); /* Multicast base address only */ *outbuf = __constant_cpu_to_le32 (1); retval = 0; break; case OID_802_3_MAC_OPTIONS: - DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__); + pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__); break; /* ieee802.3 statistics OIDs (table 4-4) */ /* mandatory */ case OID_802_3_RCV_ERROR_ALIGNMENT: - DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__); + pr_debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__); if (stats) { *outbuf = cpu_to_le32(stats->rx_frame_errors); retval = 0; @@ -465,14 +460,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_XMIT_ONE_COLLISION: - DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__); + pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; /* mandatory */ case OID_802_3_XMIT_MORE_COLLISIONS: - DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__); + pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; @@ -504,9 +499,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, return -ENOMEM; if (buf_len && rndis_debug > 1) { - DBG("set OID %08x value, len %d:\n", OID, buf_len); + pr_debug("set OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { - DBG("%03d: %08x %08x %08x %08x\n", i, + pr_debug("%03d: %08x %08x %08x %08x\n", i, get_unaligned_le32(&buf[i]), get_unaligned_le32(&buf[i + 4]), get_unaligned_le32(&buf[i + 8]), @@ -525,7 +520,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, * MULTICAST, ALL_MULTICAST, BROADCAST */ *params->filter = (u16)get_unaligned_le32(buf); - DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", + pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __func__, *params->filter); /* this call has a significant side effect: it's @@ -547,7 +542,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, case OID_802_3_MULTICAST_LIST: /* I think we can ignore this */ - DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__); + pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__); retval = 0; break; @@ -606,7 +601,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) rndis_resp_t *r; struct rndis_params *params = rndis_per_dev_params + configNr; - // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); + /* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */ if (!params->dev) return -ENOTSUPP; @@ -659,15 +654,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) BufOffset = le32_to_cpu (buf->InformationBufferOffset); #ifdef VERBOSE_DEBUG - DBG("%s: Length: %d\n", __func__, BufLength); - DBG("%s: Offset: %d\n", __func__, BufOffset); - DBG("%s: InfoBuffer: ", __func__); + pr_debug("%s: Length: %d\n", __func__, BufLength); + pr_debug("%s: Offset: %d\n", __func__, BufOffset); + pr_debug("%s: InfoBuffer: ", __func__); for (i = 0; i < BufLength; i++) { - DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); + pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); } - DBG("\n"); + pr_debug("\n"); #endif resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); @@ -821,14 +816,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf) /* For USB: responses may take up to 10 seconds */ switch (MsgType) { case REMOTE_NDIS_INITIALIZE_MSG: - DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", + pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __func__ ); params->state = RNDIS_INITIALIZED; return rndis_init_response (configNr, (rndis_init_msg_type *) buf); case REMOTE_NDIS_HALT_MSG: - DBG("%s: REMOTE_NDIS_HALT_MSG\n", + pr_debug("%s: REMOTE_NDIS_HALT_MSG\n", __func__ ); params->state = RNDIS_UNINITIALIZED; if (params->dev) { @@ -846,7 +841,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) (rndis_set_msg_type *) buf); case REMOTE_NDIS_RESET_MSG: - DBG("%s: REMOTE_NDIS_RESET_MSG\n", + pr_debug("%s: REMOTE_NDIS_RESET_MSG\n", __func__ ); return rndis_reset_response (configNr, (rndis_reset_msg_type *) buf); @@ -854,7 +849,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) case REMOTE_NDIS_KEEPALIVE_MSG: /* For USB: host does this every 5 seconds */ if (rndis_debug > 1) - DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", + pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __func__ ); return rndis_keepalive_response (configNr, (rndis_keepalive_msg_type *) @@ -870,7 +865,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) { unsigned i; for (i = 0; i < MsgLength; i += 16) { - DBG("%03d: " + pr_debug("%03d: " " %02x %02x %02x %02x" " %02x %02x %02x %02x" " %02x %02x %02x %02x" @@ -905,18 +900,18 @@ int rndis_register(void (*resp_avail)(void *v), void *v) rndis_per_dev_params [i].used = 1; rndis_per_dev_params [i].resp_avail = resp_avail; rndis_per_dev_params [i].v = v; - DBG("%s: configNr = %d\n", __func__, i); + pr_debug("%s: configNr = %d\n", __func__, i); return i; } } - DBG("failed\n"); + pr_debug("failed\n"); return -ENODEV; } void rndis_deregister (int configNr) { - DBG("%s: \n", __func__ ); + pr_debug("%s: \n", __func__); if (configNr >= RNDIS_MAX_CONFIGS) return; rndis_per_dev_params [configNr].used = 0; @@ -926,7 +921,7 @@ void rndis_deregister (int configNr) int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) { - DBG("%s:\n", __func__ ); + pr_debug("%s:\n", __func__); if (!dev) return -EINVAL; if (configNr >= RNDIS_MAX_CONFIGS) return -1; @@ -939,7 +934,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) { - DBG("%s:\n", __func__ ); + pr_debug("%s:\n", __func__); if (!vendorDescr) return -1; if (configNr >= RNDIS_MAX_CONFIGS) return -1; @@ -951,7 +946,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) { - DBG("%s: %u %u\n", __func__, medium, speed); + pr_debug("%s: %u %u\n", __func__, medium, speed); if (configNr >= RNDIS_MAX_CONFIGS) return -1; rndis_per_dev_params [configNr].medium = medium; @@ -1114,7 +1109,7 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer, break; default: if (fl_speed) p->speed = speed; - else DBG("%c is not valid\n", c); + else pr_debug("%c is not valid\n", c); break; } @@ -1159,12 +1154,12 @@ int __init rndis_init (void) &rndis_proc_fops, (void *)(rndis_per_dev_params + i)))) { - DBG("%s :remove entries", __func__); + pr_debug("%s :remove entries", __func__); while (i) { sprintf (name, NAME_TEMPLATE, --i); remove_proc_entry (name, NULL); } - DBG("\n"); + pr_debug("\n"); return -EIO; } #endif diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 29d13ebe7500..48f51b12d2e2 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1651,7 +1651,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) return -EBUSY; if (!driver->bind || !driver->setup - || driver->speed != USB_SPEED_FULL) { + || driver->speed < USB_SPEED_FULL) { printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", driver->bind, driver->setup, driver->speed); return -EINVAL; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b3699afff002..37879af1c433 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -30,6 +30,25 @@ /*-------------------------------------------------------------------------*/ +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +#include "f_acm.c" +#include "f_obex.c" +#include "f_serial.c" +#include "u_serial.c" + +/*-------------------------------------------------------------------------*/ + /* Thanks to NetChip Technologies for donating this product ID. * * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! @@ -38,6 +57,7 @@ #define GS_VENDOR_ID 0x0525 /* NetChip */ #define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */ #define GS_CDC_PRODUCT_ID 0xa4a7 /* ... as CDC-ACM */ +#define GS_CDC_OBEX_PRODUCT_ID 0xa4a9 /* ... as CDC-OBEX */ /* string IDs are assigned dynamically */ @@ -107,6 +127,10 @@ static int use_acm = true; module_param(use_acm, bool, 0); MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes"); +static int use_obex = false; +module_param(use_obex, bool, 0); +MODULE_PARM_DESC(use_obex, "Use CDC OBEX, default=no"); + static unsigned n_ports = 1; module_param(n_ports, uint, 0); MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); @@ -121,6 +145,8 @@ static int __init serial_bind_config(struct usb_configuration *c) for (i = 0; i < n_ports && status == 0; i++) { if (use_acm) status = acm_bind_config(c, i); + else if (use_obex) + status = obex_bind_config(c, i); else status = gser_bind_config(c, i); } @@ -133,7 +159,6 @@ static struct usb_configuration serial_config_driver = { /* .bConfigurationValue = f(use_acm) */ /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, /* 2 mA, minimal */ }; static int __init gs_bind(struct usb_composite_dev *cdev) @@ -231,6 +256,12 @@ static int __init init(void) device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = __constant_cpu_to_le16(GS_CDC_PRODUCT_ID); + } else if (use_obex) { + serial_config_driver.label = "CDC OBEX config"; + serial_config_driver.bConfigurationValue = 3; + device_desc.bDeviceClass = USB_CLASS_COMM; + device_desc.idProduct = + __constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); } else { serial_config_driver.label = "Generic Serial config"; serial_config_driver.bConfigurationValue = 1; diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 3791e6271903..66948b72bb9b 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -52,7 +52,7 @@ * this single "physical" link to be used by multiple virtual links.) */ -#define DRIVER_VERSION "29-May-2008" +#define UETH__VERSION "29-May-2008" struct eth_dev { /* lock is held while accessing port_usb @@ -170,7 +170,7 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) struct eth_dev *dev = netdev_priv(net); strlcpy(p->driver, "g_ether", sizeof p->driver); - strlcpy(p->version, DRIVER_VERSION, sizeof p->version); + strlcpy(p->version, UETH__VERSION, sizeof p->version); strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version); strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info); } @@ -873,6 +873,13 @@ struct net_device *gether_connect(struct gether *link) spin_lock(&dev->lock); dev->port_usb = link; link->ioport = dev; + if (netif_running(dev->net)) { + if (link->open) + link->open(link); + } else { + if (link->close) + link->close(link); + } spin_unlock(&dev->lock); netif_carrier_on(dev->net); diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h index af3910d01aea..300f0ed9475d 100644 --- a/drivers/usb/gadget/u_serial.h +++ b/drivers/usb/gadget/u_serial.h @@ -62,5 +62,6 @@ void gserial_disconnect(struct gserial *); /* functions are bound to configurations by a config or gadget driver */ int acm_bind_config(struct usb_configuration *c, u8 port_num); int gser_bind_config(struct usb_configuration *c, u8 port_num); +int obex_bind_config(struct usb_configuration *c, u8 port_num); #endif /* __U_SERIAL_H */ diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index aa0bd4f126a1..361d9659ac48 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -59,6 +59,23 @@ /*-------------------------------------------------------------------------*/ +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +#include "f_sourcesink.c" +#include "f_loopback.c" + +/*-------------------------------------------------------------------------*/ + #define DRIVER_VERSION "Cinco de Mayo 2008" static const char longname[] = "Gadget Zero"; diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index b0f8ed5a7fb9..0cb53ca8d343 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -358,7 +358,8 @@ struct debug_buffer { struct usb_bus *bus; struct mutex mutex; /* protect filling of buffer */ size_t count; /* number of characters filled into buffer */ - char *page; + char *output_buf; + size_t alloc_size; }; #define speed_char(info1) ({ char tmp; \ @@ -488,8 +489,8 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci (hcd); - next = buf->page; - size = PAGE_SIZE; + next = buf->output_buf; + size = buf->alloc_size; *next = 0; @@ -510,7 +511,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) } spin_unlock_irqrestore (&ehci->lock, flags); - return strlen(buf->page); + return strlen(buf->output_buf); } #define DBG_SCHED_LIMIT 64 @@ -531,8 +532,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci (hcd); - next = buf->page; - size = PAGE_SIZE; + next = buf->output_buf; + size = buf->alloc_size; temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); size -= temp; @@ -568,14 +569,16 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) for (temp = 0; temp < seen_count; temp++) { if (seen [temp].ptr != p.ptr) continue; - if (p.qh->qh_next.ptr) + if (p.qh->qh_next.ptr) { temp = scnprintf (next, size, " ..."); - p.ptr = NULL; + size -= temp; + next += temp; + } break; } /* show more info the first time around */ - if (temp == seen_count && p.ptr) { + if (temp == seen_count) { u32 scratch = hc32_to_cpup(ehci, &p.qh->hw_info1); struct ehci_qtd *qtd; @@ -649,7 +652,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) spin_unlock_irqrestore (&ehci->lock, flags); kfree (seen); - return PAGE_SIZE - size; + return buf->alloc_size - size; } #undef DBG_SCHED_LIMIT @@ -665,14 +668,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci (hcd); - next = buf->page; - size = PAGE_SIZE; + next = buf->output_buf; + size = buf->alloc_size; spin_lock_irqsave (&ehci->lock, flags); if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { size = scnprintf (next, size, - "bus %s, device %s (driver " DRIVER_VERSION ")\n" + "bus %s, device %s\n" "%s\n" "SUSPENDED (no register access)\n", hcd->self.controller->bus->name, @@ -684,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* Capability Registers */ i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); temp = scnprintf (next, size, - "bus %s, device %s (driver " DRIVER_VERSION ")\n" + "bus %s, device %s\n" "%s\n" "EHCI %x.%02x, hcd state %d\n", hcd->self.controller->bus->name, @@ -808,7 +811,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) done: spin_unlock_irqrestore (&ehci->lock, flags); - return PAGE_SIZE - size; + return buf->alloc_size - size; } static struct debug_buffer *alloc_buffer(struct usb_bus *bus, @@ -822,6 +825,7 @@ static struct debug_buffer *alloc_buffer(struct usb_bus *bus, buf->bus = bus; buf->fill_func = fill_func; mutex_init(&buf->mutex); + buf->alloc_size = PAGE_SIZE; } return buf; @@ -831,10 +835,10 @@ static int fill_buffer(struct debug_buffer *buf) { int ret = 0; - if (!buf->page) - buf->page = (char *)get_zeroed_page(GFP_KERNEL); + if (!buf->output_buf) + buf->output_buf = (char *)vmalloc(buf->alloc_size); - if (!buf->page) { + if (!buf->output_buf) { ret = -ENOMEM; goto out; } @@ -867,7 +871,7 @@ static ssize_t debug_output(struct file *file, char __user *user_buf, mutex_unlock(&buf->mutex); ret = simple_read_from_buffer(user_buf, len, offset, - buf->page, buf->count); + buf->output_buf, buf->count); out: return ret; @@ -879,8 +883,8 @@ static int debug_close(struct inode *inode, struct file *file) struct debug_buffer *buf = file->private_data; if (buf) { - if (buf->page) - free_page((unsigned long)buf->page); + if (buf->output_buf) + vfree(buf->output_buf); kfree(buf); } @@ -895,10 +899,14 @@ static int debug_async_open(struct inode *inode, struct file *file) static int debug_periodic_open(struct inode *inode, struct file *file) { - file->private_data = alloc_buffer(inode->i_private, - fill_periodic_buffer); + struct debug_buffer *buf; + buf = alloc_buffer(inode->i_private, fill_periodic_buffer); + if (!buf) + return -ENOMEM; - return file->private_data ? 0 : -ENOMEM; + buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; + file->private_data = buf; + return 0; } static int debug_registers_open(struct inode *inode, struct file *file) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8409e0705d63..d343afacb0b0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -24,6 +24,7 @@ #include <linux/ioport.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/vmalloc.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/timer.h> @@ -59,7 +60,6 @@ * providing early devices for those host controllers to talk to! */ -#define DRIVER_VERSION "10 Dec 2004" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" @@ -620,9 +620,9 @@ static int ehci_run (struct usb_hcd *hcd) temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci_info (ehci, - "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", + "USB %x.%x started, EHCI %x.%02x%s\n", ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, DRIVER_VERSION, + temp >> 8, temp & 0xff, ignore_oc ? ", overcurrent ignored" : ""); ehci_writel(ehci, INTR_MASK, @@ -706,7 +706,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) pcd_status = status; /* resume root hub? */ - if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN)) + if (!(cmd & CMD_RUN)) usb_hcd_resume_root_hub(hcd); while (i--) { @@ -715,8 +715,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) if (pstatus & PORT_OWNER) continue; - if (!(pstatus & PORT_RESUME) - || ehci->reset_done [i] != 0) + if (!(test_bit(i, &ehci->suspended_ports) && + ((pstatus & PORT_RESUME) || + !(pstatus & PORT_SUSPEND)) && + (pstatus & PORT_PE) && + ehci->reset_done[i] == 0)) continue; /* start 20 msec resume signaling from this port, @@ -731,9 +734,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { - dbg_cmd (ehci, "fatal", ehci_readl(ehci, - &ehci->regs->command)); - dbg_status (ehci, "fatal", status); + dbg_cmd(ehci, "fatal", cmd); + dbg_status(ehci, "fatal", status); if (status & STS_HALT) { ehci_err (ehci, "fatal error\n"); dead: @@ -994,9 +996,7 @@ static int ehci_get_frame (struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ -#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC - -MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_LICENSE ("GPL"); @@ -1020,11 +1020,6 @@ MODULE_LICENSE ("GPL"); #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver #endif -#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE) -#include "ehci-ppc-soc.c" -#define PLATFORM_DRIVER ehci_ppc_soc_driver -#endif - #ifdef CONFIG_USB_EHCI_HCD_PPC_OF #include "ehci-ppc-of.c" #define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver @@ -1049,6 +1044,16 @@ static int __init ehci_hcd_init(void) { int retval = 0; + if (usb_disabled()) + return -ENODEV; + + printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); + set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || + test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) + printk(KERN_WARNING "Warning! ehci_hcd should always be loaded" + " before uhci_hcd and ohci_hcd, not after\n"); + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", hcd_name, sizeof(struct ehci_qh), sizeof(struct ehci_qtd), @@ -1056,8 +1061,10 @@ static int __init ehci_hcd_init(void) #ifdef DEBUG ehci_debug_root = debugfs_create_dir("ehci", NULL); - if (!ehci_debug_root) - return -ENOENT; + if (!ehci_debug_root) { + retval = -ENOENT; + goto err_debug; + } #endif #ifdef PLATFORM_DRIVER @@ -1105,6 +1112,8 @@ clean0: debugfs_remove(ehci_debug_root); ehci_debug_root = NULL; #endif +err_debug: + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); return retval; } module_init(ehci_hcd_init); @@ -1126,6 +1135,7 @@ static void __exit ehci_hcd_cleanup(void) #ifdef DEBUG debugfs_remove(ehci_debug_root); #endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(ehci_hcd_cleanup); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 740835bb8575..218f9660d7ee 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -236,10 +236,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) temp = ehci_readl(ehci, &ehci->regs->port_status [i]); temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); if (test_bit(i, &ehci->bus_suspended) && - (temp & PORT_SUSPEND)) { - ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); + (temp & PORT_SUSPEND)) temp |= PORT_RESUME; - } ehci_writel(ehci, temp, &ehci->regs->port_status [i]); } i = HCS_N_PORTS (ehci->hcs_params); @@ -482,10 +480,9 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) * controller by the user. */ - if ((temp & mask) != 0 - || ((temp & PORT_RESUME) != 0 - && time_after_eq(jiffies, - ehci->reset_done[i]))) { + if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend) + || (ehci->reset_done[i] && time_after_eq( + jiffies, ehci->reset_done[i]))) { if (i < 7) buf [0] |= 1 << (i + 1); else @@ -688,6 +685,7 @@ static int ehci_hub_control ( /* resume completed? */ else if (time_after_eq(jiffies, ehci->reset_done[wIndex])) { + clear_bit(wIndex, &ehci->suspended_ports); set_bit(wIndex, &ehci->port_c_suspend); ehci->reset_done[wIndex] = 0; @@ -734,6 +732,9 @@ static int ehci_hub_control ( ehci_readl(ehci, status_reg)); } + if (!(temp & (PORT_RESUME|PORT_RESET))) + ehci->reset_done[wIndex] = 0; + /* transfer dedicated ports to the companion hc */ if ((temp & PORT_CONNECT) && test_bit(wIndex, &ehci->companion_ports)) { @@ -757,8 +758,17 @@ static int ehci_hub_control ( } if (temp & PORT_PE) status |= 1 << USB_PORT_FEAT_ENABLE; - if (temp & (PORT_SUSPEND|PORT_RESUME)) + + /* maybe the port was unsuspended without our knowledge */ + if (temp & (PORT_SUSPEND|PORT_RESUME)) { status |= 1 << USB_PORT_FEAT_SUSPEND; + } else if (test_bit(wIndex, &ehci->suspended_ports)) { + clear_bit(wIndex, &ehci->suspended_ports); + ehci->reset_done[wIndex] = 0; + if (temp & PORT_PE) + set_bit(wIndex, &ehci->port_c_suspend); + } + if (temp & PORT_OC) status |= 1 << USB_PORT_FEAT_OVER_CURRENT; if (temp & PORT_RESET) @@ -803,6 +813,7 @@ static int ehci_hub_control ( || (temp & PORT_RESET) != 0) goto error; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); + set_bit(wIndex, &ehci->suspended_ports); break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index f9575c409124..9c32063a0c2f 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -1,7 +1,7 @@ /* * IXP4XX EHCI Host Controller Driver * - * Author: Vladimir Barinov <vbarinov@ru.mvista.com> + * Author: Vladimir Barinov <vbarinov@embeddedalley.com> * * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com> * diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c deleted file mode 100644 index 529590eb4037..000000000000 --- a/drivers/usb/host/ehci-ppc-soc.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering - * - * Bus Glue for PPC On-Chip EHCI driver - * Tested on AMCC 440EPx - * - * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> - -extern int usb_disabled(void); - -/* called during probe() after chip reset completes */ -static int ehci_ppc_soc_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - return ehci_reset(ehci); -} - -/** - * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - */ -int usb_ehci_ppc_soc_probe(const struct hc_driver *driver, - struct usb_hcd **hcd_out, - struct platform_device *dev) -{ - int retval; - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - - if (dev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug("resource[1] is not IORESOURCE_IRQ"); - retval = -ENOMEM; - } - hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI"); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed"); - retval = -ENOMEM; - goto err2; - } - - ehci = hcd_to_ehci(hcd); - ehci->big_endian_mmio = 1; - ehci->big_endian_desc = 1; - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - -#if defined(CONFIG_440EPX) - /* - * 440EPx Errata USBH_3 - * Fix: Enable Break Memory Transfer (BMT) in INSNREG3 - */ - out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0)); - ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n"); -#endif - - retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); - if (retval == 0) - return retval; - - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: - usb_put_hcd(hcd); - return retval; -} - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev) -{ - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -static const struct hc_driver ehci_ppc_soc_hc_driver = { - .description = hcd_name, - .product_desc = "PPC-SOC EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_ppc_soc_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, -}; - -static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd = NULL; - int ret; - - pr_debug("In ehci_hcd_ppc_soc_drv_probe\n"); - - if (usb_disabled()) - return -ENODEV; - - /* FIXME we only want one one probe() not two */ - ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev); - return ret; -} - -static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - /* FIXME we only want one one remove() not two */ - usb_ehci_ppc_soc_remove(hcd, pdev); - return 0; -} - -MODULE_ALIAS("platform:ppc-soc-ehci"); -static struct platform_driver ehci_ppc_soc_driver = { - .probe = ehci_hcd_ppc_soc_drv_probe, - .remove = ehci_hcd_ppc_soc_drv_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "ppc-soc-ehci", - } -}; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 5799298364fb..b11798d17ae5 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -99,6 +99,8 @@ struct ehci_hcd { /* one per controller */ owned by the companion during a bus suspend */ unsigned long port_c_suspend; /* which ports have the change-suspend feature turned on */ + unsigned long suspended_ports; /* which ports are + suspended */ /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ @@ -181,14 +183,16 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) * the async ring; just the I/O watchdog. Note that if a * SHRINK were pending, OFF would never be requested. */ - if (timer_pending(&ehci->watchdog) - && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) - & ehci->actions)) - return; + enum ehci_timer_action oldactions = ehci->actions; if (!test_and_set_bit (action, &ehci->actions)) { unsigned long t; + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & oldactions)) + return; + switch (action) { case TIMER_IO_WATCHDOG: t = EHCI_IO_JIFFIES; @@ -204,149 +208,13 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; break; } - mod_timer(&ehci->watchdog, t + jiffies); + mod_timer(&ehci->watchdog, round_jiffies(t + jiffies)); } } /*-------------------------------------------------------------------------*/ -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct ehci_caps { - /* these fields are specified as 8 and 16 bit registers, - * but some hosts can't perform 8 or 16 bit PCI accesses. - */ - u32 hc_capbase; -#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - u8 portroute [8]; /* nibbles for routing - offset 0xC */ -} __attribute__ ((packed)); - - -/* Section 2.3 Host Controller Operational Registers */ -struct ehci_regs { - - /* USBCMD: offset 0x00 */ - u32 command; -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - - /* USBSTS: offset 0x04 */ - u32 status; -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ -/* some bits reserved */ - /* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - - /* USBINTR: offset 0x08 */ - u32 intr_enable; - - /* FRINDEX: offset 0x0C */ - u32 frame_index; /* current microframe number */ - /* CTRLDSSEGMENT: offset 0x10 */ - u32 segment; /* address bits 63:32 if needed */ - /* PERIODICLISTBASE: offset 0x14 */ - u32 frame_list; /* points to periodic list */ - /* ASYNCLISTADDR: offset 0x18 */ - u32 async_next; /* address of next async queue head */ - - u32 reserved [9]; - - /* CONFIGFLAG: offset 0x40 */ - u32 configured_flag; -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - - /* PORTSC: offset 0x44 */ - u32 port_status [0]; /* up to N_PORTS */ -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -#define PORT_LED_OFF (0<<14) -#define PORT_LED_AMBER (1<<14) -#define PORT_LED_GREEN (2<<14) -#define PORT_LED_MASK (3<<14) -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CONNECT (1<<0) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) -} __attribute__ ((packed)); - -#define USBMODE 0x68 /* USB Device mode */ -#define USBMODE_SDIS (1<<3) /* Stream disable */ -#define USBMODE_BE (1<<2) /* BE/LE endianness select */ -#define USBMODE_CM_HC (3<<0) /* host controller mode */ -#define USBMODE_CM_IDLE (0<<0) /* idle state */ - -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct ehci_dbg_port { - u32 control; -#define DBGP_OWNER (1<<30) -#define DBGP_ENABLED (1<<28) -#define DBGP_DONE (1<<16) -#define DBGP_INUSE (1<<10) -#define DBGP_ERRCODE(x) (((x)>>7)&0x07) -# define DBGP_ERR_BAD 1 -# define DBGP_ERR_SIGNAL 2 -#define DBGP_ERROR (1<<6) -#define DBGP_GO (1<<5) -#define DBGP_OUT (1<<4) -#define DBGP_LEN(x) (((x)>>0)&0x0f) - u32 pids; -#define DBGP_PID_GET(x) (((x)>>16)&0xff) -#define DBGP_PID_SET(data,tok) (((data)<<8)|(tok)) - u32 data03; - u32 data47; - u32 address; -#define DBGP_EPADDR(dev,ep) (((dev)<<8)|(ep)) -} __attribute__ ((packed)); +#include <linux/usb/ehci_def.h> /*-------------------------------------------------------------------------*/ @@ -740,16 +608,7 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) /* * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. - * - * REVISIT: arch/powerpc now has readl/writel_be, so the - * definition below can die once the 4xx support is - * finally ported over. */ -#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) -#define readl_be(addr) in_be32((__force unsigned *)addr) -#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) -#endif - #if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX) #define readl_be(addr) __raw_readl((__force unsigned *)addr) #define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index ce1ca0ba0515..4dda31b26892 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1562,11 +1562,12 @@ static int __devinit isp116x_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct isp116x *isp116x; - struct resource *addr, *data; + struct resource *addr, *data, *ires; void __iomem *addr_reg; void __iomem *data_reg; int irq; int ret = 0; + unsigned long irqflags; if (pdev->num_resources < 3) { ret = -ENODEV; @@ -1575,12 +1576,16 @@ static int __devinit isp116x_probe(struct platform_device *pdev) data = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq = platform_get_irq(pdev, 0); - if (!addr || !data || irq < 0) { + ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + + if (!addr || !data || !ires) { ret = -ENODEV; goto err1; } + irq = ires->start; + irqflags = ires->flags & IRQF_TRIGGER_MASK; + if (pdev->dev.dma_mask) { DBG("DMA not supported\n"); ret = -EINVAL; @@ -1634,7 +1639,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev) goto err6; } - ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); + ret = usb_add_hcd(hcd, irq, irqflags | IRQF_DISABLED); if (ret) goto err6; diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 051ef7b6bdc6..af849f596135 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -218,7 +218,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, * and reading back and checking the contents are same or not */ if (reg_data != 0xFACE) { - err("scratch register mismatch %x", reg_data); + dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); goto clean; } @@ -232,9 +232,10 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, hcd = isp1760_register(pci_mem_phy0, length, dev->irq, IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), devflags); - pci_set_drvdata(dev, hcd); - if (!hcd) + if (!IS_ERR(hcd)) { + pci_set_drvdata(dev, hcd); return 0; + } clean: status = -ENODEV; iounmap(iobase); diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 7cef1d2f7ccc..d3269656aa4d 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -649,7 +649,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) ohci_dbg_sw (ohci, &next, &size, "bus %s, device %s\n" "%s\n" - "%s version " DRIVER_VERSION "\n", + "%s\n", hcd->self.controller->bus->name, dev_name(hcd->self.controller), hcd->product_desc, diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 89901962cbfd..8647dab0d7f9 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -46,7 +46,6 @@ #include "../core/hcd.h" -#define DRIVER_VERSION "2006 August 04" #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" @@ -984,10 +983,8 @@ static int ohci_restart (struct ohci_hcd *ohci) /*-------------------------------------------------------------------------*/ -#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC - MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI @@ -1095,9 +1092,10 @@ static int __init ohci_hcd_mod_init(void) if (usb_disabled()) return -ENODEV; - printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name); + printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, sizeof (struct ed), sizeof (struct td)); + set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); #ifdef DEBUG ohci_debug_root = debugfs_create_dir("ohci", NULL); @@ -1184,6 +1182,7 @@ static int __init ohci_hcd_mod_init(void) error_debug: #endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); return retval; } module_init(ohci_hcd_mod_init); @@ -1214,6 +1213,7 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef DEBUG debugfs_remove(ohci_debug_root); #endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); } module_exit(ohci_hcd_mod_exit); diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 7ea9a7b31155..32bbce9718f0 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -359,21 +359,24 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd) /* Carry out polling-, autostop-, and autoresume-related state changes */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, - int any_connected) + int any_connected, int rhsc_status) { int poll_rh = 1; - int rhsc; + int rhsc_enable; - rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; - switch (ohci->hc_control & OHCI_CTRL_HCFS) { + /* Some broken controllers never turn off RHCS in the interrupt + * status register. For their sake we won't re-enable RHSC + * interrupts if the interrupt bit is already active. + */ + rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC; + switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* If no status changes are pending, enable status-change - * interrupts. - */ - if (!rhsc && !changed) { - rhsc = OHCI_INTR_RHSC; - ohci_writel(ohci, rhsc, &ohci->regs->intrenable); + /* If no status changes are pending, enable RHSC interrupts. */ + if (!rhsc_enable && !rhsc_status && !changed) { + rhsc_enable = OHCI_INTR_RHSC; + ohci_writel(ohci, rhsc_enable, &ohci->regs->intrenable); } /* Keep on polling until we know a device is connected @@ -383,7 +386,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (rhsc) + if (rhsc_enable) poll_rh = 0; } else { ohci->autostop = 1; @@ -396,34 +399,45 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (rhsc && time_after_eq(jiffies, + } else if (time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); - poll_rh = 0; + if (rhsc_enable) + poll_rh = 0; } } break; - /* if there is a port change, autostart or ask to be resumed */ case OHCI_USB_SUSPEND: case OHCI_USB_RESUME: + /* if there is a port change, autostart or ask to be resumed */ if (changed) { if (ohci->autostop) ohci_rh_resume(ohci); else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); - } else { - if (!rhsc && (ohci->autostop || - ohci_to_hcd(ohci)->self.root_hub-> - do_remote_wakeup)) - ohci_writel(ohci, OHCI_INTR_RHSC, - &ohci->regs->intrenable); - /* everything is idle, no need for polling */ + /* If remote wakeup is disabled, stop polling */ + } else if (!ohci->autostop && + !ohci_to_hcd(ohci)->self.root_hub-> + do_remote_wakeup) { poll_rh = 0; + + } else { + /* If no status changes are pending, + * enable RHSC interrupts + */ + if (!rhsc_enable && !rhsc_status) { + rhsc_enable = OHCI_INTR_RHSC; + ohci_writel(ohci, rhsc_enable, + &ohci->regs->intrenable); + } + /* Keep polling until RHSC is enabled */ + if (rhsc_enable) + poll_rh = 0; } break; } @@ -441,18 +455,22 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) * autostop isn't used when CONFIG_PM is turned off. */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, - int any_connected) + int any_connected, int rhsc_status) { /* If RHSC is enabled, don't poll */ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) return 0; - /* If no status changes are pending, enable status-change interrupts */ - if (!changed) { - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - return 0; - } - return 1; + /* If status changes are pending, continue polling. + * Conversely, if no status changes are pending but the RHSC + * status bit was set, then RHSC may be broken so continue polling. + */ + if (changed || rhsc_status) + return 1; + + /* It's safe to re-enable RHSC interrupts */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + return 0; } #endif /* CONFIG_PM */ @@ -467,6 +485,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; int any_connected = 0; + int rhsc_status; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); @@ -492,12 +511,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) length++; } - /* Some broken controllers never turn off RHCS in the interrupt - * status register. For their sake we won't re-enable RHSC - * interrupts if the flag is already set. - */ - if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) - changed = 1; + /* Clear the RHSC status flag before reading the port statuses */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus); + rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) & + OHCI_INTR_RHSC; /* look at each port */ for (i = 0; i < ohci->num_ports; i++) { @@ -517,7 +534,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) } hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed, - any_connected); + any_connected, rhsc_status); done: spin_unlock_irqrestore (&ohci->lock, flags); diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 95b3ec89c126..91697bdb399f 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -231,7 +231,7 @@ static int ohci_omap_init(struct usb_hcd *hcd) omap_ohci_clock_power(1); - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { omap_1510_local_bus_power(1); omap_1510_local_bus_init(); } @@ -319,7 +319,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, if (IS_ERR(usb_host_ck)) return PTR_ERR(usb_host_ck); - if (!cpu_is_omap1510()) + if (!cpu_is_omap15xx()) usb_dc_ck = clk_get(0, "usb_dc_ck"); else usb_dc_ck = clk_get(0, "lb_ck"); @@ -344,7 +344,12 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, goto err1; } - hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start); + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(&pdev->dev, "can't ioremap OHCI HCD\n"); + retval = -ENOMEM; + goto err2; + } ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); @@ -355,11 +360,11 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, irq = platform_get_irq(pdev, 0); if (irq < 0) { retval = -ENXIO; - goto err2; + goto err3; } retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (retval) - goto err2; + goto err3; host_initialized = 1; @@ -367,6 +372,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, omap_ohci_clock_power(0); return 0; +err3: + iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: @@ -401,6 +408,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) } if (machine_is_omap_osk()) omap_free_gpio(9); + iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); clk_put(usb_dc_ck); diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 658a2a978c32..e306ca6aef3d 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -331,7 +331,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) int ret = 0, irq; - dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name); + dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name); if (usb_disabled()) { err("USB is disabled"); ret = -ENODEV; diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 7f0f35c78185..e294d430733b 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -23,17 +23,90 @@ #include <linux/signal.h> #include <linux/platform_device.h> #include <linux/clk.h> - -#include <mach/hardware.h> -#include <mach/pxa-regs.h> -#include <mach/pxa2xx-regs.h> /* FIXME: for PSSR */ #include <mach/ohci.h> +/* + * UHC: USB Host Controller (OHCI-like) register definitions + */ +#define UHCREV (0x0000) /* UHC HCI Spec Revision */ +#define UHCHCON (0x0004) /* UHC Host Control Register */ +#define UHCCOMS (0x0008) /* UHC Command Status Register */ +#define UHCINTS (0x000C) /* UHC Interrupt Status Register */ +#define UHCINTE (0x0010) /* UHC Interrupt Enable */ +#define UHCINTD (0x0014) /* UHC Interrupt Disable */ +#define UHCHCCA (0x0018) /* UHC Host Controller Comm. Area */ +#define UHCPCED (0x001C) /* UHC Period Current Endpt Descr */ +#define UHCCHED (0x0020) /* UHC Control Head Endpt Descr */ +#define UHCCCED (0x0024) /* UHC Control Current Endpt Descr */ +#define UHCBHED (0x0028) /* UHC Bulk Head Endpt Descr */ +#define UHCBCED (0x002C) /* UHC Bulk Current Endpt Descr */ +#define UHCDHEAD (0x0030) /* UHC Done Head */ +#define UHCFMI (0x0034) /* UHC Frame Interval */ +#define UHCFMR (0x0038) /* UHC Frame Remaining */ +#define UHCFMN (0x003C) /* UHC Frame Number */ +#define UHCPERS (0x0040) /* UHC Periodic Start */ +#define UHCLS (0x0044) /* UHC Low Speed Threshold */ + +#define UHCRHDA (0x0048) /* UHC Root Hub Descriptor A */ +#define UHCRHDA_NOCP (1 << 12) /* No over current protection */ +#define UHCRHDA_OCPM (1 << 11) /* Over Current Protection Mode */ +#define UHCRHDA_POTPGT(x) \ + (((x) & 0xff) << 24) /* Power On To Power Good Time */ + +#define UHCRHDB (0x004C) /* UHC Root Hub Descriptor B */ +#define UHCRHS (0x0050) /* UHC Root Hub Status */ +#define UHCRHPS1 (0x0054) /* UHC Root Hub Port 1 Status */ +#define UHCRHPS2 (0x0058) /* UHC Root Hub Port 2 Status */ +#define UHCRHPS3 (0x005C) /* UHC Root Hub Port 3 Status */ + +#define UHCSTAT (0x0060) /* UHC Status Register */ +#define UHCSTAT_UPS3 (1 << 16) /* USB Power Sense Port3 */ +#define UHCSTAT_SBMAI (1 << 15) /* System Bus Master Abort Interrupt*/ +#define UHCSTAT_SBTAI (1 << 14) /* System Bus Target Abort Interrupt*/ +#define UHCSTAT_UPRI (1 << 13) /* USB Port Resume Interrupt */ +#define UHCSTAT_UPS2 (1 << 12) /* USB Power Sense Port 2 */ +#define UHCSTAT_UPS1 (1 << 11) /* USB Power Sense Port 1 */ +#define UHCSTAT_HTA (1 << 10) /* HCI Target Abort */ +#define UHCSTAT_HBA (1 << 8) /* HCI Buffer Active */ +#define UHCSTAT_RWUE (1 << 7) /* HCI Remote Wake Up Event */ + +#define UHCHR (0x0064) /* UHC Reset Register */ +#define UHCHR_SSEP3 (1 << 11) /* Sleep Standby Enable for Port3 */ +#define UHCHR_SSEP2 (1 << 10) /* Sleep Standby Enable for Port2 */ +#define UHCHR_SSEP1 (1 << 9) /* Sleep Standby Enable for Port1 */ +#define UHCHR_PCPL (1 << 7) /* Power control polarity low */ +#define UHCHR_PSPL (1 << 6) /* Power sense polarity low */ +#define UHCHR_SSE (1 << 5) /* Sleep Standby Enable */ +#define UHCHR_UIT (1 << 4) /* USB Interrupt Test */ +#define UHCHR_SSDC (1 << 3) /* Simulation Scale Down Clock */ +#define UHCHR_CGR (1 << 2) /* Clock Generation Reset */ +#define UHCHR_FHR (1 << 1) /* Force Host Controller Reset */ +#define UHCHR_FSBIR (1 << 0) /* Force System Bus Iface Reset */ + +#define UHCHIE (0x0068) /* UHC Interrupt Enable Register*/ +#define UHCHIE_UPS3IE (1 << 14) /* Power Sense Port3 IntEn */ +#define UHCHIE_UPRIE (1 << 13) /* Port Resume IntEn */ +#define UHCHIE_UPS2IE (1 << 12) /* Power Sense Port2 IntEn */ +#define UHCHIE_UPS1IE (1 << 11) /* Power Sense Port1 IntEn */ +#define UHCHIE_TAIE (1 << 10) /* HCI Interface Transfer Abort + Interrupt Enable*/ +#define UHCHIE_HBAIE (1 << 8) /* HCI Buffer Active IntEn */ +#define UHCHIE_RWIE (1 << 7) /* Remote Wake-up IntEn */ + +#define UHCHIT (0x006C) /* UHC Interrupt Test register */ + #define PXA_UHC_MAX_PORTNUM 3 -#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 ) +struct pxa27x_ohci { + /* must be 1st member here for hcd_to_ohci() to work */ + struct ohci_hcd ohci; + + struct device *dev; + struct clk *clk; + void __iomem *mmio_base; +}; -static struct clk *usb_clk; +#define to_pxa27x_ohci(hcd) (struct pxa27x_ohci *)hcd_to_ohci(hcd) /* PMM_NPS_MODE -- PMM Non-power switching mode @@ -45,30 +118,35 @@ static struct clk *usb_clk; PMM_PERPORT_MODE -- PMM per port switching mode Ports are powered individually. */ -static int pxa27x_ohci_select_pmm( int mode ) +static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *ohci, int mode) { - switch ( mode ) { + uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA); + uint32_t uhcrhdb = __raw_readl(ohci->mmio_base + UHCRHDB); + + switch (mode) { case PMM_NPS_MODE: - UHCRHDA |= RH_A_NPS; + uhcrhda |= RH_A_NPS; break; case PMM_GLOBAL_MODE: - UHCRHDA &= ~(RH_A_NPS & RH_A_PSM); + uhcrhda &= ~(RH_A_NPS & RH_A_PSM); break; case PMM_PERPORT_MODE: - UHCRHDA &= ~(RH_A_NPS); - UHCRHDA |= RH_A_PSM; + uhcrhda &= ~(RH_A_NPS); + uhcrhda |= RH_A_PSM; /* Set port power control mask bits, only 3 ports. */ - UHCRHDB |= (0x7<<17); + uhcrhdb |= (0x7<<17); break; default: printk( KERN_ERR "Invalid mode %d, set to non-power switch mode.\n", mode ); - UHCRHDA |= RH_A_NPS; + uhcrhda |= RH_A_NPS; } + __raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA); + __raw_writel(uhcrhdb, ohci->mmio_base + UHCRHDB); return 0; } @@ -76,57 +154,110 @@ extern int usb_disabled(void); /*-------------------------------------------------------------------------*/ -static int pxa27x_start_hc(struct device *dev) +static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci, + struct pxaohci_platform_data *inf) +{ + uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR); + uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA); + + if (inf->flags & ENABLE_PORT1) + uhchr &= ~UHCHR_SSEP1; + + if (inf->flags & ENABLE_PORT2) + uhchr &= ~UHCHR_SSEP2; + + if (inf->flags & ENABLE_PORT3) + uhchr &= ~UHCHR_SSEP3; + + if (inf->flags & POWER_CONTROL_LOW) + uhchr |= UHCHR_PCPL; + + if (inf->flags & POWER_SENSE_LOW) + uhchr |= UHCHR_PSPL; + + if (inf->flags & NO_OC_PROTECTION) + uhcrhda |= UHCRHDA_NOCP; + + if (inf->flags & OC_MODE_PERPORT) + uhcrhda |= UHCRHDA_OCPM; + + if (inf->power_on_delay) { + uhcrhda &= ~UHCRHDA_POTPGT(0xff); + uhcrhda |= UHCRHDA_POTPGT(inf->power_on_delay / 2); + } + + __raw_writel(uhchr, ohci->mmio_base + UHCHR); + __raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA); +} + +static inline void pxa27x_reset_hc(struct pxa27x_ohci *ohci) +{ + uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR); + + __raw_writel(uhchr | UHCHR_FHR, ohci->mmio_base + UHCHR); + udelay(11); + __raw_writel(uhchr & ~UHCHR_FHR, ohci->mmio_base + UHCHR); +} + +#ifdef CONFIG_CPU_PXA27x +extern void pxa27x_clear_otgph(void); +#else +#define pxa27x_clear_otgph() do {} while (0) +#endif + +static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev) { int retval = 0; struct pxaohci_platform_data *inf; + uint32_t uhchr; inf = dev->platform_data; - clk_enable(usb_clk); + clk_enable(ohci->clk); - UHCHR |= UHCHR_FHR; - udelay(11); - UHCHR &= ~UHCHR_FHR; + pxa27x_reset_hc(ohci); + + uhchr = __raw_readl(ohci->mmio_base + UHCHR) | UHCHR_FSBIR; + __raw_writel(uhchr, ohci->mmio_base + UHCHR); - UHCHR |= UHCHR_FSBIR; - while (UHCHR & UHCHR_FSBIR) + while (__raw_readl(ohci->mmio_base + UHCHR) & UHCHR_FSBIR) cpu_relax(); + pxa27x_setup_hc(ohci, inf); + if (inf->init) retval = inf->init(dev); if (retval < 0) return retval; - UHCHR &= ~UHCHR_SSE; - - UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); + uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE; + __raw_writel(uhchr, ohci->mmio_base + UHCHR); + __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE); /* Clear any OTG Pin Hold */ - if (cpu_is_pxa27x() && (PSSR & PSSR_OTGPH)) - PSSR |= PSSR_OTGPH; - + pxa27x_clear_otgph(); return 0; } -static void pxa27x_stop_hc(struct device *dev) +static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) { struct pxaohci_platform_data *inf; + uint32_t uhccoms; inf = dev->platform_data; if (inf->exit) inf->exit(dev); - UHCHR |= UHCHR_FHR; - udelay(11); - UHCHR &= ~UHCHR_FHR; + pxa27x_reset_hc(ohci); - UHCCOMS |= 1; + /* Host Controller Reset */ + uhccoms = __raw_readl(ohci->mmio_base + UHCCOMS) | 0x01; + __raw_writel(uhccoms, ohci->mmio_base + UHCCOMS); udelay(10); - clk_disable(usb_clk); + clk_disable(ohci->clk); } @@ -147,18 +278,22 @@ static void pxa27x_stop_hc(struct device *dev) */ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev) { - int retval; + int retval, irq; struct usb_hcd *hcd; struct pxaohci_platform_data *inf; + struct pxa27x_ohci *ohci; + struct resource *r; + struct clk *usb_clk; inf = pdev->dev.platform_data; if (!inf) return -ENODEV; - if (pdev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug ("resource[1] is not IORESOURCE_IRQ"); - return -ENOMEM; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + pr_err("no resource of IORESOURCE_IRQ"); + return -ENXIO; } usb_clk = clk_get(&pdev->dev, "USBCLK"); @@ -168,8 +303,16 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); if (!hcd) return -ENOMEM; - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + pr_err("no resource of IORESOURCE_MEM"); + retval = -ENXIO; + goto err1; + } + + hcd->rsrc_start = r->start; + hcd->rsrc_len = resource_size(r); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed"); @@ -184,24 +327,30 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device goto err2; } - if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) { + /* initialize "struct pxa27x_ohci" */ + ohci = (struct pxa27x_ohci *)hcd_to_ohci(hcd); + ohci->dev = &pdev->dev; + ohci->clk = usb_clk; + ohci->mmio_base = (void __iomem *)hcd->regs; + + if ((retval = pxa27x_start_hc(ohci, &pdev->dev)) < 0) { pr_debug("pxa27x_start_hc failed"); goto err3; } /* Select Power Management Mode */ - pxa27x_ohci_select_pmm(inf->port_mode); + pxa27x_ohci_select_pmm(ohci, inf->port_mode); if (inf->power_budget) hcd->power_budget = inf->power_budget; ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED); + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (retval == 0) return retval; - pxa27x_stop_hc(&pdev->dev); + pxa27x_stop_hc(ohci, &pdev->dev); err3: iounmap(hcd->regs); err2: @@ -228,12 +377,14 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device */ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) { + struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); + usb_remove_hcd(hcd); - pxa27x_stop_hc(&pdev->dev); + pxa27x_stop_hc(ohci, &pdev->dev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); - clk_put(usb_clk); + clk_put(ohci->clk); } /*-------------------------------------------------------------------------*/ @@ -266,7 +417,7 @@ ohci_pxa27x_start (struct usb_hcd *hcd) static const struct hc_driver ohci_pxa27x_hc_driver = { .description = hcd_name, .product_desc = "PXA27x OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), + .hcd_priv_size = sizeof(struct pxa27x_ohci), /* * generic hardware linkage @@ -330,13 +481,13 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); - if (time_before(jiffies, ohci->next_statechange)) + if (time_before(jiffies, ohci->ohci.next_statechange)) msleep(5); - ohci->next_statechange = jiffies; + ohci->ohci.next_statechange = jiffies; - pxa27x_stop_hc(&pdev->dev); + pxa27x_stop_hc(ohci, &pdev->dev); hcd->state = HC_STATE_SUSPENDED; return 0; @@ -345,14 +496,14 @@ static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); int status; - if (time_before(jiffies, ohci->next_statechange)) + if (time_before(jiffies, ohci->ohci.next_statechange)) msleep(5); - ohci->next_statechange = jiffies; + ohci->ohci.next_statechange = jiffies; - if ((status = pxa27x_start_hc(&pdev->dev)) < 0) + if ((status = pxa27x_start_hc(ohci, &pdev->dev)) < 0) return status; ohci_finish_controller_resume(hcd); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index faf622eafce7..222011f6172c 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -540,15 +540,7 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci) * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. * - * REVISIT: arch/powerpc now has readl/writel_be, so the - * definition below can die once the STB04xxx support is - * finally ported over. */ -#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) -#define readl_be(addr) in_be32((__force unsigned *)addr) -#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) -#endif - static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs) { diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index ea7126f99cab..c18d8790c410 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -66,7 +66,7 @@ static unsigned short endian; module_param(endian, ushort, 0644); MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)"); -static unsigned short irq_sense = INTL; +static unsigned short irq_sense = 0xff; module_param(irq_sense, ushort, 0644); MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0 " "(default=32)"); @@ -118,7 +118,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) r8a66597_write(r8a66597, SCKE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { - err("register access fail."); + printk(KERN_ERR "r8a66597: register access fail.\n"); return -ENXIO; } } while ((tmp & SCKE) != SCKE); @@ -128,7 +128,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) r8a66597_write(r8a66597, USBE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { - err("register access fail."); + printk(KERN_ERR "r8a66597: register access fail.\n"); return -ENXIO; } } while ((tmp & USBE) != USBE); @@ -141,7 +141,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) msleep(1); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 500) { - err("register access fail."); + printk(KERN_ERR "r8a66597: register access fail.\n"); return -ENXIO; } } while ((tmp & SCKE) != SCKE); @@ -265,7 +265,7 @@ static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port) if (root_port) { *root_port = (devpath[0] & 0x0F) - 1; if (*root_port >= R8A66597_MAX_ROOT_HUB) - err("illegal root port number"); + printk(KERN_ERR "r8a66597: Illegal root port number.\n"); } if (hub_port) *hub_port = devpath[2] & 0x0F; @@ -286,7 +286,7 @@ static u16 get_r8a66597_usb_speed(enum usb_device_speed speed) usbspd = HSMODE; break; default: - err("unknown speed"); + printk(KERN_ERR "r8a66597: unknown speed\n"); break; } @@ -385,7 +385,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb) struct r8a66597_device *dev; if (is_hub_limit(urb->dev->devpath)) { - err("Externel hub limit reached."); + dev_err(&urb->dev->dev, "External hub limit reached.\n"); return 0; } @@ -406,8 +406,9 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb) return addr; } - err("cannot communicate with a USB device more than 10.(%x)", - r8a66597->address_map); + dev_err(&urb->dev->dev, + "cannot communicate with a USB device more than 10.(%x)\n", + r8a66597->address_map); return 0; } @@ -447,7 +448,8 @@ static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg, do { tmp = r8a66597_read(r8a66597, reg); if (i++ > 1000000) { - err("register%lx, loop %x is timeout", reg, loop); + printk(KERN_ERR "r8a66597: register%lx, loop %x " + "is timeout\n", reg, loop); break; } ndelay(1); @@ -675,7 +677,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, array[i++] = 1; break; default: - err("Illegal type"); + printk(KERN_ERR "r8a66597: Illegal type\n"); return 0; } @@ -705,7 +707,7 @@ static u16 get_r8a66597_type(__u8 type) r8a66597_type = R8A66597_ISO; break; default: - err("Illegal type"); + printk(KERN_ERR "r8a66597: Illegal type\n"); r8a66597_type = 0x0000; break; } @@ -724,7 +726,7 @@ static u16 get_bufnum(u16 pipenum) else if (check_interrupt(pipenum)) bufnum = 4 + (pipenum - 6); else - err("Illegal pipenum (%d)", pipenum); + printk(KERN_ERR "r8a66597: Illegal pipenum (%d)\n", pipenum); return bufnum; } @@ -740,7 +742,7 @@ static u16 get_buf_bsize(u16 pipenum) else if (check_interrupt(pipenum)) buf_bsize = 0; else - err("Illegal pipenum (%d)", pipenum); + printk(KERN_ERR "r8a66597: Illegal pipenum (%d)\n", pipenum); return buf_bsize; } @@ -760,10 +762,12 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, if ((r8a66597->dma_map & (1 << i)) != 0) continue; - info("address %d, EndpointAddress 0x%02x use DMA FIFO", - usb_pipedevice(urb->pipe), - info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum - : info->epnum); + dev_info(&dev->udev->dev, + "address %d, EndpointAddress 0x%02x use " + "DMA FIFO\n", usb_pipedevice(urb->pipe), + info->dir_in ? + USB_ENDPOINT_DIR_MASK + info->epnum + : info->epnum); r8a66597->dma_map |= 1 << i; dev->dma_map |= 1 << i; @@ -1187,7 +1191,7 @@ static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td) prepare_status_packet(r8a66597, td); break; default: - err("invalid type."); + printk(KERN_ERR "r8a66597: invalid type.\n"); break; } @@ -1295,7 +1299,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) if (unlikely((tmp & FRDY) == 0)) { pipe_stop(r8a66597, td->pipe); pipe_irq_disable(r8a66597, pipenum); - err("in fifo not ready (%d)", pipenum); + printk(KERN_ERR "r8a66597: in fifo not ready (%d)\n", pipenum); finish_request(r8a66597, td, pipenum, td->urb, -EPIPE); return; } @@ -1370,7 +1374,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) if (unlikely((tmp & FRDY) == 0)) { pipe_stop(r8a66597, td->pipe); pipe_irq_disable(r8a66597, pipenum); - err("out write fifo not ready. (%d)", pipenum); + printk(KERN_ERR "r8a66597: out fifo not ready (%d)\n", pipenum); finish_request(r8a66597, td, pipenum, urb, -EPIPE); return; } @@ -2005,7 +2009,7 @@ static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597, return dev; } - err("get_r8a66597_device fail.(%d)\n", addr); + printk(KERN_ERR "r8a66597: get_r8a66597_device fail.(%d)\n", addr); return NULL; } @@ -2263,7 +2267,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev) #define resource_len(r) (((r)->end - (r)->start) + 1) static int __init r8a66597_probe(struct platform_device *pdev) { - struct resource *res = NULL; + struct resource *res = NULL, *ires; int irq = -1; void __iomem *reg = NULL; struct usb_hcd *hcd = NULL; @@ -2274,7 +2278,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) if (pdev->dev.dma_mask) { ret = -EINVAL; - err("dma not support"); + dev_err(&pdev->dev, "dma not supported\n"); goto clean_up; } @@ -2282,21 +2286,25 @@ static int __init r8a66597_probe(struct platform_device *pdev) (char *)hcd_name); if (!res) { ret = -ENODEV; - err("platform_get_resource_byname error."); + dev_err(&pdev->dev, "platform_get_resource_byname error.\n"); goto clean_up; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { + ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!ires) { ret = -ENODEV; - err("platform_get_irq error."); + dev_err(&pdev->dev, + "platform_get_resource IORESOURCE_IRQ error.\n"); goto clean_up; } + irq = ires->start; + irq_trigger = ires->flags & IRQF_TRIGGER_MASK; + reg = ioremap(res->start, resource_len(res)); if (reg == NULL) { ret = -ENOMEM; - err("ioremap error."); + dev_err(&pdev->dev, "ioremap error.\n"); goto clean_up; } @@ -2304,7 +2312,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) hcd = usb_create_hcd(&r8a66597_hc_driver, &pdev->dev, (char *)hcd_name); if (!hcd) { ret = -ENOMEM; - err("Failed to create hcd"); + dev_err(&pdev->dev, "Failed to create hcd\n"); goto clean_up; } r8a66597 = hcd_to_r8a66597(hcd); @@ -2329,13 +2337,33 @@ static int __init r8a66597_probe(struct platform_device *pdev) INIT_LIST_HEAD(&r8a66597->child_device); hcd->rsrc_start = res->start; - if (irq_sense == INTL) - irq_trigger = IRQF_TRIGGER_LOW; - else - irq_trigger = IRQF_TRIGGER_FALLING; + + /* irq_sense setting on cmdline takes precedence over resource + * settings, so the introduction of irqflags in IRQ resourse + * won't disturb existing setups */ + switch (irq_sense) { + case INTL: + irq_trigger = IRQF_TRIGGER_LOW; + break; + case 0: + irq_trigger = IRQF_TRIGGER_FALLING; + break; + case 0xff: + if (irq_trigger) + irq_sense = (irq_trigger & IRQF_TRIGGER_LOW) ? + INTL : 0; + else { + irq_sense = INTL; + irq_trigger = IRQF_TRIGGER_LOW; + } + break; + default: + dev_err(&pdev->dev, "Unknown irq_sense value.\n"); + } + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger); if (ret != 0) { - err("Failed to add hcd"); + dev_err(&pdev->dev, "Failed to add hcd\n"); goto clean_up; } @@ -2364,7 +2392,8 @@ static int __init r8a66597_init(void) if (usb_disabled()) return -ENODEV; - info("driver %s, %s", hcd_name, DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": driver %s, %s\n", hcd_name, + DRIVER_VERSION); return platform_driver_register(&r8a66597_driver); } module_init(r8a66597_init); diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 8a74bbb57d08..e106e9d48d4a 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1620,22 +1620,26 @@ sl811h_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct sl811 *sl811; - struct resource *addr, *data; + struct resource *addr, *data, *ires; int irq; void __iomem *addr_reg; void __iomem *data_reg; int retval; u8 tmp, ioaddr = 0; + unsigned long irqflags; /* basic sanity checks first. board-specific init logic should * have initialized these three resources and probably board * specific platform_data. we don't probe for IRQs, and do only * minimal sanity checking. */ - irq = platform_get_irq(dev, 0); - if (dev->num_resources < 3 || irq < 0) + ires = platform_get_resource(dev, IORESOURCE_IRQ, 0); + if (dev->num_resources < 3 || !ires) return -ENODEV; + irq = ires->start; + irqflags = ires->flags & IRQF_TRIGGER_MASK; + /* refuse to confuse usbcore */ if (dev->dev.dma_mask) { DBG("no we won't dma\n"); @@ -1717,8 +1721,11 @@ sl811h_probe(struct platform_device *dev) * triggers (e.g. most ARM CPUs). Initial driver stress testing * was on a system with single edge triggering, so most sorts of * triggering arrangement should work. + * + * Use resource IRQ flags if set by platform device setup. */ - retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + irqflags |= IRQF_SHARED; + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | irqflags); if (retval != 0) goto err6; diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 5da63f535005..516848dd9b48 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -112,7 +112,8 @@ static struct platform_device platform_dev = { .num_resources = ARRAY_SIZE(resources), }; -static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) +static int sl811_hc_init(struct device *parent, resource_size_t base_addr, + int irq) { if (platform_dev.dev.parent) return -EBUSY; @@ -155,97 +156,72 @@ static void sl811_cs_release(struct pcmcia_device * link) platform_device_unregister(&platform_dev); } +static int sl811_cs_config_check(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) +{ + if (cfg->index == 0) + return -ENODEV; + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { + if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc) + return -ENODEV; + } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) { + if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc) + return -ENODEV; + } + + if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + p_dev->conf.Vpp = + cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; + else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) + p_dev->conf.Vpp = + dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; + + /* we need an interrupt */ + if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) + p_dev->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->io.BasePort1 = io->win[0].base; + p_dev->io.NumPorts1 = io->win[0].len; + + return pcmcia_request_io(p_dev, &p_dev->io); + } + pcmcia_disable_device(p_dev); + return -ENODEV; +} + + static int sl811_cs_config(struct pcmcia_device *link) { struct device *parent = &handle_to_dev(link); local_info_t *dev = link->priv; - tuple_t tuple; - cisparse_t parse; int last_fn, last_ret; - u_char buf[64]; - config_info_t conf; - cistpl_cftable_entry_t dflt = { 0 }; DBG(0, "sl811_cs_config(0x%p)\n", link); - /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(link, &conf)); - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - while (1) { - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - - if (pcmcia_get_tuple_data(link, &tuple) != 0 - || pcmcia_parse_tuple(link, &tuple, &parse) - != 0) - goto next_entry; - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { - dflt = *cfg; - } - - if (cfg->index == 0) - goto next_entry; - - link->conf.ConfigIndex = cfg->index; - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 - != conf.Vcc) - goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000 - != conf.Vcc) - goto next_entry; - } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* we need an interrupt */ - if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - - if (pcmcia_request_io(link, &link->io) != 0) - goto next_entry; - } - break; - -next_entry: - pcmcia_disable_device(link); - last_ret = pcmcia_get_next_tuple(link, &tuple); - } + if (pcmcia_loop_config(link, sl811_cs_config_check, NULL)) + goto failed; /* require an IRQ and two registers */ if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) - goto cs_failed; + goto failed; if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); else - goto cs_failed; + goto failed; CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); @@ -266,8 +242,9 @@ next_entry: if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) < 0) { cs_failed: - printk("sl811_cs_config failed\n"); cs_error(link, last_fn, last_ret); +failed: + printk(KERN_WARNING "sl811_cs_config failed\n"); sl811_cs_release(link); return -ENODEV; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 3a7bfe7a8874..cf5e4cf7ea42 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -53,7 +53,6 @@ /* * Version Information */ -#define DRIVER_VERSION "v3.0" #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ Alan Stern" @@ -951,12 +950,13 @@ static int __init uhci_hcd_init(void) { int retval = -ENOMEM; - printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n", - ignore_oc ? ", overcurrent ignored" : ""); - if (usb_disabled()) return -ENODEV; + printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n", + ignore_oc ? ", overcurrent ignored" : ""); + set_bit(USB_UHCI_LOADED, &usb_hcds_loaded); + if (DEBUG_CONFIGURED) { errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); if (!errbuf) @@ -988,6 +988,7 @@ debug_failed: errbuf_failed: + clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); return retval; } @@ -997,6 +998,7 @@ static void __exit uhci_hcd_cleanup(void) kmem_cache_destroy(uhci_up_cachep); debugfs_remove(uhci_debugfs_root); kfree(errbuf); + clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); } module_init(uhci_hcd_init); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index db645936eedd..5631d89c8730 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -123,14 +123,10 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) { - if (!list_empty(&td->list)) { - dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); - WARN_ON(1); - } - if (!list_empty(&td->fl_list)) { - dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); - WARN_ON(1); - } + if (!list_empty(&td->list)) + dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td); + if (!list_empty(&td->fl_list)) + dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td); dma_pool_free(uhci->td_pool, td, td->dma_handle); } @@ -295,10 +291,8 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); - if (!list_empty(&qh->queue)) { - dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh); - WARN_ON(1); - } + if (!list_empty(&qh->queue)) + dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh); list_del(&qh->node); if (qh->udev) { @@ -746,11 +740,9 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci, { struct uhci_td *td, *tmp; - if (!list_empty(&urbp->node)) { - dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", + if (!list_empty(&urbp->node)) + dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n", urbp->urb); - WARN_ON(1); - } list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { uhci_remove_td_from_urbp(td); @@ -1073,13 +1065,18 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, } if (exponent < 0) return -EINVAL; - qh->period = 1 << exponent; - qh->skel = SKEL_INDEX(exponent); - /* For now, interrupt phase is fixed by the layout - * of the QH lists. */ - qh->phase = (qh->period / 2) & (MAX_PHASE - 1); - ret = uhci_check_bandwidth(uhci, qh); + /* If the slot is full, try a lower period */ + do { + qh->period = 1 << exponent; + qh->skel = SKEL_INDEX(exponent); + + /* For now, interrupt phase is fixed by the layout + * of the QH lists. + */ + qh->phase = (qh->period / 2) & (MAX_PHASE - 1); + ret = uhci_check_bandwidth(uhci, qh); + } while (ret != 0 && --exponent >= 0); if (ret) return ret; } else if (qh->period > urb->interval) diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 0fb114ca1eba..878c77ca086e 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -355,13 +355,14 @@ static int mdc800_usb_waitForIRQ (int mode, int msec) if (mdc800->camera_request_ready>0) { mdc800->camera_request_ready=0; - err ("timeout waiting for camera."); + dev_err(&mdc800->dev->dev, "timeout waiting for camera.\n"); return -1; } if (mdc800->state == NOT_CONNECTED) { - warn ("Camera gets disconnected during waiting for irq."); + printk(KERN_WARNING "mdc800: Camera gets disconnected " + "during waiting for irq.\n"); mdc800->camera_request_ready=0; return -2; } @@ -379,7 +380,8 @@ static void mdc800_usb_write_notify (struct urb *urb) int status = urb->status; if (status != 0) - err ("writing command fails (status=%i)", status); + dev_err(&mdc800->dev->dev, + "writing command fails (status=%i)\n", status); else mdc800->state=READY; mdc800->written = 1; @@ -406,7 +408,8 @@ static void mdc800_usb_download_notify (struct urb *urb) mdc800->state=READY; } } else { - err ("request bytes fails (status:%i)", status); + dev_err(&mdc800->dev->dev, + "request bytes fails (status:%i)\n", status); } mdc800->downloaded = 1; wake_up (&mdc800->download_wait); @@ -443,13 +446,14 @@ static int mdc800_usb_probe (struct usb_interface *intf, if (mdc800->dev != NULL) { - warn ("only one Mustek MDC800 is supported."); + dev_warn(&intf->dev, "only one Mustek MDC800 is supported.\n"); return -ENODEV; } if (dev->descriptor.bNumConfigurations != 1) { - err ("probe fails -> wrong Number of Configuration"); + dev_err(&intf->dev, + "probe fails -> wrong Number of Configuration\n"); return -ENODEV; } intf_desc = intf->cur_altsetting; @@ -461,7 +465,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, || ( intf_desc->desc.bNumEndpoints != 4) ) { - err ("probe fails -> wrong Interface"); + dev_err(&intf->dev, "probe fails -> wrong Interface\n"); return -ENODEV; } @@ -482,19 +486,19 @@ static int mdc800_usb_probe (struct usb_interface *intf, } if (mdc800->endpoint[i] == -1) { - err ("probe fails -> Wrong Endpoints."); + dev_err(&intf->dev, "probe fails -> Wrong Endpoints.\n"); return -ENODEV; } } - info ("Found Mustek MDC800 on USB."); + dev_info(&intf->dev, "Found Mustek MDC800 on USB.\n"); mutex_lock(&mdc800->io_lock); retval = usb_register_dev(intf, &mdc800_class); if (retval) { - err ("Not able to get a minor for this device."); + dev_err(&intf->dev, "Not able to get a minor for this device.\n"); return -ENODEV; } @@ -570,7 +574,7 @@ static void mdc800_usb_disconnect (struct usb_interface *intf) mdc800->dev = NULL; usb_set_intfdata(intf, NULL); } - info ("Mustek MDC800 disconnected from USB."); + dev_info(&intf->dev, "Mustek MDC800 disconnected from USB.\n"); } @@ -644,7 +648,8 @@ static int mdc800_device_open (struct inode* inode, struct file *file) mdc800->irq_urb->dev = mdc800->dev; retval = usb_submit_urb (mdc800->irq_urb, GFP_KERNEL); if (retval) { - err ("request USB irq fails (submit_retval=%i).", retval); + dev_err(&mdc800->dev->dev, + "request USB irq fails (submit_retval=%i).\n", retval); errn = -EIO; goto error_out; } @@ -701,7 +706,8 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l } if (mdc800->state == WORKING) { - warn ("Illegal State \"working\" reached during read ?!"); + printk(KERN_WARNING "mdc800: Illegal State \"working\"" + "reached during read ?!\n"); mutex_unlock(&mdc800->io_lock); return -EBUSY; } @@ -733,7 +739,9 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l mdc800->download_urb->dev = mdc800->dev; retval = usb_submit_urb (mdc800->download_urb, GFP_KERNEL); if (retval) { - err ("Can't submit download urb (retval=%i)",retval); + dev_err(&mdc800->dev->dev, + "Can't submit download urb " + "(retval=%i)\n", retval); mutex_unlock(&mdc800->io_lock); return len-left; } @@ -742,7 +750,10 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l mdc800->downloaded = 0; if (mdc800->download_urb->status != 0) { - err ("request download-bytes fails (status=%i)",mdc800->download_urb->status); + dev_err(&mdc800->dev->dev, + "request download-bytes fails " + "(status=%i)\n", + mdc800->download_urb->status); mutex_unlock(&mdc800->io_lock); return len-left; } @@ -839,7 +850,8 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (mdc800_usb_waitForIRQ (0,TO_GET_READY)) { - err ("Camera didn't get ready.\n"); + dev_err(&mdc800->dev->dev, + "Camera didn't get ready.\n"); mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -851,7 +863,9 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s mdc800->write_urb->dev = mdc800->dev; retval = usb_submit_urb (mdc800->write_urb, GFP_KERNEL); if (retval) { - err ("submitting write urb fails (retval=%i)", retval); + dev_err(&mdc800->dev->dev, + "submitting write urb fails " + "(retval=%i)\n", retval); mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -870,7 +884,9 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s case 0x3e: /* Take shot in Fine Mode (WCam Mode) */ if (mdc800->pic_len < 0) { - err ("call 0x07 before 0x05,0x3e"); + dev_err(&mdc800->dev->dev, + "call 0x07 before " + "0x05,0x3e\n"); mdc800->state=READY; mutex_unlock(&mdc800->io_lock); return -EIO; @@ -890,7 +906,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ)) { - err ("requesting answer from irq fails"); + dev_err(&mdc800->dev->dev, "requesting answer from irq fails\n"); mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -918,7 +934,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s { if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND)) { - err ("Command Timeout."); + dev_err(&mdc800->dev->dev, "Command Timeout.\n"); mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -1018,7 +1034,8 @@ static int __init usb_mdc800_init (void) if (retval) goto cleanup_on_fail; - info (DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; @@ -1028,7 +1045,7 @@ cleanup_on_fail: if (mdc800 != NULL) { - err ("can't alloc memory!"); + printk(KERN_ERR "mdc800: can't alloc memory!\n"); kfree(mdc800->download_urb_buffer); kfree(mdc800->write_urb_buffer); diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 4ea50e0abcbb..e463db5d8188 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -42,6 +42,15 @@ config USB_ADUTUX To compile this driver as a module, choose M here. The module will be called adutux. +config USB_SEVSEG + tristate "USB 7-Segment LED Display" + depends on USB + help + Say Y here if you have a USB 7-Segment Display by Delcom + + To compile this driver as a module, choose M here: the + module will be called usbsevseg. + config USB_RIO500 tristate "USB Diamond Rio500 support" depends on USB @@ -271,3 +280,18 @@ config USB_ISIGHTFW The firmware for this driver must be extracted from the MacOS driver beforehand. Tools for doing so are available at http://bersace03.free.fr + +config USB_VST + tristate "USB VST driver" + depends on USB + help + This driver is intended for Vernier Software Technologies + bulk usb devices such as their Ocean-Optics spectrometers or + Labquest. + It is a bulk channel driver with configurable read and write + timeouts. + + To compile this driver as a module, choose M here: the + module will be called vstusb. + + diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 45b4e12afb08..1334f7bdd7be 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -26,6 +26,8 @@ obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o +obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o +obj-$(CONFIG_USB_VST) += vstusb.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 965f6eaea6a0..7b6922e08ed1 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -283,8 +283,8 @@ static int adu_open(struct inode *inode, struct file *file) interface = usb_find_interface(&adu_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d", - __func__, subminor); + printk(KERN_ERR "adutux: %s - error, can't find device for " + "minor %d\n", __func__, subminor); retval = -ENODEV; goto exit_no_device; } @@ -416,7 +416,8 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - err("No device or device unplugged %d", retval); + printk(KERN_ERR "adutux: No device or device unplugged %d\n", + retval); goto exit; } @@ -576,7 +577,8 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - err("No device or device unplugged %d", retval); + printk(KERN_ERR "adutux: No device or device unplugged %d\n", + retval); goto exit; } @@ -645,7 +647,8 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval < 0) { dev->out_urb_finished = 1; - err("Couldn't submit interrupt_out_urb %d", retval); + dev_err(&dev->udev->dev, "Couldn't submit " + "interrupt_out_urb %d\n", retval); goto exit; } @@ -890,13 +893,14 @@ static int __init adu_init(void) /* register this driver with the USB subsystem */ result = usb_register(&adu_driver); if (result < 0) { - err("usb_register failed for the "__FILE__" driver. " - "Error number %d", result); + printk(KERN_ERR "usb_register failed for the "__FILE__ + " driver. Error number %d\n", result); goto exit; } - info("adutux " DRIVER_DESC " " DRIVER_VERSION); - info("adutux is an experimental driver. Use at your own risk"); + printk(KERN_INFO "adutux " DRIVER_DESC " " DRIVER_VERSION "\n"); + printk(KERN_INFO "adutux is an experimental driver. " + "Use at your own risk\n"); exit: dbg(2," %s : leave, return value %d", __func__, result); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index a076c24a312a..1d8e39a557d9 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -130,7 +130,8 @@ static void appledisplay_complete(struct urb *urb) exit: retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); if (retval) { - err("%s - usb_submit_urb failed with result %d", + dev_err(&pdata->udev->dev, + "%s - usb_submit_urb failed with result %d\n", __func__, retval); } } @@ -220,7 +221,7 @@ static int appledisplay_probe(struct usb_interface *iface, } } if (!int_in_endpointAddr) { - err("Could not find int-in endpoint"); + dev_err(&iface->dev, "Could not find int-in endpoint\n"); return -EIO; } @@ -228,7 +229,7 @@ static int appledisplay_probe(struct usb_interface *iface, pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); if (!pdata) { retval = -ENOMEM; - err("Out of memory"); + dev_err(&iface->dev, "Out of memory\n"); goto error; } @@ -241,8 +242,8 @@ static int appledisplay_probe(struct usb_interface *iface, pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); if (!pdata->msgdata) { retval = -ENOMEM; - err("appledisplay: Allocating buffer for control messages " - "failed"); + dev_err(&iface->dev, + "Allocating buffer for control messages failed\n"); goto error; } @@ -250,7 +251,7 @@ static int appledisplay_probe(struct usb_interface *iface, pdata->urb = usb_alloc_urb(0, GFP_KERNEL); if (!pdata->urb) { retval = -ENOMEM; - err("appledisplay: Allocating URB failed"); + dev_err(&iface->dev, "Allocating URB failed\n"); goto error; } @@ -259,7 +260,7 @@ static int appledisplay_probe(struct usb_interface *iface, GFP_KERNEL, &pdata->urb->transfer_dma); if (!pdata->urbdata) { retval = -ENOMEM; - err("appledisplay: Allocating URB buffer failed"); + dev_err(&iface->dev, "Allocating URB buffer failed\n"); goto error; } @@ -270,7 +271,7 @@ static int appledisplay_probe(struct usb_interface *iface, pdata, 1); if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { retval = -EIO; - err("appledisplay: Submitting URB failed"); + dev_err(&iface->dev, "Submitting URB failed\n"); goto error; } @@ -280,7 +281,7 @@ static int appledisplay_probe(struct usb_interface *iface, pdata->bd = backlight_device_register(bl_name, NULL, pdata, &appledisplay_bl_data); if (IS_ERR(pdata->bd)) { - err("appledisplay: Backlight registration failed"); + dev_err(&iface->dev, "Backlight registration failed\n"); goto error; } @@ -291,7 +292,8 @@ static int appledisplay_probe(struct usb_interface *iface, if (brightness < 0) { retval = brightness; - err("appledisplay: Error while getting initial brightness: %d", retval); + dev_err(&iface->dev, + "Error while getting initial brightness: %d\n", retval); goto error; } @@ -314,7 +316,7 @@ error: pdata->urbdata, pdata->urb->transfer_dma); usb_free_urb(pdata->urb); } - if (pdata->bd) + if (pdata->bd && !IS_ERR(pdata->bd)) backlight_device_unregister(pdata->bd); kfree(pdata->msgdata); } @@ -352,7 +354,7 @@ static int __init appledisplay_init(void) { wq = create_singlethread_workqueue("appledisplay"); if (!wq) { - err("Could not create work queue\n"); + printk(KERN_ERR "appledisplay: Could not create work queue\n"); return -ENOMEM; } diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index 937940404b7a..5720bfef6a38 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -278,9 +278,9 @@ static int __init cypress_init(void) /* register this driver with the USB subsystem */ result = usb_register(&cypress_driver); - if (result) { - err("Function usb_register failed! Error number: %d\n", result); - } + if (result) + printk(KERN_ERR KBUILD_MODNAME ": usb_register failed! " + "Error number: %d\n", result); return result; } diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index 1cd9e7eba93b..4fb3c38b924b 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c @@ -422,13 +422,14 @@ static int __init usb_cytherm_init(void) int result; result = usb_register(&cytherm_driver); - if (result) - { - err("usb_register failed. Error number %d", result); + if (result) { + printk(KERN_ERR KBUILD_MODNAME ": usb_register failed! " + "Error number: %d\n", result); return result; } - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; } diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 4b994a0cd272..e762beb5f3c6 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -50,7 +50,7 @@ static int emi26_writememory (struct usb_device *dev, int address, unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); if (!buffer) { - err("emi26: kmalloc(%d) failed.", length); + dev_err(&dev->dev, "kmalloc(%d) failed.\n", length); return -ENOMEM; } /* Note: usb_control_msg returns negative value on error or length of the @@ -64,11 +64,11 @@ static int emi26_writememory (struct usb_device *dev, int address, static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit) { int response; - info("%s - %d", __func__, reset_bit); + dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit); /* printk(KERN_DEBUG "%s - %d", __func__, reset_bit); */ response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0); if (response < 0) { - err("emi26: set_reset (%d) failed", reset_bit); + dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit); } return response; } @@ -88,7 +88,8 @@ static int emi26_load_firmware (struct usb_device *dev) buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); if (!buf) { - err( "%s - error loading firmware: error = %d", __func__, -ENOMEM); + dev_err(&dev->dev, "%s - error loading firmware: error = %d\n", + __func__, -ENOMEM); err = -ENOMEM; goto wraperr; } @@ -106,14 +107,16 @@ static int emi26_load_firmware (struct usb_device *dev) &dev->dev); if (err) { nofw: - err( "%s - request_firmware() failed", __func__); + dev_err(&dev->dev, "%s - request_firmware() failed\n", + __func__); goto wraperr; } /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); if (err < 0) { - err( "%s - error loading firmware: error = %d", __func__, err); + dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", + __func__, err); goto wraperr; } @@ -254,7 +257,7 @@ static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *i { struct usb_device *dev = interface_to_usbdev(intf); - info("%s start", __func__); + dev_info(&intf->dev, "%s start\n", __func__); emi26_load_firmware(dev); diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 5d859ded5bbf..602ee05ba9ff 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -73,7 +73,7 @@ static int emi62_writememory(struct usb_device *dev, int address, static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit) { int response; - info("%s - %d", __func__, reset_bit); + dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit); response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0); if (response < 0) { @@ -271,7 +271,7 @@ static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_device *dev = interface_to_usbdev(intf); dev_dbg(&intf->dev, "emi62_probe\n"); - info("%s start", __func__); + dev_info(&intf->dev, "%s start\n", __func__); emi62_load_firmware(dev); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 97c280971532..79a7668ef264 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -698,7 +698,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer, int retval = usb_bulk_msg(ftdi->udev, usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, msecs_to_jiffies(50)); + &packet_bytes, 50); if (packet_bytes > 2) { ftdi->bulk_in_left = packet_bytes - 2; ftdi->bulk_in_last = 1; @@ -960,7 +960,7 @@ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi) int retval = usb_bulk_msg(ftdi->udev, usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, msecs_to_jiffies(500)); + &packet_bytes, 500); char diag[30 *3 + 4]; char *d = diag; int m = packet_bytes; @@ -1880,7 +1880,7 @@ static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi) int retval = usb_bulk_msg(ftdi->udev, usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, msecs_to_jiffies(100)); + &packet_bytes, 100); if (packet_bytes > 2) { char diag[30 *3 + 4]; char *d = diag; @@ -2067,7 +2067,7 @@ static int ftdi_elan_synchronize(struct usb_ftdi *ftdi) usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, msecs_to_jiffies(500)); + &packet_bytes, 500); if (packet_bytes > 2) { char diag[30 *3 + 4]; char *d = diag; @@ -2176,7 +2176,7 @@ static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi) int retval = usb_bulk_msg(ftdi->udev, usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, msecs_to_jiffies(1000)); + &packet_bytes, 1000); if (packet_bytes > 2) { char diag[30 *3 + 4]; char *d = diag; diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 4bcf7fb4e5da..6da8887538c7 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -403,14 +403,15 @@ static void idmouse_disconnect(struct usb_interface *interface) mutex_unlock(&dev->lock); } - info("%s disconnected", DRIVER_DESC); + dev_info(&interface->dev, "disconnected\n"); } static int __init usb_idmouse_init(void) { int result; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); /* register this driver with the USB subsystem */ result = usb_register(&idmouse_driver); diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 9370326a5940..ab0f3226158b 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -851,9 +851,8 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device dbg(2, "%s: enter", __func__); - if (udev == NULL) { - info ("udev is NULL."); - } + if (udev == NULL) + dev_info(&interface->dev, "udev is NULL.\n"); /* allocate memory for our device state and initialize it */ @@ -954,7 +953,9 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device dev->minor = interface->minor; /* let the user know what node this device is now attached to */ - info ("LEGO USB Tower #%d now attached to major %d minor %d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), USB_MAJOR, dev->minor); + dev_info(&interface->dev, "LEGO USB Tower #%d now attached to major " + "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), + USB_MAJOR, dev->minor); /* get the firmware version and log it */ result = usb_control_msg (udev, @@ -971,10 +972,10 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device retval = result; goto error; } - info("LEGO USB Tower firmware version is %d.%d build %d", - get_version_reply.major, - get_version_reply.minor, - le16_to_cpu(get_version_reply.build_no)); + dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d " + "build %d\n", get_version_reply.major, + get_version_reply.minor, + le16_to_cpu(get_version_reply.build_no)); exit: @@ -1021,7 +1022,8 @@ static void tower_disconnect (struct usb_interface *interface) mutex_unlock(&dev->lock); } - info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); + dev_info(&interface->dev, "LEGO USB Tower #%d now disconnected\n", + (minor - LEGO_USB_TOWER_MINOR_BASE)); dbg(2, "%s: leave", __func__); } @@ -1046,7 +1048,8 @@ static int __init lego_usb_tower_init(void) goto exit; } - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); exit: dbg(2, "%s: leave, return value %d", __func__, retval); diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 4cfa25b0f44e..cc8e0a926f99 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -595,9 +595,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic } while(value); kit->dev_no = bit; - kit->dev = device_create_drvdata(phidget_class, &kit->udev->dev, - MKDEV(0, 0), kit, - "interfacekit%d", kit->dev_no); + kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0), + kit, "interfacekit%d", kit->dev_no); if (IS_ERR(kit->dev)) { rc = PTR_ERR(kit->dev); kit->dev = NULL; diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 9b4696f21b22..38088b44349e 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -365,9 +365,8 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic } while(value); mc->dev_no = bit; - mc->dev = device_create_drvdata(phidget_class, &mc->udev->dev, - MKDEV(0, 0), mc, - "motorcontrol%d", mc->dev_no); + mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc, + "motorcontrol%d", mc->dev_no); if (IS_ERR(mc->dev)) { rc = PTR_ERR(mc->dev); mc->dev = NULL; diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index 1ca7ddb41d4d..bef6fe16364b 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c @@ -275,9 +275,8 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id) } while (value); dev->dev_no = bit; - dev->dev = device_create_drvdata(phidget_class, &dev->udev->dev, - MKDEV(0, 0), dev, - "servo%d", dev->dev_no); + dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0), + dev, "servo%d", dev->dev_no); if (IS_ERR(dev->dev)) { rc = PTR_ERR(dev->dev); dev->dev = NULL; diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 248a12aacef6..deb95bb49fd1 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -89,7 +89,7 @@ static int open_rio(struct inode *inode, struct file *file) mutex_unlock(&(rio->lock)); - info("Rio opened."); + dev_info(&rio->rio_dev->dev, "Rio opened.\n"); return 0; } @@ -100,7 +100,7 @@ static int close_rio(struct inode *inode, struct file *file) rio->isopen = 0; - info("Rio closed."); + dev_info(&rio->rio_dev->dev, "Rio closed.\n"); return 0; } @@ -451,7 +451,7 @@ static int probe_rio(struct usb_interface *intf, struct rio_usb_data *rio = &rio_instance; int retval; - info("USB Rio found at address %d", dev->devnum); + dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); retval = usb_register_dev(intf, &usb_rio_class); if (retval) { @@ -503,7 +503,7 @@ static void disconnect_rio(struct usb_interface *intf) kfree(rio->ibuf); kfree(rio->obuf); - info("USB Rio disconnected."); + dev_info(&intf->dev, "USB Rio disconnected.\n"); rio->present = 0; mutex_unlock(&(rio->lock)); @@ -531,7 +531,8 @@ static int __init usb_rio_init(void) if (retval) goto out; - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); out: return retval; diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c index 03368edf3f22..2e14102955c5 100644 --- a/drivers/usb/misc/trancevibrator.c +++ b/drivers/usb/misc/trancevibrator.c @@ -144,7 +144,8 @@ static int __init tv_init(void) return retval; } - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; } diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 2db4228fbb01..e0ff9ccd866b 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -311,7 +311,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id dev->interface = interface; if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) { - warn(KERN_INFO "USBLCD model not supported."); + dev_warn(&interface->dev, "USBLCD model not supported.\n"); return -ENODEV; } @@ -359,12 +359,13 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id i = le16_to_cpu(dev->udev->descriptor.bcdDevice); - info("USBLCD Version %1d%1d.%1d%1d found at address %d", - (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF), - dev->udev->devnum); + dev_info(&interface->dev, "USBLCD Version %1d%1d.%1d%1d found " + "at address %d\n", (i & 0xF000)>>12, (i & 0xF00)>>8, + (i & 0xF0)>>4,(i & 0xF), dev->udev->devnum); /* let the user know what node this device is now attached to */ - info("USB LCD device now attached to USBLCD-%d", interface->minor); + dev_info(&interface->dev, "USB LCD device now attached to USBLCD-%d\n", + interface->minor); return 0; error: @@ -413,7 +414,7 @@ static void lcd_disconnect(struct usb_interface *interface) /* decrement our usage count */ kref_put(&dev->kref, lcd_delete); - info("USB LCD #%d now disconnected", minor); + dev_info(&interface->dev, "USB LCD #%d now disconnected\n", minor); } static struct usb_driver lcd_driver = { diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c new file mode 100644 index 000000000000..28a6a3a09538 --- /dev/null +++ b/drivers/usb/misc/usbsevseg.c @@ -0,0 +1,394 @@ +/* + * USB 7 Segment Driver + * + * Copyright (C) 2008 Harrison Metzger <harrisonmetz@gmail.com> + * Based on usbled.c by Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/usb.h> + + +#define DRIVER_AUTHOR "Harrison Metzger <harrisonmetz@gmail.com>" +#define DRIVER_DESC "USB 7 Segment Driver" + +#define VENDOR_ID 0x0fc5 +#define PRODUCT_ID 0x1227 +#define MAXLEN 6 + +/* table of devices that work with this driver */ +static struct usb_device_id id_table[] = { + { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* the different text display modes the device is capable of */ +static char *display_textmodes[] = {"raw", "hex", "ascii", NULL}; + +struct usb_sevsegdev { + struct usb_device *udev; + + u8 powered; + u8 mode_msb; + u8 mode_lsb; + u8 decimals[MAXLEN]; + u8 textmode; + u8 text[MAXLEN]; + u16 textlength; +}; + +/* sysfs_streq can't replace this completely + * If the device was in hex mode, and the user wanted a 0, + * if str commands are used, we would assume the end of string + * so mem commands are used. + */ +inline size_t my_memlen(const char *buf, size_t count) +{ + if (count > 0 && buf[count-1] == '\n') + return count - 1; + else + return count; +} + +static void update_display_powered(struct usb_sevsegdev *mydev) +{ + int rc; + + rc = usb_control_msg(mydev->udev, + usb_sndctrlpipe(mydev->udev, 0), + 0x12, + 0x48, + (80 * 0x100) + 10, /* (power mode) */ + (0x00 * 0x100) + (mydev->powered ? 1 : 0), + NULL, + 0, + 2000); + if (rc < 0) + dev_dbg(&mydev->udev->dev, "power retval = %d\n", rc); +} + +static void update_display_mode(struct usb_sevsegdev *mydev) +{ + int rc; + + rc = usb_control_msg(mydev->udev, + usb_sndctrlpipe(mydev->udev, 0), + 0x12, + 0x48, + (82 * 0x100) + 10, /* (set mode) */ + (mydev->mode_msb * 0x100) + mydev->mode_lsb, + NULL, + 0, + 2000); + + if (rc < 0) + dev_dbg(&mydev->udev->dev, "mode retval = %d\n", rc); +} + +static void update_display_visual(struct usb_sevsegdev *mydev) +{ + int rc; + int i; + unsigned char *buffer; + u8 decimals = 0; + + buffer = kzalloc(MAXLEN, GFP_KERNEL); + if (!buffer) { + dev_err(&mydev->udev->dev, "out of memory\n"); + return; + } + + /* The device is right to left, where as you write left to right */ + for (i = 0; i < mydev->textlength; i++) + buffer[i] = mydev->text[mydev->textlength-1-i]; + + rc = usb_control_msg(mydev->udev, + usb_sndctrlpipe(mydev->udev, 0), + 0x12, + 0x48, + (85 * 0x100) + 10, /* (write text) */ + (0 * 0x100) + mydev->textmode, /* mode */ + buffer, + mydev->textlength, + 2000); + + if (rc < 0) + dev_dbg(&mydev->udev->dev, "write retval = %d\n", rc); + + kfree(buffer); + + /* The device is right to left, where as you write left to right */ + for (i = 0; i < sizeof(mydev->decimals); i++) + decimals |= mydev->decimals[i] << i; + + rc = usb_control_msg(mydev->udev, + usb_sndctrlpipe(mydev->udev, 0), + 0x12, + 0x48, + (86 * 0x100) + 10, /* (set decimal) */ + (0 * 0x100) + decimals, /* decimals */ + NULL, + 0, + 2000); + + if (rc < 0) + dev_dbg(&mydev->udev->dev, "decimal retval = %d\n", rc); +} + +#define MYDEV_ATTR_SIMPLE_UNSIGNED(name, update_fcn) \ +static ssize_t show_attr_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); \ + \ + return sprintf(buf, "%u\n", mydev->name); \ +} \ + \ +static ssize_t set_attr_##name(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); \ + \ + mydev->name = simple_strtoul(buf, NULL, 10); \ + update_fcn(mydev); \ + \ + return count; \ +} \ +static DEVICE_ATTR(name, S_IWUGO | S_IRUGO, show_attr_##name, set_attr_##name); + +static ssize_t show_attr_text(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); + + return snprintf(buf, mydev->textlength, "%s\n", mydev->text); +} + +static ssize_t set_attr_text(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); + size_t end = my_memlen(buf, count); + + if (end > sizeof(mydev->text)) + return -EINVAL; + + memset(mydev->text, 0, sizeof(mydev->text)); + mydev->textlength = end; + + if (end > 0) + memcpy(mydev->text, buf, end); + + update_display_visual(mydev); + return count; +} + +static DEVICE_ATTR(text, S_IWUGO | S_IRUGO, show_attr_text, set_attr_text); + +static ssize_t show_attr_decimals(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); + int i; + int pos; + + for (i = 0; i < sizeof(mydev->decimals); i++) { + pos = sizeof(mydev->decimals) - 1 - i; + if (mydev->decimals[i] == 0) + buf[pos] = '0'; + else if (mydev->decimals[i] == 1) + buf[pos] = '1'; + else + buf[pos] = 'x'; + } + + buf[sizeof(mydev->decimals)] = '\n'; + return sizeof(mydev->decimals) + 1; +} + +static ssize_t set_attr_decimals(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); + size_t end = my_memlen(buf, count); + int i; + + if (end > sizeof(mydev->decimals)) + return -EINVAL; + + for (i = 0; i < end; i++) + if (buf[i] != '0' && buf[i] != '1') + return -EINVAL; + + memset(mydev->decimals, 0, sizeof(mydev->decimals)); + for (i = 0; i < end; i++) + if (buf[i] == '1') + mydev->decimals[end-1-i] = 1; + + update_display_visual(mydev); + + return count; +} + +static DEVICE_ATTR(decimals, S_IWUGO | S_IRUGO, + show_attr_decimals, set_attr_decimals); + +static ssize_t show_attr_textmode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); + int i; + + buf[0] = 0; + + for (i = 0; display_textmodes[i]; i++) { + if (mydev->textmode == i) { + strcat(buf, " ["); + strcat(buf, display_textmodes[i]); + strcat(buf, "] "); + } else { + strcat(buf, " "); + strcat(buf, display_textmodes[i]); + strcat(buf, " "); + } + } + strcat(buf, "\n"); + + + return strlen(buf); +} + +static ssize_t set_attr_textmode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_sevsegdev *mydev = usb_get_intfdata(intf); + int i; + + for (i = 0; display_textmodes[i]; i++) { + if (sysfs_streq(display_textmodes[i], buf)) { + mydev->textmode = i; + update_display_visual(mydev); + return count; + } + } + + return -EINVAL; +} + +static DEVICE_ATTR(textmode, S_IWUGO | S_IRUGO, + show_attr_textmode, set_attr_textmode); + + +MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered); +MYDEV_ATTR_SIMPLE_UNSIGNED(mode_msb, update_display_mode); +MYDEV_ATTR_SIMPLE_UNSIGNED(mode_lsb, update_display_mode); + +static struct attribute *dev_attrs[] = { + &dev_attr_powered.attr, + &dev_attr_text.attr, + &dev_attr_textmode.attr, + &dev_attr_decimals.attr, + &dev_attr_mode_msb.attr, + &dev_attr_mode_lsb.attr, + NULL +}; + +static struct attribute_group dev_attr_grp = { + .attrs = dev_attrs, +}; + +static int sevseg_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_sevsegdev *mydev = NULL; + int rc = -ENOMEM; + + mydev = kzalloc(sizeof(struct usb_sevsegdev), GFP_KERNEL); + if (mydev == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + goto error_mem; + } + + mydev->udev = usb_get_dev(udev); + usb_set_intfdata(interface, mydev); + + /*set defaults */ + mydev->textmode = 0x02; /* ascii mode */ + mydev->mode_msb = 0x06; /* 6 characters */ + mydev->mode_lsb = 0x3f; /* scanmode for 6 chars */ + + rc = sysfs_create_group(&interface->dev.kobj, &dev_attr_grp); + if (rc) + goto error; + + dev_info(&interface->dev, "USB 7 Segment device now attached\n"); + return 0; + +error: + usb_set_intfdata(interface, NULL); + usb_put_dev(mydev->udev); + kfree(mydev); +error_mem: + return rc; +} + +static void sevseg_disconnect(struct usb_interface *interface) +{ + struct usb_sevsegdev *mydev; + + mydev = usb_get_intfdata(interface); + sysfs_remove_group(&interface->dev.kobj, &dev_attr_grp); + usb_set_intfdata(interface, NULL); + usb_put_dev(mydev->udev); + kfree(mydev); + dev_info(&interface->dev, "USB 7 Segment now disconnected\n"); +} + +static struct usb_driver sevseg_driver = { + .name = "usbsevseg", + .probe = sevseg_probe, + .disconnect = sevseg_disconnect, + .id_table = id_table, +}; + +static int __init usb_sevseg_init(void) +{ + int rc = 0; + + rc = usb_register(&sevseg_driver); + if (rc) + err("usb_register failed. Error number %d", rc); + return rc; +} + +static void __exit usb_sevseg_exit(void) +{ + usb_deregister(&sevseg_driver); +} + +module_init(usb_sevseg_init); +module_exit(usb_sevseg_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index f1255b0a182d..9a6c27a01793 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -228,11 +228,12 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha ret = rq->urb->status; *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]]; if (ret) - warn("get_1284_register: usb error %d", ret); + printk(KERN_WARNING "get_1284_register: " + "usb error %d\n", ret); kref_put(&rq->ref_count, destroy_async); return ret; } - warn("get_1284_register timeout"); + printk(KERN_WARNING "get_1284_register timeout\n"); kill_all_async_requests_priv(priv); return -EIO; } @@ -716,7 +717,7 @@ static int uss720_probe(struct usb_interface *intf, spin_lock_init(&priv->asynclock); INIT_LIST_HEAD(&priv->asynclist); if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) { - warn("could not register parport"); + printk(KERN_WARNING "uss720: could not register parport\n"); goto probe_abort; } @@ -800,10 +801,14 @@ static int __init uss720_init(void) if (retval) goto out; - info(DRIVER_VERSION ":" DRIVER_DESC); - info("NOTE: this is a special purpose driver to allow nonstandard"); - info("protocols (eg. bitbang) over USS720 usb to parallel cables"); - info("If you just want to connect to a printer, use usblp instead"); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + printk(KERN_INFO KBUILD_MODNAME ": NOTE: this is a special purpose " + "driver to allow nonstandard\n"); + printk(KERN_INFO KBUILD_MODNAME ": protocols (eg. bitbang) over " + "USS720 usb to parallel cables\n"); + printk(KERN_INFO KBUILD_MODNAME ": If you just want to connect to a " + "printer, use usblp instead\n"); out: return retval; } diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c new file mode 100644 index 000000000000..8648470c81ca --- /dev/null +++ b/drivers/usb/misc/vstusb.c @@ -0,0 +1,782 @@ +/***************************************************************************** + * File: drivers/usb/misc/vstusb.c + * + * Purpose: Support for the bulk USB Vernier Spectrophotometers + * + * Author: Johnnie Peters + * Axian Consulting + * Beaverton, OR, USA 97005 + * + * Modified by: EQware Engineering, Inc. + * Oregon City, OR, USA 97045 + * + * Copyright: 2007, 2008 + * Vernier Software & Technology + * Beaverton, OR, USA 97005 + * + * Web: www.vernier.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + *****************************************************************************/ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/uaccess.h> +#include <linux/usb.h> + +#include <linux/usb/vstusb.h> + +#define DRIVER_VERSION "VST USB Driver Version 1.5" +#define DRIVER_DESC "Vernier Software Technology Bulk USB Driver" + +#ifdef CONFIG_USB_DYNAMIC_MINORS + #define VSTUSB_MINOR_BASE 0 +#else + #define VSTUSB_MINOR_BASE 199 +#endif + +#define USB_VENDOR_OCEANOPTICS 0x2457 +#define USB_VENDOR_VERNIER 0x08F7 /* Vernier Software & Technology */ + +#define USB_PRODUCT_USB2000 0x1002 +#define USB_PRODUCT_ADC1000_FW 0x1003 /* firmware download (renumerates) */ +#define USB_PRODUCT_ADC1000 0x1004 +#define USB_PRODUCT_HR2000_FW 0x1009 /* firmware download (renumerates) */ +#define USB_PRODUCT_HR2000 0x100A +#define USB_PRODUCT_HR4000_FW 0x1011 /* firmware download (renumerates) */ +#define USB_PRODUCT_HR4000 0x1012 +#define USB_PRODUCT_USB650 0x1014 /* "Red Tide" */ +#define USB_PRODUCT_QE65000 0x1018 +#define USB_PRODUCT_USB4000 0x1022 +#define USB_PRODUCT_USB325 0x1024 /* "Vernier Spectrometer" */ + +#define USB_PRODUCT_LABPRO 0x0001 +#define USB_PRODUCT_LABQUEST 0x0005 + +#define VST_MAXBUFFER (64*1024) + +static struct usb_device_id id_table[] = { + { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)}, + { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)}, + { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB650)}, + { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB4000)}, + { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB325)}, + { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABQUEST)}, + { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABPRO)}, + {}, +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +struct vstusb_device { + struct kref kref; + struct mutex lock; + struct usb_device *usb_dev; + char present; + char isopen; + struct usb_anchor submitted; + int rd_pipe; + int rd_timeout_ms; + int wr_pipe; + int wr_timeout_ms; +}; +#define to_vst_dev(d) container_of(d, struct vstusb_device, kref) + +static struct usb_driver vstusb_driver; + +static void vstusb_delete(struct kref *kref) +{ + struct vstusb_device *vstdev = to_vst_dev(kref); + + usb_put_dev(vstdev->usb_dev); + kfree(vstdev); +} + +static int vstusb_open(struct inode *inode, struct file *file) +{ + struct vstusb_device *vstdev; + struct usb_interface *interface; + + interface = usb_find_interface(&vstusb_driver, iminor(inode)); + + if (!interface) { + printk(KERN_ERR KBUILD_MODNAME + ": %s - error, can't find device for minor %d\n", + __func__, iminor(inode)); + return -ENODEV; + } + + vstdev = usb_get_intfdata(interface); + + if (!vstdev) + return -ENODEV; + + /* lock this device */ + mutex_lock(&vstdev->lock); + + /* can only open one time */ + if ((!vstdev->present) || (vstdev->isopen)) { + mutex_unlock(&vstdev->lock); + return -EBUSY; + } + + /* increment our usage count */ + kref_get(&vstdev->kref); + + vstdev->isopen = 1; + + /* save device in the file's private structure */ + file->private_data = vstdev; + + dev_dbg(&vstdev->usb_dev->dev, "%s: opened\n", __func__); + + mutex_unlock(&vstdev->lock); + + return 0; +} + +static int vstusb_release(struct inode *inode, struct file *file) +{ + struct vstusb_device *vstdev; + + vstdev = file->private_data; + + if (vstdev == NULL) + return -ENODEV; + + mutex_lock(&vstdev->lock); + + vstdev->isopen = 0; + + dev_dbg(&vstdev->usb_dev->dev, "%s: released\n", __func__); + + mutex_unlock(&vstdev->lock); + + kref_put(&vstdev->kref, vstusb_delete); + + return 0; +} + +static void usb_api_blocking_completion(struct urb *urb) +{ + struct completion *completeit = urb->context; + + complete(completeit); +} + +static int vstusb_fill_and_send_urb(struct urb *urb, + struct usb_device *usb_dev, + unsigned int pipe, void *data, + unsigned int len, struct completion *done) +{ + struct usb_host_endpoint *ep; + struct usb_host_endpoint **hostep; + unsigned int pipend; + + int status; + + hostep = usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out; + pipend = usb_pipeendpoint(pipe); + ep = hostep[pipend]; + + if (!ep || (len == 0)) + return -EINVAL; + + if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT) { + pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); + usb_fill_int_urb(urb, usb_dev, pipe, data, len, + (usb_complete_t)usb_api_blocking_completion, + NULL, ep->desc.bInterval); + } else + usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, + (usb_complete_t)usb_api_blocking_completion, + NULL); + + init_completion(done); + urb->context = done; + urb->actual_length = 0; + status = usb_submit_urb(urb, GFP_KERNEL); + + return status; +} + +static int vstusb_complete_urb(struct urb *urb, struct completion *done, + int timeout, int *actual_length) +{ + unsigned long expire; + int status; + + expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; + if (!wait_for_completion_interruptible_timeout(done, expire)) { + usb_kill_urb(urb); + status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status; + + dev_dbg(&urb->dev->dev, + "%s timed out on ep%d%s len=%d/%d, urb status = %d\n", + current->comm, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->actual_length, + urb->transfer_buffer_length, + urb->status); + + } else { + if (signal_pending(current)) { + /* if really an error */ + if (urb->status && !((urb->status == -ENOENT) || + (urb->status == -ECONNRESET) || + (urb->status == -ESHUTDOWN))) { + status = -EINTR; + usb_kill_urb(urb); + } else { + status = 0; + } + + dev_dbg(&urb->dev->dev, + "%s: signal pending on ep%d%s len=%d/%d," + "urb status = %d\n", + current->comm, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->actual_length, + urb->transfer_buffer_length, + urb->status); + + } else { + status = urb->status; + } + } + + if (actual_length) + *actual_length = urb->actual_length; + + return status; +} + +static ssize_t vstusb_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct vstusb_device *vstdev; + int cnt = -1; + void *buf; + int retval = 0; + + struct urb *urb; + struct usb_device *dev; + unsigned int pipe; + int timeout; + + DECLARE_COMPLETION_ONSTACK(done); + + vstdev = file->private_data; + + if (vstdev == NULL) + return -ENODEV; + + /* verify that we actually want to read some data */ + if ((count == 0) || (count > VST_MAXBUFFER)) + return -EINVAL; + + /* lock this object */ + if (mutex_lock_interruptible(&vstdev->lock)) + return -ERESTARTSYS; + + /* anyone home */ + if (!vstdev->present) { + mutex_unlock(&vstdev->lock); + printk(KERN_ERR KBUILD_MODNAME + ": %s: device not present\n", __func__); + return -ENODEV; + } + + /* pull out the necessary data */ + dev = vstdev->usb_dev; + pipe = usb_rcvbulkpipe(dev, vstdev->rd_pipe); + timeout = vstdev->rd_timeout_ms; + + buf = kmalloc(count, GFP_KERNEL); + if (buf == NULL) { + mutex_unlock(&vstdev->lock); + return -ENOMEM; + } + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + kfree(buf); + mutex_unlock(&vstdev->lock); + return -ENOMEM; + } + + usb_anchor_urb(urb, &vstdev->submitted); + retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done); + mutex_unlock(&vstdev->lock); + if (retval) { + usb_unanchor_urb(urb); + dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n", + __func__, retval, pipe); + goto exit; + } + + retval = vstusb_complete_urb(urb, &done, timeout, &cnt); + if (retval) { + dev_err(&dev->dev, "%s: error %d completing urb %d\n", + __func__, retval, pipe); + goto exit; + } + + if (copy_to_user(buffer, buf, cnt)) { + dev_err(&dev->dev, "%s: can't copy_to_user\n", __func__); + retval = -EFAULT; + } else { + retval = cnt; + dev_dbg(&dev->dev, "%s: read %d bytes from pipe %d\n", + __func__, cnt, pipe); + } + +exit: + usb_free_urb(urb); + kfree(buf); + return retval; +} + +static ssize_t vstusb_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct vstusb_device *vstdev; + int cnt = -1; + void *buf; + int retval = 0; + + struct urb *urb; + struct usb_device *dev; + unsigned int pipe; + int timeout; + + DECLARE_COMPLETION_ONSTACK(done); + + vstdev = file->private_data; + + if (vstdev == NULL) + return -ENODEV; + + /* verify that we actually have some data to write */ + if ((count == 0) || (count > VST_MAXBUFFER)) + return retval; + + /* lock this object */ + if (mutex_lock_interruptible(&vstdev->lock)) + return -ERESTARTSYS; + + /* anyone home */ + if (!vstdev->present) { + mutex_unlock(&vstdev->lock); + printk(KERN_ERR KBUILD_MODNAME + ": %s: device not present\n", __func__); + return -ENODEV; + } + + /* pull out the necessary data */ + dev = vstdev->usb_dev; + pipe = usb_sndbulkpipe(dev, vstdev->wr_pipe); + timeout = vstdev->wr_timeout_ms; + + buf = kmalloc(count, GFP_KERNEL); + if (buf == NULL) { + mutex_unlock(&vstdev->lock); + return -ENOMEM; + } + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + kfree(buf); + mutex_unlock(&vstdev->lock); + return -ENOMEM; + } + + if (copy_from_user(buf, buffer, count)) { + dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__); + retval = -EFAULT; + goto exit; + } + + usb_anchor_urb(urb, &vstdev->submitted); + retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done); + mutex_unlock(&vstdev->lock); + if (retval) { + usb_unanchor_urb(urb); + dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n", + __func__, retval, pipe); + goto exit; + } + + retval = vstusb_complete_urb(urb, &done, timeout, &cnt); + if (retval) { + dev_err(&dev->dev, "%s: error %d completing urb %d\n", + __func__, retval, pipe); + goto exit; + } else { + retval = cnt; + dev_dbg(&dev->dev, "%s: sent %d bytes to pipe %d\n", + __func__, cnt, pipe); + } + +exit: + usb_free_urb(urb); + kfree(buf); + return retval; +} + +static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + int cnt = -1; + void __user *data = (void __user *)arg; + struct vstusb_args usb_data; + + struct vstusb_device *vstdev; + void *buffer = NULL; /* must be initialized. buffer is + * referenced on exit but not all + * ioctls allocate it */ + + struct urb *urb = NULL; /* must be initialized. urb is + * referenced on exit but not all + * ioctls allocate it */ + struct usb_device *dev; + unsigned int pipe; + int timeout; + + DECLARE_COMPLETION_ONSTACK(done); + + vstdev = file->private_data; + + if (_IOC_TYPE(cmd) != VST_IOC_MAGIC) { + dev_warn(&vstdev->usb_dev->dev, + "%s: ioctl command %x, bad ioctl magic %x, " + "expected %x\n", __func__, cmd, + _IOC_TYPE(cmd), VST_IOC_MAGIC); + return -EINVAL; + } + + if (vstdev == NULL) + return -ENODEV; + + if (copy_from_user(&usb_data, data, sizeof(struct vstusb_args))) { + dev_err(&vstdev->usb_dev->dev, "%s: can't copy_from_user\n", + __func__); + return -EFAULT; + } + + /* lock this object */ + if (mutex_lock_interruptible(&vstdev->lock)) { + retval = -ERESTARTSYS; + goto exit; + } + + /* anyone home */ + if (!vstdev->present) { + mutex_unlock(&vstdev->lock); + dev_err(&vstdev->usb_dev->dev, "%s: device not present\n", + __func__); + retval = -ENODEV; + goto exit; + } + + /* pull out the necessary data */ + dev = vstdev->usb_dev; + + switch (cmd) { + + case IOCTL_VSTUSB_CONFIG_RW: + + vstdev->rd_pipe = usb_data.rd_pipe; + vstdev->rd_timeout_ms = usb_data.rd_timeout_ms; + vstdev->wr_pipe = usb_data.wr_pipe; + vstdev->wr_timeout_ms = usb_data.wr_timeout_ms; + + mutex_unlock(&vstdev->lock); + + dev_dbg(&dev->dev, "%s: setting pipes/timeouts, " + "rdpipe = %d, rdtimeout = %d, " + "wrpipe = %d, wrtimeout = %d\n", __func__, + vstdev->rd_pipe, vstdev->rd_timeout_ms, + vstdev->wr_pipe, vstdev->wr_timeout_ms); + break; + + case IOCTL_VSTUSB_SEND_PIPE: + + if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) { + mutex_unlock(&vstdev->lock); + retval = -EINVAL; + goto exit; + } + + buffer = kmalloc(usb_data.count, GFP_KERNEL); + if (buffer == NULL) { + mutex_unlock(&vstdev->lock); + retval = -ENOMEM; + goto exit; + } + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + mutex_unlock(&vstdev->lock); + retval = -ENOMEM; + goto exit; + } + + timeout = usb_data.timeout_ms; + + pipe = usb_sndbulkpipe(dev, usb_data.pipe); + + if (copy_from_user(buffer, usb_data.buffer, usb_data.count)) { + dev_err(&dev->dev, "%s: can't copy_from_user\n", + __func__); + mutex_unlock(&vstdev->lock); + retval = -EFAULT; + goto exit; + } + + usb_anchor_urb(urb, &vstdev->submitted); + retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer, + usb_data.count, &done); + mutex_unlock(&vstdev->lock); + if (retval) { + usb_unanchor_urb(urb); + dev_err(&dev->dev, + "%s: error %d filling and sending urb %d\n", + __func__, retval, pipe); + goto exit; + } + + retval = vstusb_complete_urb(urb, &done, timeout, &cnt); + if (retval) { + dev_err(&dev->dev, "%s: error %d completing urb %d\n", + __func__, retval, pipe); + } + + break; + case IOCTL_VSTUSB_RECV_PIPE: + + if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) { + mutex_unlock(&vstdev->lock); + retval = -EINVAL; + goto exit; + } + + buffer = kmalloc(usb_data.count, GFP_KERNEL); + if (buffer == NULL) { + mutex_unlock(&vstdev->lock); + retval = -ENOMEM; + goto exit; + } + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + mutex_unlock(&vstdev->lock); + retval = -ENOMEM; + goto exit; + } + + timeout = usb_data.timeout_ms; + + pipe = usb_rcvbulkpipe(dev, usb_data.pipe); + + usb_anchor_urb(urb, &vstdev->submitted); + retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer, + usb_data.count, &done); + mutex_unlock(&vstdev->lock); + if (retval) { + usb_unanchor_urb(urb); + dev_err(&dev->dev, + "%s: error %d filling and sending urb %d\n", + __func__, retval, pipe); + goto exit; + } + + retval = vstusb_complete_urb(urb, &done, timeout, &cnt); + if (retval) { + dev_err(&dev->dev, "%s: error %d completing urb %d\n", + __func__, retval, pipe); + goto exit; + } + + if (copy_to_user(usb_data.buffer, buffer, cnt)) { + dev_err(&dev->dev, "%s: can't copy_to_user\n", + __func__); + retval = -EFAULT; + goto exit; + } + + usb_data.count = cnt; + if (copy_to_user(data, &usb_data, sizeof(struct vstusb_args))) { + dev_err(&dev->dev, "%s: can't copy_to_user\n", + __func__); + retval = -EFAULT; + } else { + dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n", + __func__, usb_data.count, usb_data.pipe); + } + + break; + + default: + mutex_unlock(&vstdev->lock); + dev_warn(&dev->dev, "ioctl_vstusb: invalid ioctl cmd %x\n", + cmd); + return -EINVAL; + break; + } +exit: + usb_free_urb(urb); + kfree(buffer); + return retval; +} + +static const struct file_operations vstusb_fops = { + .owner = THIS_MODULE, + .read = vstusb_read, + .write = vstusb_write, + .unlocked_ioctl = vstusb_ioctl, + .compat_ioctl = vstusb_ioctl, + .open = vstusb_open, + .release = vstusb_release, +}; + +static struct usb_class_driver usb_vstusb_class = { + .name = "usb/vstusb%d", + .fops = &vstusb_fops, + .minor_base = VSTUSB_MINOR_BASE, +}; + +static int vstusb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct vstusb_device *vstdev; + int i; + int retval = 0; + + /* allocate memory for our device state and intialize it */ + + vstdev = kzalloc(sizeof(*vstdev), GFP_KERNEL); + if (vstdev == NULL) + return -ENOMEM; + + /* must do usb_get_dev() prior to kref_init() since the kref_put() + * release function will do a usb_put_dev() */ + usb_get_dev(dev); + kref_init(&vstdev->kref); + mutex_init(&vstdev->lock); + + i = dev->descriptor.bcdDevice; + + dev_dbg(&intf->dev, "Version %1d%1d.%1d%1d found at address %d\n", + (i & 0xF000) >> 12, (i & 0xF00) >> 8, + (i & 0xF0) >> 4, (i & 0xF), dev->devnum); + + vstdev->present = 1; + vstdev->isopen = 0; + vstdev->usb_dev = dev; + init_usb_anchor(&vstdev->submitted); + + usb_set_intfdata(intf, vstdev); + retval = usb_register_dev(intf, &usb_vstusb_class); + if (retval) { + dev_err(&intf->dev, + "%s: Not able to get a minor for this device.\n", + __func__); + usb_set_intfdata(intf, NULL); + kref_put(&vstdev->kref, vstusb_delete); + return retval; + } + + /* let the user know what node this device is now attached to */ + dev_info(&intf->dev, + "VST USB Device #%d now attached to major %d minor %d\n", + (intf->minor - VSTUSB_MINOR_BASE), USB_MAJOR, intf->minor); + + dev_info(&intf->dev, "%s, %s\n", DRIVER_DESC, DRIVER_VERSION); + + return retval; +} + +static void vstusb_disconnect(struct usb_interface *intf) +{ + struct vstusb_device *vstdev = usb_get_intfdata(intf); + + usb_deregister_dev(intf, &usb_vstusb_class); + usb_set_intfdata(intf, NULL); + + if (vstdev) { + + mutex_lock(&vstdev->lock); + vstdev->present = 0; + + usb_kill_anchored_urbs(&vstdev->submitted); + + mutex_unlock(&vstdev->lock); + + kref_put(&vstdev->kref, vstusb_delete); + } + +} + +static int vstusb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct vstusb_device *vstdev = usb_get_intfdata(intf); + int time; + if (!vstdev) + return 0; + + mutex_lock(&vstdev->lock); + time = usb_wait_anchor_empty_timeout(&vstdev->submitted, 1000); + if (!time) + usb_kill_anchored_urbs(&vstdev->submitted); + mutex_unlock(&vstdev->lock); + + return 0; +} + +static int vstusb_resume(struct usb_interface *intf) +{ + return 0; +} + +static struct usb_driver vstusb_driver = { + .name = "vstusb", + .probe = vstusb_probe, + .disconnect = vstusb_disconnect, + .suspend = vstusb_suspend, + .resume = vstusb_resume, + .id_table = id_table, +}; + +static int __init vstusb_init(void) +{ + int rc; + + rc = usb_register(&vstusb_driver); + if (rc) + printk(KERN_ERR "%s: failed to register (%d)", __func__, rc); + + return rc; +} + +static void __exit vstusb_exit(void) +{ + usb_deregister(&vstusb_driver); +} + +module_init(vstusb_init); +module_exit(vstusb_exit); + +MODULE_AUTHOR("Dennis O'Brien/Stephen Ware"); +MODULE_DESCRIPTION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 6566fc0a3228..c9de3f027aab 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1162,9 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus) if (minor >= MON_BIN_MAX_MINOR) return 0; - dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL, - MKDEV(MAJOR(mon_bin_dev0), minor), NULL, - "usbmon%d", minor); + dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL, + MKDEV(MAJOR(mon_bin_dev0), minor), NULL, + "usbmon%d", minor); if (IS_ERR(dev)) return 0; diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 442d8076b201..5e0ab4201c00 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -361,12 +361,12 @@ static int __init mon_init(void) } // MOD_INC_USE_COUNT(which_module?); - usb_register_notify(&mon_nb); mutex_lock(&usb_bus_list_lock); list_for_each_entry (ubus, &usb_bus_list, bus_list) { mon_bus_init(ubus); } + usb_register_notify(&mon_nb); mutex_unlock(&usb_bus_list_lock); return 0; diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 58b2b8fc9439..4b9542bbb35c 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -33,10 +33,6 @@ config USB_MUSB_SOC default y if ARCH_DAVINCI default y if ARCH_OMAP2430 default y if ARCH_OMAP34XX - help - Use a static <asm/arch/hdrc_cnf.h> file to describe how the - controller is configured (endpoints, mechanisms, etc) on the - current iteration of a given system-on-chip. comment "DaVinci 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h index fc5216b5d2c5..729b4071787b 100644 --- a/drivers/usb/musb/cppi_dma.h +++ b/drivers/usb/musb/cppi_dma.h @@ -119,8 +119,8 @@ struct cppi { void __iomem *mregs; /* Mentor regs */ void __iomem *tibase; /* TI/CPPI regs */ - struct cppi_channel tx[MUSB_C_NUM_EPT - 1]; - struct cppi_channel rx[MUSB_C_NUM_EPR - 1]; + struct cppi_channel tx[4]; + struct cppi_channel rx[4]; struct dma_pool *pool; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 75baf181a8cd..dfb3bcbe00fc 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -30,6 +30,7 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/gpio.h> #include <asm/arch/hardware.h> #include <asm/arch/memory.h> @@ -39,7 +40,7 @@ #include "musb_core.h" #ifdef CONFIG_MACH_DAVINCI_EVM -#include <asm/arch/i2c-client.h> +#define GPIO_nVBUS_DRV 87 #endif #include "davinci.h" @@ -138,7 +139,6 @@ static int vbus_state = -1; /* VBUS SWITCHING IS BOARD-SPECIFIC */ #ifdef CONFIG_MACH_DAVINCI_EVM -#ifndef CONFIG_MACH_DAVINCI_EVM_OTG /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice @@ -146,12 +146,11 @@ static int vbus_state = -1; */ static void evm_deferred_drvvbus(struct work_struct *ignored) { - davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state); + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); -#endif /* modified board */ #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) @@ -165,21 +164,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) #ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { -#ifdef CONFIG_MACH_DAVINCI_EVM_OTG - /* modified EVM board switching VBUS with GPIO(6) not I2C - * NOTE: PINMUX0.RGB888 (bit23) must be clear - */ - if (is_on) - gpio_set(GPIO(6)); - else - gpio_clear(GPIO(6)); - immediate = 1; -#else if (immediate) - davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on); + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); -#endif } #endif if (immediate) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 128e949db47c..4a35745b30be 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -82,9 +82,9 @@ /* * This gets many kinds of configuration information: * - Kconfig for everything user-configurable - * - <asm/arch/hdrc_cnf.h> for SOC or family details * - platform_device for addressing, irq, and platform_data * - platform_data is mostly for board-specific informarion + * (plus recentrly, SOC or family details) * * Most of the conditional compilation will (someday) vanish. */ @@ -974,9 +974,9 @@ static void musb_shutdown(struct platform_device *pdev) /* * The silicon either has hard-wired endpoint configurations, or else * "dynamic fifo" sizing. The driver has support for both, though at this - * writing only the dynamic sizing is very well tested. We use normal - * idioms to so both modes are compile-tested, but dead code elimination - * leaves only the relevant one in the object file. + * writing only the dynamic sizing is very well tested. Since we switched + * away from compile-time hardware parameters, we can no longer rely on + * dead code elimination to leave only the relevant one in the object file. * * We don't currently use dynamic fifo setup capability to do anything * more than selecting one of a bunch of predefined configurations. @@ -1806,6 +1806,7 @@ allocate_instance(struct device *dev, musb->ctrl_base = mbase; musb->nIrq = -ENODEV; musb->config = config; + BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS); for (epnum = 0, ep = musb->endpoints; epnum < musb->config->num_eps; epnum++, ep++) { @@ -2054,15 +2055,6 @@ bad_config: } - return 0; - -fail: - if (musb->clock) - clk_put(musb->clock); - device_init_wakeup(dev, 0); - musb_free(musb); - return status; - #ifdef CONFIG_SYSFS status = device_create_file(dev, &dev_attr_mode); status = device_create_file(dev, &dev_attr_vbus); @@ -2071,12 +2063,31 @@ fail: #endif /* CONFIG_USB_GADGET_MUSB_HDRC */ status = 0; #endif + if (status) + goto fail2; - return status; + return 0; fail2: +#ifdef CONFIG_SYSFS + device_remove_file(musb->controller, &dev_attr_mode); + device_remove_file(musb->controller, &dev_attr_vbus); +#ifdef CONFIG_USB_MUSB_OTG + device_remove_file(musb->controller, &dev_attr_srp); +#endif +#endif musb_platform_exit(musb); - goto fail; +fail: + dev_err(musb->controller, + "musb_init_controller failed with status %d\n", status); + + if (musb->clock) + clk_put(musb->clock); + device_init_wakeup(dev, 0); + musb_free(musb); + + return status; + } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index a57652fff39c..3f5e30ddfa27 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -437,7 +437,7 @@ static void ep0_rxstate(struct musb *musb) { void __iomem *regs = musb->control_ep->regs; struct usb_request *req; - u16 tmp; + u16 count, csr; req = next_ep0_request(musb); @@ -449,35 +449,35 @@ static void ep0_rxstate(struct musb *musb) unsigned len = req->length - req->actual; /* read the buffer */ - tmp = musb_readb(regs, MUSB_COUNT0); - if (tmp > len) { + count = musb_readb(regs, MUSB_COUNT0); + if (count > len) { req->status = -EOVERFLOW; - tmp = len; + count = len; } - musb_read_fifo(&musb->endpoints[0], tmp, buf); - req->actual += tmp; - tmp = MUSB_CSR0_P_SVDRXPKTRDY; - if (tmp < 64 || req->actual == req->length) { + musb_read_fifo(&musb->endpoints[0], count, buf); + req->actual += count; + csr = MUSB_CSR0_P_SVDRXPKTRDY; + if (count < 64 || req->actual == req->length) { musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - tmp |= MUSB_CSR0_P_DATAEND; + csr |= MUSB_CSR0_P_DATAEND; } else req = NULL; } else - tmp = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL; + csr = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL; /* Completion handler may choose to stall, e.g. because the * message just received holds invalid data. */ if (req) { - musb->ackpend = tmp; + musb->ackpend = csr; musb_g_ep0_giveback(musb, req); if (!musb->ackpend) return; musb->ackpend = 0; } musb_ep_select(musb->mregs, 0); - musb_writew(regs, MUSB_CSR0, tmp); + musb_writew(regs, MUSB_CSR0, csr); } /* diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 8b4be012669a..3133990f04ec 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -108,7 +108,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, /* * Clear TX fifo. Needed to avoid BABBLE errors. */ -static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) +static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) { void __iomem *epio = ep->regs; u16 csr; @@ -291,6 +291,7 @@ __acquires(musb->lock) urb->actual_length, urb->transfer_buffer_length ); + usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); spin_unlock(&musb->lock); usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status); spin_lock(&musb->lock); @@ -353,8 +354,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) break; } - usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); - qh->is_ready = 0; __musb_giveback(musb, urb, status); qh->is_ready = ready; @@ -436,7 +435,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb, } } -static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) +static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) { /* we don't want fifo to fill itself again; * ignore dma (various models), @@ -1005,7 +1004,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) /* * Handle default endpoint interrupt as host. Only called in IRQ time - * from the LinuxIsr() interrupt service routine. + * from musb_interrupt(). * * called with controller irqlocked */ @@ -1791,7 +1790,9 @@ static int musb_urb_enqueue( */ qh = kzalloc(sizeof *qh, mem_flags); if (!qh) { + spin_lock_irqsave(&musb->lock, flags); usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&musb->lock, flags); return -ENOMEM; } @@ -1873,7 +1874,11 @@ static int musb_urb_enqueue( /* set up tt info if needed */ if (urb->dev->tt) { qh->h_port_reg = (u8) urb->dev->ttport; - qh->h_addr_reg |= 0x80; + if (urb->dev->tt->hub) + qh->h_addr_reg = + (u8) urb->dev->tt->hub->devnum; + if (urb->dev->tt->multi) + qh->h_addr_reg |= 0x80; } } } @@ -1903,7 +1908,9 @@ static int musb_urb_enqueue( done: if (ret != 0) { + spin_lock_irqsave(&musb->lock, flags); usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&musb->lock, flags); kfree(qh); } return ret; diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 6bbedae83af8..223f0a514094 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -37,7 +37,9 @@ #include <linux/io.h> -#ifndef CONFIG_ARM +#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ + && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ + && !defined(CONFIG_PPC64) static inline void readsl(const void __iomem *addr, void *buf, int len) { insl((unsigned long)addr, buf, len); } static inline void readsw(const void __iomem *addr, void *buf, int len) diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 9ba8fb7fcd24..8c734ef2c1ed 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -45,8 +45,8 @@ #define MUSB_HSDMA_ADDRESS 0x8 #define MUSB_HSDMA_COUNT 0xc -#define MUSB_HSDMA_CHANNEL_OFFSET(_bChannel, _offset) \ - (MUSB_HSDMA_BASE + (_bChannel << 4) + _offset) +#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ + (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) /* control register (16-bit): */ #define MUSB_HSDMA_ENABLE_SHIFT 0 @@ -67,23 +67,23 @@ struct musb_dma_controller; struct musb_dma_channel { - struct dma_channel Channel; + struct dma_channel channel; struct musb_dma_controller *controller; - u32 dwStartAddress; + u32 start_addr; u32 len; - u16 wMaxPacketSize; - u8 bIndex; + u16 max_packet_sz; + u8 idx; u8 epnum; u8 transmit; }; struct musb_dma_controller { - struct dma_controller Controller; - struct musb_dma_channel aChannel[MUSB_HSDMA_CHANNELS]; - void *pDmaPrivate; - void __iomem *pCoreBase; - u8 bChannelCount; - u8 bmUsedChannels; + struct dma_controller controller; + struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; + void *private_data; + void __iomem *base; + u8 channel_count; + u8 used_channels; u8 irq; }; @@ -93,91 +93,91 @@ static int dma_controller_start(struct dma_controller *c) return 0; } -static void dma_channel_release(struct dma_channel *pChannel); +static void dma_channel_release(struct dma_channel *channel); static int dma_controller_stop(struct dma_controller *c) { - struct musb_dma_controller *controller = - container_of(c, struct musb_dma_controller, Controller); - struct musb *musb = (struct musb *) controller->pDmaPrivate; - struct dma_channel *pChannel; - u8 bBit; + struct musb_dma_controller *controller = container_of(c, + struct musb_dma_controller, controller); + struct musb *musb = controller->private_data; + struct dma_channel *channel; + u8 bit; - if (controller->bmUsedChannels != 0) { + if (controller->used_channels != 0) { dev_err(musb->controller, "Stopping DMA controller while channel active\n"); - for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) { - if (controller->bmUsedChannels & (1 << bBit)) { - pChannel = &controller->aChannel[bBit].Channel; - dma_channel_release(pChannel); + for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) { + if (controller->used_channels & (1 << bit)) { + channel = &controller->channel[bit].channel; + dma_channel_release(channel); - if (!controller->bmUsedChannels) + if (!controller->used_channels) break; } } } + return 0; } static struct dma_channel *dma_channel_allocate(struct dma_controller *c, struct musb_hw_ep *hw_ep, u8 transmit) { - u8 bBit; - struct dma_channel *pChannel = NULL; - struct musb_dma_channel *pImplChannel = NULL; - struct musb_dma_controller *controller = - container_of(c, struct musb_dma_controller, Controller); - - for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) { - if (!(controller->bmUsedChannels & (1 << bBit))) { - controller->bmUsedChannels |= (1 << bBit); - pImplChannel = &(controller->aChannel[bBit]); - pImplChannel->controller = controller; - pImplChannel->bIndex = bBit; - pImplChannel->epnum = hw_ep->epnum; - pImplChannel->transmit = transmit; - pChannel = &(pImplChannel->Channel); - pChannel->private_data = pImplChannel; - pChannel->status = MUSB_DMA_STATUS_FREE; - pChannel->max_len = 0x10000; + struct musb_dma_controller *controller = container_of(c, + struct musb_dma_controller, controller); + struct musb_dma_channel *musb_channel = NULL; + struct dma_channel *channel = NULL; + u8 bit; + + for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) { + if (!(controller->used_channels & (1 << bit))) { + controller->used_channels |= (1 << bit); + musb_channel = &(controller->channel[bit]); + musb_channel->controller = controller; + musb_channel->idx = bit; + musb_channel->epnum = hw_ep->epnum; + musb_channel->transmit = transmit; + channel = &(musb_channel->channel); + channel->private_data = musb_channel; + channel->status = MUSB_DMA_STATUS_FREE; + channel->max_len = 0x10000; /* Tx => mode 1; Rx => mode 0 */ - pChannel->desired_mode = transmit; - pChannel->actual_len = 0; + channel->desired_mode = transmit; + channel->actual_len = 0; break; } } - return pChannel; + + return channel; } -static void dma_channel_release(struct dma_channel *pChannel) +static void dma_channel_release(struct dma_channel *channel) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; + struct musb_dma_channel *musb_channel = channel->private_data; - pChannel->actual_len = 0; - pImplChannel->dwStartAddress = 0; - pImplChannel->len = 0; + channel->actual_len = 0; + musb_channel->start_addr = 0; + musb_channel->len = 0; - pImplChannel->controller->bmUsedChannels &= - ~(1 << pImplChannel->bIndex); + musb_channel->controller->used_channels &= + ~(1 << musb_channel->idx); - pChannel->status = MUSB_DMA_STATUS_UNKNOWN; + channel->status = MUSB_DMA_STATUS_UNKNOWN; } -static void configure_channel(struct dma_channel *pChannel, +static void configure_channel(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; - struct musb_dma_controller *controller = pImplChannel->controller; - void __iomem *mbase = controller->pCoreBase; - u8 bChannel = pImplChannel->bIndex; + struct musb_dma_channel *musb_channel = channel->private_data; + struct musb_dma_controller *controller = musb_channel->controller; + void __iomem *mbase = controller->base; + u8 bchannel = musb_channel->idx; u16 csr = 0; DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", - pChannel, packet_sz, dma_addr, len, mode); + channel, packet_sz, dma_addr, len, mode); if (mode) { csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; @@ -195,180 +195,183 @@ static void configure_channel(struct dma_channel *pChannel, } } - csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) + csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) | (1 << MUSB_HSDMA_ENABLE_SHIFT) | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) - | (pImplChannel->transmit + | (musb_channel->transmit ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) : 0); /* address/count */ musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), dma_addr); musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), len); /* control (this should start things) */ musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), csr); } -static int dma_channel_program(struct dma_channel *pChannel, +static int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; + struct musb_dma_channel *musb_channel = channel->private_data; DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", - pImplChannel->epnum, - pImplChannel->transmit ? "Tx" : "Rx", + musb_channel->epnum, + musb_channel->transmit ? "Tx" : "Rx", packet_sz, dma_addr, len, mode); - BUG_ON(pChannel->status == MUSB_DMA_STATUS_UNKNOWN || - pChannel->status == MUSB_DMA_STATUS_BUSY); + BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || + channel->status == MUSB_DMA_STATUS_BUSY); - pChannel->actual_len = 0; - pImplChannel->dwStartAddress = dma_addr; - pImplChannel->len = len; - pImplChannel->wMaxPacketSize = packet_sz; - pChannel->status = MUSB_DMA_STATUS_BUSY; + channel->actual_len = 0; + musb_channel->start_addr = dma_addr; + musb_channel->len = len; + musb_channel->max_packet_sz = packet_sz; + channel->status = MUSB_DMA_STATUS_BUSY; if ((mode == 1) && (len >= packet_sz)) - configure_channel(pChannel, packet_sz, 1, dma_addr, len); + configure_channel(channel, packet_sz, 1, dma_addr, len); else - configure_channel(pChannel, packet_sz, 0, dma_addr, len); + configure_channel(channel, packet_sz, 0, dma_addr, len); return true; } -static int dma_channel_abort(struct dma_channel *pChannel) +static int dma_channel_abort(struct dma_channel *channel) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; - u8 bChannel = pImplChannel->bIndex; - void __iomem *mbase = pImplChannel->controller->pCoreBase; + struct musb_dma_channel *musb_channel = channel->private_data; + void __iomem *mbase = musb_channel->controller->base; + + u8 bchannel = musb_channel->idx; u16 csr; - if (pChannel->status == MUSB_DMA_STATUS_BUSY) { - if (pImplChannel->transmit) { + if (channel->status == MUSB_DMA_STATUS_BUSY) { + if (musb_channel->transmit) { csr = musb_readw(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR)); csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE); musb_writew(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, - MUSB_TXCSR), + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), csr); } else { csr = musb_readw(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR)); csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAMODE); musb_writew(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, - MUSB_RXCSR), + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR), csr); } musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), 0); musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), 0); musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), 0); - pChannel->status = MUSB_DMA_STATUS_FREE; + channel->status = MUSB_DMA_STATUS_FREE; } + return 0; } static irqreturn_t dma_controller_irq(int irq, void *private_data) { - struct musb_dma_controller *controller = - (struct musb_dma_controller *)private_data; - struct musb_dma_channel *pImplChannel; - struct musb *musb = controller->pDmaPrivate; - void __iomem *mbase = controller->pCoreBase; - struct dma_channel *pChannel; - u8 bChannel; - u16 csr; - u32 dwAddress; - u8 int_hsdma; + struct musb_dma_controller *controller = private_data; + struct musb *musb = controller->private_data; + struct musb_dma_channel *musb_channel; + struct dma_channel *channel; + + void __iomem *mbase = controller->base; + irqreturn_t retval = IRQ_NONE; + unsigned long flags; + u8 bchannel; + u8 int_hsdma; + + u32 addr; + u16 csr; + spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); if (!int_hsdma) goto done; - for (bChannel = 0; bChannel < MUSB_HSDMA_CHANNELS; bChannel++) { - if (int_hsdma & (1 << bChannel)) { - pImplChannel = (struct musb_dma_channel *) - &(controller->aChannel[bChannel]); - pChannel = &pImplChannel->Channel; + for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { + if (int_hsdma & (1 << bchannel)) { + musb_channel = (struct musb_dma_channel *) + &(controller->channel[bchannel]); + channel = &musb_channel->channel; csr = musb_readw(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL)); - if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) - pImplChannel->Channel.status = + if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) { + musb_channel->channel.status = MUSB_DMA_STATUS_BUS_ABORT; - else { + } else { u8 devctl; - dwAddress = musb_readl(mbase, + addr = musb_readl(mbase, MUSB_HSDMA_CHANNEL_OFFSET( - bChannel, + bchannel, MUSB_HSDMA_ADDRESS)); - pChannel->actual_len = dwAddress - - pImplChannel->dwStartAddress; + channel->actual_len = addr + - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", - pChannel, pImplChannel->dwStartAddress, - dwAddress, pChannel->actual_len, - pImplChannel->len, - (pChannel->actual_len - < pImplChannel->len) ? + channel, musb_channel->start_addr, + addr, channel->actual_len, + musb_channel->len, + (channel->actual_len + < musb_channel->len) ? "=> reconfig 0" : "=> complete"); devctl = musb_readb(mbase, MUSB_DEVCTL); - pChannel->status = MUSB_DMA_STATUS_FREE; + channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((devctl & MUSB_DEVCTL_HM) - && (pImplChannel->transmit) - && ((pChannel->desired_mode == 0) - || (pChannel->actual_len & - (pImplChannel->wMaxPacketSize - 1))) + && (musb_channel->transmit) + && ((channel->desired_mode == 0) + || (channel->actual_len & + (musb_channel->max_packet_sz - 1))) ) { /* Send out the packet */ musb_ep_select(mbase, - pImplChannel->epnum); + musb_channel->epnum); musb_writew(mbase, MUSB_EP_OFFSET( - pImplChannel->epnum, + musb_channel->epnum, MUSB_TXCSR), MUSB_TXCSR_TXPKTRDY); - } else + } else { musb_dma_completion( musb, - pImplChannel->epnum, - pImplChannel->transmit); + musb_channel->epnum, + musb_channel->transmit); + } } } } @@ -380,9 +383,9 @@ done: void dma_controller_destroy(struct dma_controller *c) { - struct musb_dma_controller *controller; + struct musb_dma_controller *controller = container_of(c, + struct musb_dma_controller, controller); - controller = container_of(c, struct musb_dma_controller, Controller); if (!controller) return; @@ -393,7 +396,7 @@ void dma_controller_destroy(struct dma_controller *c) } struct dma_controller *__init -dma_controller_create(struct musb *musb, void __iomem *pCoreBase) +dma_controller_create(struct musb *musb, void __iomem *base) { struct musb_dma_controller *controller; struct device *dev = musb->controller; @@ -405,29 +408,30 @@ dma_controller_create(struct musb *musb, void __iomem *pCoreBase) return NULL; } - controller = kzalloc(sizeof(struct musb_dma_controller), GFP_KERNEL); + controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) return NULL; - controller->bChannelCount = MUSB_HSDMA_CHANNELS; - controller->pDmaPrivate = musb; - controller->pCoreBase = pCoreBase; + controller->channel_count = MUSB_HSDMA_CHANNELS; + controller->private_data = musb; + controller->base = base; - controller->Controller.start = dma_controller_start; - controller->Controller.stop = dma_controller_stop; - controller->Controller.channel_alloc = dma_channel_allocate; - controller->Controller.channel_release = dma_channel_release; - controller->Controller.channel_program = dma_channel_program; - controller->Controller.channel_abort = dma_channel_abort; + controller->controller.start = dma_controller_start; + controller->controller.stop = dma_controller_stop; + controller->controller.channel_alloc = dma_channel_allocate; + controller->controller.channel_release = dma_channel_release; + controller->controller.channel_program = dma_channel_program; + controller->controller.channel_abort = dma_channel_abort; if (request_irq(irq, dma_controller_irq, IRQF_DISABLED, - musb->controller->bus_id, &controller->Controller)) { + musb->controller->bus_id, &controller->controller)) { dev_err(dev, "request_irq %d failed!\n", irq); - dma_controller_destroy(&controller->Controller); + dma_controller_destroy(&controller->controller); + return NULL; } controller->irq = irq; - return &controller->Controller; + return &controller->controller; } diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 79ea98c66fa8..537f953bd7f8 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -220,8 +220,8 @@ static void aircable_send(struct usb_serial_port *port) buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC); if (!buf) { - err("%s- kzalloc(%d) failed.", __func__, - count + HCI_HEADER_LENGTH); + dev_err(&port->dev, "%s- kzalloc(%d) failed.\n", + __func__, count + HCI_HEADER_LENGTH); return; } @@ -272,23 +272,24 @@ static void aircable_read(struct work_struct *work) * 64 bytes, to ensure I do not get throttled. * Ask USB mailing list for better aproach. */ - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (!tty) { schedule_work(&priv->rx_work); - err("%s - No tty available", __func__); + dev_err(&port->dev, "%s - No tty available\n", __func__); return ; } count = min(64, serial_buf_data_avail(priv->rx_buf)); if (count <= 0) - return; /* We have finished sending everything. */ + goto out; /* We have finished sending everything. */ tty_prepare_flip_string(tty, &data, count); if (!data) { - err("%s- kzalloc(%d) failed.", __func__, count); - return; + dev_err(&port->dev, "%s- kzalloc(%d) failed.", + __func__, count); + goto out; } serial_buf_get(priv->rx_buf, data, count); @@ -297,7 +298,8 @@ static void aircable_read(struct work_struct *work) if (serial_buf_data_avail(priv->rx_buf)) schedule_work(&priv->rx_work); - +out: + tty_kref_put(tty); return; } /* End of private methods */ @@ -334,7 +336,7 @@ static int aircable_attach(struct usb_serial *serial) priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL); if (!priv) { - err("%s- kmalloc(%Zd) failed.", __func__, + dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, sizeof(struct aircable_private)); return -ENOMEM; } @@ -495,7 +497,7 @@ static void aircable_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, urb->transfer_buffer); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { if (urb->actual_length <= 2) { /* This is an incomplete package */ @@ -527,6 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb) } aircable_read(&priv->rx_work); } + tty_kref_put(tty); /* Schedule the next read _if_ we are still open */ if (port->port.count) { diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 2ebe06c3405a..b7eacad4d48c 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -187,7 +187,7 @@ static int belkin_sa_startup(struct usb_serial *serial) /* see comments at top of file */ priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0; - info("bcdDevice: %04x, bfc: %d", + dev_info(&dev->dev, "bcdDevice: %04x, bfc: %d\n", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); @@ -228,7 +228,7 @@ static int belkin_sa_open(struct tty_struct *tty, port->read_urb->dev = port->serial->dev; retval = usb_submit_urb(port->read_urb, GFP_KERNEL); if (retval) { - err("usb_submit_urb(read bulk) failed"); + dev_err(&port->dev, "usb_submit_urb(read bulk) failed\n"); goto exit; } @@ -236,7 +236,7 @@ static int belkin_sa_open(struct tty_struct *tty, retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (retval) { usb_kill_urb(port->read_urb); - err(" usb_submit_urb(read int) failed"); + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); } exit: @@ -322,7 +322,7 @@ static void belkin_sa_read_int_callback(struct urb *urb) * to look in to this before committing any code. */ if (priv->last_lsr & BELKIN_SA_LSR_ERR) { - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); /* Overrun Error */ if (priv->last_lsr & BELKIN_SA_LSR_OE) { } @@ -335,14 +335,15 @@ static void belkin_sa_read_int_callback(struct urb *urb) /* Break Indicator */ if (priv->last_lsr & BELKIN_SA_LSR_BI) { } + tty_kref_put(tty); } #endif spin_unlock_irqrestore(&priv->lock, flags); exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err("%s - usb_submit_urb failed with result %d", - __func__, retval); + dev_err(&port->dev, "%s - usb_submit_urb failed with " + "result %d\n", __func__, retval); } static void belkin_sa_set_termios(struct tty_struct *tty, @@ -381,12 +382,12 @@ static void belkin_sa_set_termios(struct tty_struct *tty, if ((old_cflag & CBAUD) == B0) { control_state |= (TIOCM_DTR|TIOCM_RTS); if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0) - err("Set DTR error"); + dev_err(&port->dev, "Set DTR error\n"); /* don't set RTS if using hardware flow control */ if (!(old_cflag & CRTSCTS)) if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST , 1) < 0) - err("Set RTS error"); + dev_err(&port->dev, "Set RTS error\n"); } } @@ -402,18 +403,18 @@ static void belkin_sa_set_termios(struct tty_struct *tty, /* Report the actual baud rate back to the caller */ tty_encode_baud_rate(tty, baud, baud); if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0) - err("Set baudrate error"); + dev_err(&port->dev, "Set baudrate error\n"); } else { /* Disable flow control */ if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0) - err("Disable flowcontrol error"); + dev_err(&port->dev, "Disable flowcontrol error\n"); /* Drop RTS and DTR */ control_state &= ~(TIOCM_DTR | TIOCM_RTS); if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0) - err("DTR LOW error"); + dev_err(&port->dev, "DTR LOW error\n"); if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0) - err("RTS LOW error"); + dev_err(&port->dev, "RTS LOW error\n"); } /* set the parity */ @@ -424,7 +425,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, else urb_value = BELKIN_SA_PARITY_NONE; if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0) - err("Set parity error"); + dev_err(&port->dev, "Set parity error\n"); } /* set the number of data bits */ @@ -447,7 +448,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, break; } if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0) - err("Set data bits error"); + dev_err(&port->dev, "Set data bits error\n"); } /* set the number of stop bits */ @@ -456,7 +457,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, : BELKIN_SA_STOP_BITS(1); if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, urb_value) < 0) - err("Set stop bits error"); + dev_err(&port->dev, "Set stop bits error\n"); } /* Set flow control */ @@ -477,7 +478,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, urb_value &= ~(BELKIN_SA_FLOW_IRTS); if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0) - err("Set flow control error"); + dev_err(&port->dev, "Set flow control error\n"); } /* save off the modified port settings */ @@ -493,7 +494,7 @@ static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state) struct usb_serial *serial = port->serial; if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0) - err("Set break_ctl %d", break_state); + dev_err(&port->dev, "Set break_ctl %d\n", break_state); } @@ -553,13 +554,13 @@ static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, rts); if (retval < 0) { - err("Set RTS error %d", retval); + dev_err(&port->dev, "Set RTS error %d\n", retval); goto exit; } retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr); if (retval < 0) { - err("Set DTR error %d", retval); + dev_err(&port->dev, "Set DTR error %d\n", retval); goto exit; } exit: @@ -576,7 +577,8 @@ static int __init belkin_sa_init(void) retval = usb_register(&belkin_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&belkin_device); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index e980766bb84b..5b20de130e08 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -117,7 +117,7 @@ static int usb_console_setup(struct console *co, char *options) } port = serial->port[0]; - port->port.tty = NULL; + tty_port_tty_set(&port->port, NULL); info->port = port; @@ -143,7 +143,7 @@ static int usb_console_setup(struct console *co, char *options) } memset(&dummy, 0, sizeof(struct ktermios)); tty->termios = termios; - port->port.tty = tty; + tty_port_tty_set(&port->port, tty); } /* only call the device specific open if this @@ -163,7 +163,7 @@ static int usb_console_setup(struct console *co, char *options) tty_termios_encode_baud_rate(termios, baud, baud); serial->type->set_termios(tty, port, &dummy); - port->port.tty = NULL; + tty_port_tty_set(&port->port, NULL); kfree(termios); kfree(tty); } @@ -176,7 +176,7 @@ out: return retval; free_termios: kfree(termios); - port->port.tty = NULL; + tty_port_tty_set(&port->port, NULL); free_tty: kfree(tty); reset_open_count: diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 1279553381e3..8008d0bc80ad 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -753,7 +753,8 @@ static int __init cp2101_init(void) } /* Success */ - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; } diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index b4d72351cb96..858bdd038fbc 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -141,7 +141,8 @@ static int cyberjack_startup(struct usb_serial *serial) result = usb_submit_urb(serial->port[i]->interrupt_in_urb, GFP_KERNEL); if (result) - err(" usb_submit_urb(read int) failed"); + dev_err(&serial->dev->dev, + "usb_submit_urb(read int) failed\n"); dbg("%s - usb_submit_urb(int urb)", __func__); } @@ -274,8 +275,9 @@ static int cyberjack_write(struct tty_struct *tty, /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d", + __func__, result); /* Throw away data. No better idea what to do with it. */ priv->wrfilled = 0; priv->wrsent = 0; @@ -351,7 +353,9 @@ static void cyberjack_read_int_callback(struct urb *urb) port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", __func__, result); + dev_err(&port->dev, "%s - failed resubmitting " + "read urb, error %d\n", + __func__, result); dbg("%s - usb_submit_urb(read urb)", __func__); } } @@ -360,7 +364,7 @@ resubmit: port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) - err(" usb_submit_urb(read int) failed"); + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); dbg("%s - usb_submit_urb(int urb)", __func__); } @@ -384,7 +388,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb) return; } - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (!tty) { dbg("%s - ignoring since device not open\n", __func__); return; @@ -394,6 +398,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb) tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); spin_lock(&priv->lock); @@ -413,8 +418,8 @@ static void cyberjack_read_bulk_callback(struct urb *urb) port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", - __func__, result); + dev_err(&port->dev, "%s - failed resubmitting read " + "urb, error %d\n", __func__, result); dbg("%s - usb_submit_urb(read urb)", __func__); } } @@ -461,8 +466,9 @@ static void cyberjack_write_bulk_callback(struct urb *urb) /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); /* Throw away data. No better idea what to do with it. */ priv->wrfilled = 0; priv->wrsent = 0; @@ -498,8 +504,9 @@ static int __init cyberjack_init(void) if (retval) goto failed_usb_register; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " " + DRIVER_AUTHOR "\n"); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 22837a3f2f89..eae4740d448c 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -404,8 +404,8 @@ static int cypress_serial_control(struct tty_struct *tty, retval != -ENODEV); if (retval != sizeof(feature_buffer)) { - err("%s - failed sending serial line settings - %d", - __func__, retval); + dev_err(&port->dev, "%s - failed sending serial " + "line settings - %d\n", __func__, retval); cypress_set_dead(port); } else { spin_lock_irqsave(&priv->lock, flags); @@ -443,7 +443,8 @@ static int cypress_serial_control(struct tty_struct *tty, && retval != -ENODEV); if (retval != sizeof(feature_buffer)) { - err("%s - failed to retrieve serial line settings - %d", __func__, retval); + dev_err(&port->dev, "%s - failed to retrieve serial " + "line settings - %d\n", __func__, retval); cypress_set_dead(port); return retval; } else { @@ -476,8 +477,8 @@ static void cypress_set_dead(struct usb_serial_port *port) priv->comm_is_ok = 0; spin_unlock_irqrestore(&priv->lock, flags); - err("cypress_m8 suspending failing port %d - interval might be too short", - port->number); + dev_err(&port->dev, "cypress_m8 suspending failing port %d - " + "interval might be too short\n", port->number); } @@ -679,7 +680,8 @@ static int cypress_open(struct tty_struct *tty, /* setup the port and start reading from the device */ if (!port->interrupt_in_urb) { - err("%s - interrupt_in_urb is empty!", __func__); + dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", + __func__); return -1; } @@ -1107,8 +1109,8 @@ static void cypress_set_termios(struct tty_struct *tty, data_bits = 3; break; default: - err("%s - CSIZE was set, but not CS5-CS8", - __func__); + dev_err(&port->dev, "%s - CSIZE was set, but not CS5-CS8\n", + __func__); data_bits = 3; } spin_lock_irqsave(&priv->lock, flags); @@ -1286,7 +1288,7 @@ static void cypress_read_int_callback(struct urb *urb) } spin_unlock_irqrestore(&priv->lock, flags); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (!tty) { dbg("%s - bad tty pointer - exiting", __func__); return; @@ -1362,7 +1364,7 @@ static void cypress_read_int_callback(struct urb *urb) data[i]); tty_insert_flip_char(tty, data[i], tty_flag); } - tty_flip_buffer_push(port->port.tty); + tty_flip_buffer_push(tty); } spin_lock_irqsave(&priv->lock, flags); @@ -1371,6 +1373,7 @@ static void cypress_read_int_callback(struct urb *urb) spin_unlock_irqrestore(&priv->lock, flags); continue_read: + tty_kref_put(tty); /* Continue trying to always read... unless the port has closed. */ @@ -1657,7 +1660,8 @@ static int __init cypress_init(void) if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 240aad1acaab..69f84f0ea6fe 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -604,7 +604,9 @@ static void digi_wakeup_write_lock(struct work_struct *work) static void digi_wakeup_write(struct usb_serial_port *port) { - tty_wakeup(port->port.tty); + struct tty_struct *tty = tty_port_tty_get(&port->port); + tty_wakeup(tty); + tty_kref_put(tty); } @@ -659,7 +661,8 @@ static int digi_write_oob_command(struct usb_serial_port *port, } spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags); if (ret) - err("%s: usb_submit_urb failed, ret=%d", __func__, ret); + dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d\n", + __func__, ret); return ret; } @@ -741,7 +744,8 @@ static int digi_write_inb_command(struct usb_serial_port *port, spin_unlock_irqrestore(&priv->dp_port_lock, flags); if (ret) - err("%s: usb_submit_urb failed, ret=%d, port=%d", + dev_err(&port->dev, + "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); return ret; } @@ -810,7 +814,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port, spin_unlock(&port_priv->dp_port_lock); spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags); if (ret) - err("%s: usb_submit_urb failed, ret=%d", __func__, ret); + dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d\n", + __func__, ret); return ret; } @@ -905,7 +910,8 @@ static void digi_rx_unthrottle(struct tty_struct *tty) spin_unlock_irqrestore(&priv->dp_port_lock, flags); if (ret) - err("%s: usb_submit_urb failed, ret=%d, port=%d", + dev_err(&port->dev, + "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); } @@ -1212,7 +1218,8 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, /* return length of new data written, or error */ spin_unlock_irqrestore(&priv->dp_port_lock, flags); if (ret < 0) - err("%s: usb_submit_urb failed, ret=%d, port=%d", + dev_err(&port->dev, + "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); dbg("digi_write: returning %d", ret); return ret; @@ -1233,14 +1240,16 @@ static void digi_write_bulk_callback(struct urb *urb) /* port and serial sanity check */ if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { - err("%s: port or port->private is NULL, status=%d", - __func__, status); + dev_err(&port->dev, + "%s: port or port->private is NULL, status=%d\n", + __func__, status); return; } serial = port->serial; if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) { - err("%s: serial or serial->private is NULL, status=%d", - __func__, status); + dev_err(&port->dev, + "%s: serial or serial->private is NULL, status=%d\n", + __func__, status); return; } @@ -1282,7 +1291,8 @@ static void digi_write_bulk_callback(struct urb *urb) spin_unlock(&priv->dp_port_lock); if (ret) - err("%s: usb_submit_urb failed, ret=%d, port=%d", + dev_err(&port->dev, + "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); } @@ -1516,8 +1526,9 @@ static int digi_startup_device(struct usb_serial *serial) port->write_urb->dev = port->serial->dev; ret = usb_submit_urb(port->read_urb, GFP_KERNEL); if (ret != 0) { - err("%s: usb_submit_urb failed, ret=%d, port=%d", - __func__, ret, i); + dev_err(&port->dev, + "%s: usb_submit_urb failed, ret=%d, port=%d\n", + __func__, ret, i); break; } } @@ -1616,22 +1627,26 @@ static void digi_read_bulk_callback(struct urb *urb) dbg("digi_read_bulk_callback: TOP"); /* port sanity check, do not resubmit if port is not valid */ - if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { - err("%s: port or port->private is NULL, status=%d", - __func__, status); + if (port == NULL) + return; + priv = usb_get_serial_port_data(port); + if (priv == NULL) { + dev_err(&port->dev, "%s: port->private is NULL, status=%d\n", + __func__, status); return; } if (port->serial == NULL || (serial_priv = usb_get_serial_data(port->serial)) == NULL) { - err("%s: serial is bad or serial->private is NULL, status=%d", - __func__, status); + dev_err(&port->dev, "%s: serial is bad or serial->private " + "is NULL, status=%d\n", __func__, status); return; } /* do not resubmit urb if it has any status error */ if (status) { - err("%s: nonzero read bulk status: status=%d, port=%d", - __func__, status, priv->dp_port_num); + dev_err(&port->dev, + "%s: nonzero read bulk status: status=%d, port=%d\n", + __func__, status, priv->dp_port_num); return; } @@ -1648,8 +1663,9 @@ static void digi_read_bulk_callback(struct urb *urb) urb->dev = port->serial->dev; ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret != 0) { - err("%s: failed resubmitting urb, ret=%d, port=%d", - __func__, ret, priv->dp_port_num); + dev_err(&port->dev, + "%s: failed resubmitting urb, ret=%d, port=%d\n", + __func__, ret, priv->dp_port_num); } } @@ -1668,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty = port->port.tty; + struct tty_struct *tty; struct digi_port *priv = usb_get_serial_port_data(port); int opcode = ((unsigned char *)urb->transfer_buffer)[0]; int len = ((unsigned char *)urb->transfer_buffer)[1]; @@ -1685,13 +1701,15 @@ static int digi_read_inb_callback(struct urb *urb) /* short/multiple packet check */ if (urb->actual_length != len + 2) { - err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, " - "port=%d, opcode=%d, len=%d, actual_length=%d, " - "status=%d", __func__, status, priv->dp_port_num, - opcode, len, urb->actual_length, port_status); + dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " + "urb->status=%d, port=%d, opcode=%d, len=%d, " + "actual_length=%d, status=%d\n", __func__, status, + priv->dp_port_num, opcode, len, urb->actual_length, + port_status); return -1; } + tty = tty_port_tty_get(&port->port); spin_lock(&priv->dp_port_lock); /* check for throttle; if set, do not resubmit read urb */ @@ -1735,6 +1753,7 @@ static int digi_read_inb_callback(struct urb *urb) } } spin_unlock(&priv->dp_port_lock); + tty_kref_put(tty); if (opcode == DIGI_CMD_RECEIVE_DISABLE) dbg("%s: got RECEIVE_DISABLE", __func__); @@ -1760,6 +1779,7 @@ static int digi_read_oob_callback(struct urb *urb) struct usb_serial_port *port = urb->context; struct usb_serial *serial = port->serial; + struct tty_struct *tty; struct digi_port *priv = usb_get_serial_port_data(port); int opcode, line, status, val; int i; @@ -1787,10 +1807,11 @@ static int digi_read_oob_callback(struct urb *urb) if (priv == NULL) return -1; + tty = tty_port_tty_get(&port->port); rts = 0; if (port->port.count) - rts = port->port.tty->termios->c_cflag & CRTSCTS; - + rts = tty->termios->c_cflag & CRTSCTS; + if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); /* convert from digi flags to termiox flags */ @@ -1798,14 +1819,14 @@ static int digi_read_oob_callback(struct urb *urb) priv->dp_modem_signals |= TIOCM_CTS; /* port must be open to use tty struct */ if (rts) { - port->port.tty->hw_stopped = 0; + tty->hw_stopped = 0; digi_wakeup_write(port); } } else { priv->dp_modem_signals &= ~TIOCM_CTS; /* port must be open to use tty struct */ if (rts) - port->port.tty->hw_stopped = 1; + tty->hw_stopped = 1; } if (val & DIGI_READ_INPUT_SIGNALS_DSR) priv->dp_modem_signals |= TIOCM_DSR; @@ -1830,6 +1851,7 @@ static int digi_read_oob_callback(struct urb *urb) } else if (opcode == DIGI_CMD_IFLUSH_FIFO) { wake_up_interruptible(&priv->dp_flush_wait); } + tty_kref_put(tty); } return 0; @@ -1847,7 +1869,8 @@ static int __init digi_init(void) retval = usb_register(&digi_driver); if (retval) goto failed_usb_register; - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&digi_acceleport_4_device); diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index a6ab5b58d9ca..8a69cce40b6d 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -33,9 +33,8 @@ * Moved MOD_DEC_USE_COUNT to end of empeg_close(). * * (12/03/2000) gb - * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to - * empeg_open(). This notifies the tty driver that the termios have - * changed. + * Added tty->ldisc.set_termios(port, tty, NULL) to empeg_open(). + * This notifies the tty driver that the termios have changed. * * (11/13/2000) gb * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to @@ -354,7 +353,7 @@ static void empeg_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); @@ -362,6 +361,7 @@ static void empeg_read_bulk_callback(struct urb *urb) tty_flip_buffer_push(tty); bytes_in += urb->actual_length; } + tty_kref_put(tty); /* Continue trying to always read */ usb_fill_bulk_urb( @@ -416,7 +416,7 @@ static int empeg_startup(struct usb_serial *serial) dbg("%s", __func__); if (serial->dev->actconfig->desc.bConfigurationValue != 1) { - err("active config #%d != 1 ??", + dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } @@ -499,15 +499,15 @@ static int __init empeg_init(void) urb = usb_alloc_urb(0, GFP_KERNEL); write_urb_pool[i] = urb; if (urb == NULL) { - err("No more urbs???"); + printk(KERN_ERR "empeg: No more urbs???\n"); continue; } urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (!urb->transfer_buffer) { - err("%s - out of memory for urb buffers.", - __func__); + printk(KERN_ERR "empeg: %s - out of memory for urb " + "buffers.", __func__); continue; } } @@ -519,7 +519,8 @@ static int __init empeg_init(void) if (retval) goto failed_usb_register; - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index 711e84f6ed82..3cfc762f5056 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -28,7 +28,8 @@ int ezusb_writememory(struct usb_serial *serial, int address, /* dbg("ezusb_writememory %x, %d", address, length); */ if (!serial->dev) { - err("%s - no physical device present, failing.", __func__); + printk(KERN_ERR "ezusb: %s - no physical device present, " + "failing.\n", __func__); return -ENODEV; } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3dc93b542b30..51d7bdea2869 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -578,6 +578,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, @@ -860,7 +861,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, kfree(buf); if (rv < 0) { - err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", + dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", __func__, (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", @@ -1153,7 +1154,7 @@ static void ftdi_determine_type(struct usb_serial_port *port) /* Assume its an FT232R */ priv->chip_type = FT232RL; } - info("Detected %s", ftdi_chip_name[priv->chip_type]); + dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); } @@ -1326,7 +1327,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv) { - err("%s- kmalloc(%Zd) failed.", __func__, + dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, sizeof(struct ftdi_private)); return -ENOMEM; } @@ -1409,7 +1410,8 @@ static int ftdi_jtag_probe(struct usb_serial *serial) dbg("%s", __func__); if (interface == udev->actconfig->interface[0]) { - info("Ignoring serial port reserved for JTAG"); + dev_info(&udev->dev, + "Ignoring serial port reserved for JTAG\n"); return -ENODEV; } @@ -1427,7 +1429,8 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial) if (ep->enabled && ep_desc->wMaxPacketSize == 0) { ep_desc->wMaxPacketSize = cpu_to_le16(0x40); - info("Fixing invalid wMaxPacketSize on read pipe"); + dev_info(&serial->dev->dev, + "Fixing invalid wMaxPacketSize on read pipe\n"); } return 0; @@ -1521,8 +1524,9 @@ static int ftdi_open(struct tty_struct *tty, ftdi_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) - err("%s - failed submitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); return result; @@ -1556,7 +1560,7 @@ static void ftdi_close(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { - err("error from flowcontrol urb"); + dev_err(&port->dev, "error from flowcontrol urb\n"); } /* drop RTS and DTR */ @@ -1621,14 +1625,15 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, buffer = kmalloc(transfer_size, GFP_ATOMIC); if (!buffer) { - err("%s ran out of kernel memory for urb ...", __func__); + dev_err(&port->dev, + "%s ran out of kernel memory for urb ...\n", __func__); count = -ENOMEM; goto error_no_buffer; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - err("%s - no more free urbs", __func__); + dev_err(&port->dev, "%s - no more free urbs\n", __func__); count = -ENOMEM; goto error_no_urb; } @@ -1672,8 +1677,9 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - err("%s - failed submitting write urb, error %d", - __func__, status); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, status); count = status; goto error; } else { @@ -1780,7 +1786,8 @@ static int ftdi_chars_in_buffer(struct tty_struct *tty) buffered = (int)priv->tx_outstanding_bytes; spin_unlock_irqrestore(&priv->tx_lock, flags); if (buffered < 0) { - err("%s outstanding tx bytes is negative!", __func__); + dev_err(&port->dev, "%s outstanding tx bytes is negative!\n", + __func__); buffered = 0; } return buffered; @@ -1796,11 +1803,12 @@ static void ftdi_read_bulk_callback(struct urb *urb) int status = urb->status; if (urb->number_of_packets > 0) { - err("%s transfer_buffer_length %d actual_length %d number of packets %d", - __func__, - urb->transfer_buffer_length, - urb->actual_length, urb->number_of_packets); - err("%s transfer_flags %x ", __func__, urb->transfer_flags); + dev_err(&port->dev, "%s transfer_buffer_length %d " + "actual_length %d number of packets %d\n", __func__, + urb->transfer_buffer_length, + urb->actual_length, urb->number_of_packets); + dev_err(&port->dev, "%s transfer_flags %x\n", __func__, + urb->transfer_flags); } dbg("%s - port %d", __func__, port->number); @@ -1808,7 +1816,7 @@ static void ftdi_read_bulk_callback(struct urb *urb) if (port->port.count <= 0) return; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (!tty) { dbg("%s - bad tty pointer - exiting", __func__); return; @@ -1817,17 +1825,17 @@ static void ftdi_read_bulk_callback(struct urb *urb) priv = usb_get_serial_port_data(port); if (!priv) { dbg("%s - bad port private data pointer - exiting", __func__); - return; + goto out; } if (urb != port->read_urb) - err("%s - Not my urb!", __func__); + dev_err(&port->dev, "%s - Not my urb!\n", __func__); if (status) { /* This will happen at close every time so it is a dbg not an err */ dbg("(this is ok on close) nonzero read bulk status received: %d", status); - return; + goto out; } /* count data bytes, but not status bytes */ @@ -1838,7 +1846,8 @@ static void ftdi_read_bulk_callback(struct urb *urb) spin_unlock_irqrestore(&priv->rx_lock, flags); ftdi_process_read(&priv->rx_work.work); - +out: + tty_kref_put(tty); } /* ftdi_read_bulk_callback */ @@ -1863,7 +1872,7 @@ static void ftdi_process_read(struct work_struct *work) if (port->port.count <= 0) return; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (!tty) { dbg("%s - bad tty pointer - exiting", __func__); return; @@ -1872,13 +1881,13 @@ static void ftdi_process_read(struct work_struct *work) priv = usb_get_serial_port_data(port); if (!priv) { dbg("%s - bad port private data pointer - exiting", __func__); - return; + goto out; } urb = port->read_urb; if (!urb) { dbg("%s - bad read_urb pointer - exiting", __func__); - return; + goto out; } data = urb->transfer_buffer; @@ -1923,7 +1932,8 @@ static void ftdi_process_read(struct work_struct *work) length = min(PKTSZ, urb->actual_length-packet_offset)-2; if (length < 0) { - err("%s - bad packet length: %d", __func__, length+2); + dev_err(&port->dev, "%s - bad packet length: %d\n", + __func__, length+2); length = 0; } @@ -2020,7 +2030,7 @@ static void ftdi_process_read(struct work_struct *work) schedule_delayed_work(&priv->rx_work, 1); else dbg("%s - port is closed", __func__); - return; + goto out; } /* urb is completely processed */ @@ -2038,9 +2048,12 @@ static void ftdi_process_read(struct work_struct *work) result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); } +out: + tty_kref_put(tty); } /* ftdi_process_read */ @@ -2066,8 +2079,8 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, buf, 0, WDR_TIMEOUT) < 0) { - err("%s FAILED to enable/disable break state (state was %d)", - __func__, break_state); + dev_err(&port->dev, "%s FAILED to enable/disable break state " + "(state was %d)\n", __func__, break_state); } dbg("%s break state is %d - urb is %d", __func__, @@ -2139,7 +2152,7 @@ static void ftdi_set_termios(struct tty_struct *tty, case CS7: urb_value |= 7; dbg("Setting CS7"); break; case CS8: urb_value |= 8; dbg("Setting CS8"); break; default: - err("CSIZE was set but not CS5-CS8"); + dev_err(&port->dev, "CSIZE was set but not CS5-CS8\n"); } } @@ -2152,7 +2165,8 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, buf, 0, WDR_SHORT_TIMEOUT) < 0) { - err("%s FAILED to set databits/stopbits/parity", __func__); + dev_err(&port->dev, "%s FAILED to set " + "databits/stopbits/parity\n", __func__); } /* Now do the baudrate */ @@ -2163,14 +2177,17 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { - err("%s error from disable flowcontrol urb", __func__); + dev_err(&port->dev, + "%s error from disable flowcontrol urb\n", + __func__); } /* Drop RTS and DTR */ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { /* set the baudrate determined before */ if (change_speed(tty, port)) - err("%s urb failed to set baudrate", __func__); + dev_err(&port->dev, "%s urb failed to set baudrate\n", + __func__); /* Ensure RTS and DTR are raised when baudrate changed from 0 */ if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) set_mctrl(port, TIOCM_DTR | TIOCM_RTS); @@ -2186,7 +2203,8 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), buf, 0, WDR_TIMEOUT) < 0) { - err("urb failed to set to rts/cts flow control"); + dev_err(&port->dev, + "urb failed to set to rts/cts flow control\n"); } } else { @@ -2217,7 +2235,8 @@ static void ftdi_set_termios(struct tty_struct *tty, urb_value , (FTDI_SIO_XON_XOFF_HS | priv->interface), buf, 0, WDR_TIMEOUT) < 0) { - err("urb failed to set to xon/xoff flow control"); + dev_err(&port->dev, "urb failed to set to " + "xon/xoff flow control\n"); } } else { /* else clause to only run if cflag ! CRTSCTS and iflag @@ -2230,7 +2249,8 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { - err("urb failed to clear flow control"); + dev_err(&port->dev, + "urb failed to clear flow control\n"); } } @@ -2256,7 +2276,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) 0, 0, buf, 1, WDR_TIMEOUT); if (ret < 0) { - err("%s Could not get modem status of device - err: %d", __func__, + dbg("%s Could not get modem status of device - err: %d", __func__, ret); return ret; } @@ -2275,7 +2295,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) 0, priv->interface, buf, 2, WDR_TIMEOUT); if (ret < 0) { - err("%s Could not get modem status of device - err: %d", __func__, + dbg("%s Could not get modem status of device - err: %d", __func__, ret); return ret; } @@ -2422,7 +2442,8 @@ static int __init ftdi_init(void) if (retval) goto failed_usb_register; - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&ftdi_sio_device); @@ -2455,5 +2476,5 @@ module_param(vendor, ushort, 0); MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" __MODULE_STRING(FTDI_VID)")"); module_param(product, ushort, 0); -MODULE_PARM_DESC(vendor, "User specified product ID"); +MODULE_PARM_DESC(product, "User specified product ID"); diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 8a5b6df3a976..07a3992abad2 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -628,6 +628,11 @@ #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ /* + * Oceanic product ids + */ +#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */ + +/* * TTi (Thurlby Thandar Instruments) */ #define TTI_VID 0x103E /* Vendor Id */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index d95382088075..8e6a66e38db2 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -276,7 +276,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf) static void send_to_tty(struct usb_serial_port *port, char *data, unsigned int actual_length) { - struct tty_struct *tty = port->port.tty; + struct tty_struct *tty = tty_port_tty_get(&port->port); if (tty && actual_length) { @@ -287,6 +287,7 @@ static void send_to_tty(struct usb_serial_port *port, tty_insert_flip_string(tty, data, actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); } @@ -1584,7 +1585,8 @@ static int __init garmin_init(void) retval = usb_register(&garmin_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index fe84c88ec20c..814909f1ee63 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -330,7 +330,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) static void flush_and_resubmit_read_urb(struct usb_serial_port *port) { struct urb *urb = port->read_urb; - struct tty_struct *tty = port->port.tty; + struct tty_struct *tty = tty_port_tty_get(&port->port); int room; /* Push data to tty */ @@ -341,6 +341,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) tty_flip_buffer_push(tty); } } + tty_kref_put(tty); resubmit_read_urb(port, GFP_ATOMIC); } diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index ab905869e959..431329275133 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -63,7 +63,8 @@ static int __init hp49gp_init(void) retval = usb_register(&hp49gp_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&hp49gp_device); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index bfa508ddb0fe..e85c8c0d1ad9 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -600,6 +600,7 @@ static void edge_interrupt_callback(struct urb *urb) struct edgeport_serial *edge_serial = urb->context; struct edgeport_port *edge_port; struct usb_serial_port *port; + struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; int bytes_avail; @@ -675,9 +676,12 @@ static void edge_interrupt_callback(struct urb *urb) /* tell the tty driver that something has changed */ - if (edge_port->port->port.tty) - tty_wakeup(edge_port->port->port.tty); - + tty = tty_port_tty_get( + &edge_port->port->port); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } /* Since we have more credit, check if more data can be sent */ send_more_port_data(edge_serial, @@ -778,13 +782,14 @@ static void edge_bulk_out_data_callback(struct urb *urb) __func__, status); } - tty = edge_port->port->port.tty; + tty = tty_port_tty_get(&edge_port->port->port); if (tty && edge_port->open) { /* let the tty driver wakeup if it has a special write_wakeup function */ tty_wakeup(tty); } + tty_kref_put(tty); /* Release the Write URB */ edge_port->write_in_progress = false; @@ -826,11 +831,12 @@ static void edge_bulk_out_cmd_callback(struct urb *urb) } /* Get pointer to tty */ - tty = edge_port->port->port.tty; + tty = tty_port_tty_get(&edge_port->port->port); /* tell the tty driver that something has changed */ if (tty && edge_port->open) tty_wakeup(tty); + tty_kref_put(tty); /* we have completed the command */ edge_port->commandPending = false; @@ -1932,11 +1938,13 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, edge_serial->rxPort]; edge_port = usb_get_serial_port_data(port); if (edge_port->open) { - tty = edge_port->port->port.tty; + tty = tty_port_tty_get( + &edge_port->port->port); if (tty) { dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort); edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); + tty_kref_put(tty); } edge_port->icount.rx += rxLen; } @@ -1971,6 +1979,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, { struct usb_serial_port *port; struct edgeport_port *edge_port; + struct tty_struct *tty; __u8 code = edge_serial->rxStatusCode; /* switch the port pointer to the one being currently talked about */ @@ -2020,10 +2029,12 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, /* send the current line settings to the port so we are in sync with any further termios calls */ - /* FIXME: locking on tty */ - if (edge_port->port->port.tty) - change_port_settings(edge_port->port->port.tty, - edge_port, edge_port->port->port.tty->termios); + tty = tty_port_tty_get(&edge_port->port->port); + if (tty) { + change_port_settings(tty, + edge_port, tty->termios); + tty_kref_put(tty); + } /* we have completed the open */ edge_port->openPending = false; @@ -2163,10 +2174,14 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, } /* Place LSR data byte into Rx buffer */ - if (lsrData && edge_port->port->port.tty) - edge_tty_recv(&edge_port->port->dev, - edge_port->port->port.tty, &data, 1); - + if (lsrData) { + struct tty_struct *tty = + tty_port_tty_get(&edge_port->port->port); + if (tty) { + edge_tty_recv(&edge_port->port->dev, tty, &data, 1); + tty_kref_put(tty); + } + } /* update input line counters */ icount = &edge_port->icount; if (newLsr & LSR_BREAK) @@ -3094,13 +3109,13 @@ static int edge_startup(struct usb_serial *serial) edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!edge_serial->interrupt_read_urb) { - err("out of memory"); + dev_err(&dev->dev, "out of memory\n"); return -ENOMEM; } edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->interrupt_in_buffer) { - err("out of memory"); + dev_err(&dev->dev, "out of memory\n"); usb_free_urb(edge_serial->interrupt_read_urb); return -ENOMEM; } @@ -3131,13 +3146,13 @@ static int edge_startup(struct usb_serial *serial) edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!edge_serial->read_urb) { - err("out of memory"); + dev_err(&dev->dev, "out of memory\n"); return -ENOMEM; } edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->bulk_in_buffer) { - err("out of memory"); + dev_err(&dev->dev, "out of memory\n"); usb_free_urb(edge_serial->read_urb); return -ENOMEM; } @@ -3166,7 +3181,8 @@ static int edge_startup(struct usb_serial *serial) } if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) { - err("Error - the proper endpoints were not found!"); + dev_err(&dev->dev, "Error - the proper endpoints " + "were not found!\n"); return -ENODEV; } @@ -3175,8 +3191,9 @@ static int edge_startup(struct usb_serial *serial) response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL); if (response) - err("%s - Error %d submitting control urb", - __func__, response); + dev_err(&dev->dev, + "%s - Error %d submitting control urb\n", + __func__, response); } return response; } @@ -3238,7 +3255,8 @@ static int __init edgeport_init(void) if (retval) goto failed_usb_register; atomic_set(&CmdUrbs, 0); - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index cb4c54316cf5..c3cdd00ddc41 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, int flush) { int baud_rate; - struct tty_struct *tty = port->port->port.tty; + struct tty_struct *tty = tty_port_tty_get(&port->port->port); wait_queue_t wait; unsigned long flags; @@ -599,6 +599,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, if (flush) edge_buf_clear(port->ep_out_buf); spin_unlock_irqrestore(&port->ep_lock, flags); + tty_kref_put(tty); /* wait for data to drain from the device */ timeout += jiffies; @@ -1554,7 +1555,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) /* Save the new modem status */ edge_port->shadow_msr = msr & 0xf0; - tty = edge_port->port->port.tty; + tty = tty_port_tty_get(&edge_port->port->port); /* handle CTS flow control */ if (tty && C_CRTSCTS(tty)) { if (msr & EDGEPORT_MSR_CTS) { @@ -1564,6 +1565,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) tty->hw_stopped = 1; } } + tty_kref_put(tty); return; } @@ -1574,6 +1576,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, struct async_icount *icount; __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); + struct tty_struct *tty; dbg("%s - %02x", __func__, new_lsr); @@ -1587,8 +1590,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); /* Place LSR data byte into Rx buffer */ - if (lsr_data && edge_port->port->port.tty) - edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1); + if (lsr_data) { + tty = tty_port_tty_get(&edge_port->port->port); + if (tty) { + edge_tty_recv(&edge_port->port->dev, tty, &data, 1); + tty_kref_put(tty); + } + } /* update input line counters */ icount = &edge_port->icount; @@ -1749,7 +1757,7 @@ static void edge_bulk_in_callback(struct urb *urb) ++data; } - tty = edge_port->port->port.tty; + tty = tty_port_tty_get(&edge_port->port->port); if (tty && urb->actual_length) { usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data); @@ -1761,6 +1769,7 @@ static void edge_bulk_in_callback(struct urb *urb) urb->actual_length); edge_port->icount.rx += urb->actual_length; } + tty_kref_put(tty); exit: /* continue read unless stopped */ @@ -1796,6 +1805,7 @@ static void edge_bulk_out_callback(struct urb *urb) struct usb_serial_port *port = urb->context; struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status = urb->status; + struct tty_struct *tty; dbg("%s - port %d", __func__, port->number); @@ -1818,7 +1828,9 @@ static void edge_bulk_out_callback(struct urb *urb) } /* send any buffered data */ - edge_send(port->port.tty); + tty = tty_port_tty_get(&port->port); + edge_send(tty); + tty_kref_put(tty); } static int edge_open(struct tty_struct *tty, @@ -1876,7 +1888,7 @@ static int edge_open(struct tty_struct *tty, /* set up the port settings */ if (tty) - edge_set_termios(tty, port, port->port.tty->termios); + edge_set_termios(tty, port, tty->termios); /* open up the port */ @@ -2966,7 +2978,8 @@ static int __init edgeport_init(void) retval = usb_register(&io_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&edgeport_2port_device); diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index cd9a2e138c8b..132be74d2b89 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -608,7 +608,7 @@ static int ipaq_open(struct tty_struct *tty, bytes_out = 0; priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL); if (priv == NULL) { - err("%s - Out of memory", __func__); + dev_err(&port->dev, "%s - Out of memory\n", __func__); return -ENOMEM; } usb_set_serial_port_data(port, priv); @@ -693,8 +693,7 @@ static int ipaq_open(struct tty_struct *tty, } if (!retries && result) { - err("%s - failed doing control urb, error %d", __func__, - result); + dev_err(&port->dev, "%s - failed doing control urb, error %d\n", __func__, result); goto error; } @@ -707,8 +706,9 @@ static int ipaq_open(struct tty_struct *tty, result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) { - err("%s - failed submitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); goto error; } @@ -716,7 +716,7 @@ static int ipaq_open(struct tty_struct *tty, enomem: result = -ENOMEM; - err("%s - Out of memory", __func__); + dev_err(&port->dev, "%s - Out of memory\n", __func__); error: ipaq_destroy_lists(port); kfree(priv); @@ -764,13 +764,14 @@ static void ipaq_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); bytes_in += urb->actual_length; } + tty_kref_put(tty); /* Continue trying to always read */ usb_fill_bulk_urb(port->read_urb, port->serial->dev, @@ -780,8 +781,9 @@ static void ipaq_read_bulk_callback(struct urb *urb) ipaq_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); return; } @@ -846,7 +848,8 @@ static int ipaq_write_bulk(struct usb_serial_port *port, spin_unlock_irqrestore(&write_list_lock, flags); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) - err("%s - failed submitting write urb, error %d", + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", __func__, result); } else { spin_unlock_irqrestore(&write_list_lock, flags); @@ -908,8 +911,9 @@ static void ipaq_write_bulk_callback(struct urb *urb) spin_unlock_irqrestore(&write_list_lock, flags); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); } else { priv->active = 0; spin_unlock_irqrestore(&write_list_lock, flags); @@ -956,7 +960,7 @@ static int ipaq_startup(struct usb_serial *serial) { dbg("%s", __func__); if (serial->dev->actconfig->desc.bConfigurationValue != 1) { - err("active config #%d != 1 ??", + dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } @@ -975,7 +979,6 @@ static int __init ipaq_init(void) retval = usb_serial_register(&ipaq_device); if (retval) goto failed_usb_serial_register; - info(DRIVER_DESC " " DRIVER_VERSION); if (vendor) { ipaq_id_table[0].idVendor = vendor; ipaq_id_table[0].idProduct = product; @@ -984,6 +987,8 @@ static int __init ipaq_init(void) if (retval) goto failed_usb_register; + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&ipaq_device); diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index a842025b9b57..3ac59a8a980f 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -170,12 +170,13 @@ static void ipw_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* Continue trying to always read */ usb_fill_bulk_urb(port->read_urb, port->serial->dev, @@ -484,7 +485,8 @@ static int usb_ipw_init(void) usb_serial_deregister(&ipw_device); return retval; } - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; } diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index e59155c6607d..b679a556b98d 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -465,11 +465,12 @@ static void ir_read_bulk_callback(struct urb *urb) ir_baud = *data & 0x0f; usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty_buffer_request_room(tty, urb->actual_length - 1)) { tty_insert_flip_string(tty, data+1, urb->actual_length - 1); tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* * No break here. @@ -601,7 +602,8 @@ static int __init ir_init(void) if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index ddff37fa6339..e320972cb227 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -629,13 +629,14 @@ static void read_buf_callback(struct urb *urb) } dbg("%s - %i chars to write", __func__, urb->actual_length); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (data == NULL) dbg("%s - data is NULL !!!", __func__); if (tty && urb->actual_length && data) { tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); iuu_led_activity_on(urb); } @@ -1184,7 +1185,8 @@ static int __init iuu_init(void) retval = usb_register(&iuu_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&iuu_device); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 704716f6f6d3..9878c0fb3859 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -217,7 +217,8 @@ static int __init keyspan_init(void) if (retval) goto failed_usb_register; - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: @@ -430,7 +431,7 @@ static void usa26_indat_callback(struct urb *urb) } port = urb->context; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { @@ -459,6 +460,7 @@ static void usa26_indat_callback(struct urb *urb) } tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; @@ -513,6 +515,7 @@ static void usa26_instat_callback(struct urb *urb) struct usb_serial *serial; struct usb_serial_port *port; struct keyspan_port_private *p_priv; + struct tty_struct *tty; int old_dcd_state, err; int status = urb->status; @@ -553,12 +556,11 @@ static void usa26_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) - && old_dcd_state != p_priv->dcd_state) { - if (old_dcd_state) - tty_hangup(port->port.tty); - /* else */ - /* wake_up_interruptible(&p_priv->open_wait); */ + if (old_dcd_state != p_priv->dcd_state) { + tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); + tty_kref_put(tty); } /* Resubmit urb so we continue receiving */ @@ -604,11 +606,12 @@ static void usa28_indat_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); data = urb->transfer_buffer; - tty = port->port.tty; - if (urb->actual_length) { + tty =tty_port_tty_get(&port->port); + if (tty && urb->actual_length) { tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; @@ -652,6 +655,7 @@ static void usa28_instat_callback(struct urb *urb) struct usb_serial *serial; struct usb_serial_port *port; struct keyspan_port_private *p_priv; + struct tty_struct *tty; int old_dcd_state; int status = urb->status; @@ -689,12 +693,11 @@ static void usa28_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) - && old_dcd_state != p_priv->dcd_state) { - if (old_dcd_state) - tty_hangup(port->port.tty); - /* else */ - /* wake_up_interruptible(&p_priv->open_wait); */ + if( old_dcd_state != p_priv->dcd_state && old_dcd_state) { + tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); + tty_kref_put(tty); } /* Resubmit urb so we continue receiving */ @@ -785,12 +788,11 @@ static void usa49_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) - && old_dcd_state != p_priv->dcd_state) { - if (old_dcd_state) - tty_hangup(port->port.tty); - /* else */ - /* wake_up_interruptible(&p_priv->open_wait); */ + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); + tty_kref_put(tty); } /* Resubmit urb so we continue receiving */ @@ -827,7 +829,7 @@ static void usa49_indat_callback(struct urb *urb) } port = urb->context; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { @@ -850,6 +852,7 @@ static void usa49_indat_callback(struct urb *urb) } tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; @@ -893,7 +896,7 @@ static void usa49wg_indat_callback(struct urb *urb) return; } port = serial->port[data[i++]]; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); len = data[i++]; /* 0x80 bit is error flag */ @@ -927,6 +930,7 @@ static void usa49wg_indat_callback(struct urb *urb) } if (port->port.count) tty_flip_buffer_push(tty); + tty_kref_put(tty); } } @@ -967,8 +971,8 @@ static void usa90_indat_callback(struct urb *urb) port = urb->context; p_priv = usb_get_serial_port_data(port); - tty = port->port.tty; if (urb->actual_length) { + tty = tty_port_tty_get(&port->port); /* if current mode is DMA, looks like usa28 format otherwise looks like usa26 data format */ @@ -1004,6 +1008,7 @@ static void usa90_indat_callback(struct urb *urb) } } tty_flip_buffer_push(tty); + tty_kref_put(tty); } /* Resubmit urb so we continue receiving */ @@ -1025,6 +1030,7 @@ static void usa90_instat_callback(struct urb *urb) struct usb_serial *serial; struct usb_serial_port *port; struct keyspan_port_private *p_priv; + struct tty_struct *tty; int old_dcd_state, err; int status = urb->status; @@ -1053,12 +1059,11 @@ static void usa90_instat_callback(struct urb *urb) p_priv->dcd_state = ((msg->dcd) ? 1 : 0); p_priv->ri_state = ((msg->ri) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) - && old_dcd_state != p_priv->dcd_state) { - if (old_dcd_state) - tty_hangup(port->port.tty); - /* else */ - /* wake_up_interruptible(&p_priv->open_wait); */ + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { + tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); + tty_kref_put(tty); } /* Resubmit urb so we continue receiving */ @@ -1130,12 +1135,11 @@ static void usa67_instat_callback(struct urb *urb) p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) - && old_dcd_state != p_priv->dcd_state) { - if (old_dcd_state) - tty_hangup(port->port.tty); - /* else */ - /* wake_up_interruptible(&p_priv->open_wait); */ + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); + tty_kref_put(tty); } /* Resubmit urb so we continue receiving */ @@ -1332,7 +1336,7 @@ static void keyspan_close(struct tty_struct *tty, stop_urb(p_priv->out_urbs[i]); } } - port->port.tty = NULL; + tty_port_tty_set(&port->port, NULL); } /* download the firmware to a pre-renumeration device */ diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 040040a267d9..bf1ae247da66 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -172,8 +172,9 @@ static void keyspan_pda_wakeup_write(struct work_struct *work) struct keyspan_pda_private *priv = container_of(work, struct keyspan_pda_private, wakeup_work); struct usb_serial_port *port = priv->port; - - tty_wakeup(port->port.tty); + struct tty_struct *tty = tty_port_tty_get(&port->port); + tty_wakeup(tty); + tty_kref_put(tty); } static void keyspan_pda_request_unthrottle(struct work_struct *work) @@ -205,7 +206,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) static void keyspan_pda_rx_interrupt(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty = port->port.tty; + struct tty_struct *tty = tty_port_tty_get(&port->port); unsigned char *data = urb->transfer_buffer; int retval; int status = urb->status; @@ -222,7 +223,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, status); - return; + goto out; default: dbg("%s - nonzero urb status received: %d", __func__, status); @@ -261,8 +262,11 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err("%s - usb_submit_urb failed with result %d", - __func__, retval); + dev_err(&port->dev, + "%s - usb_submit_urb failed with result %d", + __func__, retval); +out: + tty_kref_put(tty); } @@ -738,11 +742,13 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) fw_name = "keyspan_pda/xircom_pgs.fw"; #endif else { - err("%s: unknown vendor, aborting.", __func__); + dev_err(&serial->dev->dev, "%s: unknown vendor, aborting.\n", + __func__); return -ENODEV; } if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { - err("failed to load firmware \"%s\"\n", fw_name); + dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n", + fw_name); return -ENOENT; } record = (const struct ihex_binrec *)fw->data; @@ -752,10 +758,10 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { - err("ezusb_writememory failed for Keyspan PDA " - "firmware (%d %04X %p %d)", - response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); + dev_err(&serial->dev->dev, "ezusb_writememory failed " + "for Keyspan PDA firmware (%d %04X %p %d)\n", + response, be32_to_cpu(record->addr), + record->data, be16_to_cpu(record->len)); break; } record = ihex_next_binrec(record); @@ -870,7 +876,8 @@ static int __init keyspan_pda_init(void) retval = usb_register(&keyspan_pda_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: #ifdef XIRCOM diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index b84dddc71124..dc36a052766f 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -182,12 +182,12 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port, sizeof(struct klsi_105_port_settings), KLSI_TIMEOUT); if (rc < 0) - err("Change port settings failed (error = %d)", rc); - info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d", - __func__, - settings->pktlen, - settings->baudrate, settings->databits, - settings->unknown1, settings->unknown2); + dev_err(&port->dev, + "Change port settings failed (error = %d)\n", rc); + dev_info(&port->serial->dev->dev, + "%d byte block, baudrate %x, databits %d, u1 %d, u2 %d\n", + settings->pktlen, settings->baudrate, settings->databits, + settings->unknown1, settings->unknown2); return rc; } /* klsi_105_chg_port_settings */ @@ -215,7 +215,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; __u16 status; - info("%s - sending SIO Poll request", __func__); + dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), KL5KUSB105A_SIO_POLL, @@ -226,12 +226,13 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, 10000 ); if (rc < 0) - err("Reading line status failed (error = %d)", rc); + dev_err(&port->dev, "Reading line status failed (error = %d)\n", + rc); else { status = get_unaligned_le16(status_buf); - info("%s - read status %x %x", __func__, - status_buf[0], status_buf[1]); + dev_info(&port->serial->dev->dev, "read status %x %x", + status_buf[0], status_buf[1]); *line_state_p = klsi_105_status2linestate(status); } @@ -280,15 +281,16 @@ static int klsi_105_startup(struct usb_serial *serial) priv->write_urb_pool[j] = urb; if (urb == NULL) { - err("No more urbs???"); + dev_err(&serial->dev->dev, "No more urbs???\n"); goto err_cleanup; } urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (!urb->transfer_buffer) { - err("%s - out of memory for urb buffers.", - __func__); + dev_err(&serial->dev->dev, + "%s - out of memory for urb buffers.\n", + __func__); goto err_cleanup; } } @@ -409,7 +411,8 @@ static int klsi_105_open(struct tty_struct *tty, rc = usb_submit_urb(port->read_urb, GFP_KERNEL); if (rc) { - err("%s - failed submitting read urb, error %d", __func__, rc); + dev_err(&port->dev, "%s - failed submitting read urb, " + "error %d\n", __func__, rc); retval = rc; goto exit; } @@ -424,7 +427,7 @@ static int klsi_105_open(struct tty_struct *tty, 0, KLSI_TIMEOUT); if (rc < 0) { - err("Enabling read failed (error = %d)", rc); + dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc); retval = rc; } else dbg("%s - enabled reading", __func__); @@ -464,7 +467,8 @@ static void klsi_105_close(struct tty_struct *tty, NULL, 0, KLSI_TIMEOUT); if (rc < 0) - err("Disabling read failed (error = %d)", rc); + dev_err(&port->dev, + "Disabling read failed (error = %d)\n", rc); } mutex_unlock(&port->serial->disc_mutex); @@ -475,8 +479,9 @@ static void klsi_105_close(struct tty_struct *tty, /* FIXME */ /* wgg - do I need this? I think so. */ usb_kill_urb(port->interrupt_in_urb); - info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", - priv->bytes_in, priv->bytes_out); + dev_info(&port->serial->dev->dev, + "port stats: %ld bytes in, %ld bytes out\n", + priv->bytes_in, priv->bytes_out); } /* klsi_105_close */ @@ -522,7 +527,9 @@ static int klsi_105_write(struct tty_struct *tty, urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); if (urb->transfer_buffer == NULL) { - err("%s - no more kernel memory...", __func__); + dev_err(&port->dev, + "%s - no more kernel memory...\n", + __func__); goto exit; } } @@ -549,8 +556,9 @@ static int klsi_105_write(struct tty_struct *tty, /* send the data out the bulk port */ result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); goto exit; } buf += size; @@ -658,7 +666,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb) } else { int bytes_sent = ((__u8 *) data)[0] + ((unsigned int) ((__u8 *) data)[1] << 8); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); /* we should immediately resubmit the URB, before attempting * to pass the data on to the tty layer. But that needs locking * against re-entry an then mixed-up data because of @@ -679,6 +687,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb) tty_buffer_request_room(tty, bytes_sent); tty_insert_flip_string(tty, data + 2, bytes_sent); tty_flip_buffer_push(tty); + tty_kref_put(tty); /* again lockless, but debug info only */ priv->bytes_in += bytes_sent; @@ -693,8 +702,9 @@ static void klsi_105_read_bulk_callback(struct urb *urb) port); rc = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (rc) - err("%s - failed resubmitting read urb, error %d", - __func__, rc); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, rc); } /* klsi_105_read_bulk_callback */ @@ -798,7 +808,8 @@ static void klsi_105_set_termios(struct tty_struct *tty, priv->cfg.databits = kl5kusb105a_dtb_8; break; default: - err("CSIZE was not CS5-CS8, using default of 8"); + dev_err(&port->dev, + "CSIZE was not CS5-CS8, using default of 8\n"); priv->cfg.databits = kl5kusb105a_dtb_8; break; } @@ -885,7 +896,8 @@ static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) rc = klsi_105_get_line_state(port, &line_state); if (rc < 0) { - err("Reading line control failed (error = %d)", rc); + dev_err(&port->dev, + "Reading line control failed (error = %d)\n", rc); /* better return value? EAGAIN? */ return rc; } @@ -943,8 +955,9 @@ static void klsi_105_unthrottle(struct tty_struct *tty) port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed submitting read urb, error %d", __func__, - result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); } @@ -959,7 +972,8 @@ static int __init klsi_105_init(void) if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&kl5kusb105d_device); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index deba28ec77e8..6286baad9392 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -383,7 +383,7 @@ static void kobil_read_int_callback(struct urb *urb) return; } - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (urb->actual_length) { /* BEGIN DEBUG */ @@ -405,6 +405,7 @@ static void kobil_read_int_callback(struct urb *urb) tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* someone sets the dev to 0 if the close method has been called */ port->interrupt_in_urb->dev = port->serial->dev; @@ -743,8 +744,8 @@ static int __init kobil_init(void) if (retval) goto failed_usb_register; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 0ded8bd6ec85..07710cf31d0d 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -246,7 +246,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, WDR_TIMEOUT); if (rc < 0) /*FIXME: What value speed results */ - err("Set BAUD RATE %d failed (error = %d)", value, rc); + dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n", + value, rc); else tty_encode_baud_rate(tty, speed, speed); dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); @@ -274,8 +275,9 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, WDR_TIMEOUT); if (rc < 0) - err("Sending USB device request code %d failed (error = %d)", - MCT_U232_SET_UNKNOWN1_REQUEST, rc); + dev_err(&port->dev, "Sending USB device request code %d " + "failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST, + rc); if (port && C_CRTSCTS(tty)) cts_enable_byte = 1; @@ -288,8 +290,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, WDR_TIMEOUT); if (rc < 0) - err("Sending USB device request code %d failed (error = %d)", - MCT_U232_SET_CTS_REQUEST, rc); + dev_err(&port->dev, "Sending USB device request code %d " + "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc); return rc; } /* mct_u232_set_baud_rate */ @@ -303,7 +305,8 @@ static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, WDR_TIMEOUT); if (rc < 0) - err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc); + dev_err(&serial->dev->dev, + "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc); dbg("set_line_ctrl: 0x%x", lcr); return rc; } /* mct_u232_set_line_ctrl */ @@ -325,7 +328,8 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, WDR_TIMEOUT); if (rc < 0) - err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc); + dev_err(&serial->dev->dev, + "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); return rc; @@ -341,7 +345,8 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial, 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, WDR_TIMEOUT); if (rc < 0) { - err("Get MODEM STATus failed (error = %d)", rc); + dev_err(&serial->dev->dev, + "Get MODEM STATus failed (error = %d)\n", rc); *msr = 0; } dbg("get_modem_stat: 0x%x", *msr); @@ -470,8 +475,9 @@ static int mct_u232_open(struct tty_struct *tty, port->read_urb->dev = port->serial->dev; retval = usb_submit_urb(port->read_urb, GFP_KERNEL); if (retval) { - err("usb_submit_urb(read bulk) failed pipe 0x%x err %d", - port->read_urb->pipe, retval); + dev_err(&port->dev, + "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n", + port->read_urb->pipe, retval); goto error; } @@ -479,8 +485,9 @@ static int mct_u232_open(struct tty_struct *tty, retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (retval) { usb_kill_urb(port->read_urb); - err(" usb_submit_urb(read int) failed pipe 0x%x err %d", - port->interrupt_in_urb->pipe, retval); + dev_err(&port->dev, + "usb_submit_urb(read int) failed pipe 0x%x err %d", + port->interrupt_in_urb->pipe, retval); goto error; } return 0; @@ -563,10 +570,11 @@ static void mct_u232_read_int_callback(struct urb *urb) * Work-a-round: handle the 'usual' bulk-in pipe here */ if (urb->transfer_buffer_length > 2) { - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (urb->actual_length) { tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); + tty_kref_put(tty); } goto exit; } @@ -591,7 +599,7 @@ static void mct_u232_read_int_callback(struct urb *urb) * to look in to this before committing any code. */ if (priv->last_lsr & MCT_U232_LSR_ERR) { - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); /* Overrun Error */ if (priv->last_lsr & MCT_U232_LSR_OE) { } @@ -604,14 +612,16 @@ static void mct_u232_read_int_callback(struct urb *urb) /* Break Indicator */ if (priv->last_lsr & MCT_U232_LSR_BI) { } + tty_kref_put(tty); } #endif spin_unlock_irqrestore(&priv->lock, flags); exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err("%s - usb_submit_urb failed with result %d", - __func__, retval); + dev_err(&port->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, retval); } /* mct_u232_read_int_callback */ static void mct_u232_set_termios(struct tty_struct *tty, @@ -678,7 +688,8 @@ static void mct_u232_set_termios(struct tty_struct *tty, case CS8: last_lcr |= MCT_U232_DATA_BITS_8; break; default: - err("CSIZE was not CS5-CS8, using default of 8"); + dev_err(&port->dev, + "CSIZE was not CS5-CS8, using default of 8\n"); last_lcr |= MCT_U232_DATA_BITS_8; break; } @@ -815,7 +826,8 @@ static int __init mct_u232_init(void) retval = usb_register(&mct_u232_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&mct_u232_device); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 7c4917d77c0a..e772cc0a97fd 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -216,12 +216,13 @@ static void mos7720_bulk_in_callback(struct urb *urb) data = urb->transfer_buffer; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); if (!port->read_urb) { dbg("URB KILLED !!!"); @@ -262,10 +263,11 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) dbg("Entering ........."); - tty = mos7720_port->port->port.tty; + tty = tty_port_tty_get(&mos7720_port->port->port); if (tty && mos7720_port->open) tty_wakeup(tty); + tty_kref_put(tty); } /* @@ -353,14 +355,16 @@ static int mos7720_open(struct tty_struct *tty, mos7720_port->write_urb_pool[j] = urb; if (urb == NULL) { - err("No more urbs???"); + dev_err(&port->dev, "No more urbs???\n"); continue; } urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (!urb->transfer_buffer) { - err("%s-out of memory for urb buffers.", __func__); + dev_err(&port->dev, + "%s-out of memory for urb buffers.\n", + __func__); usb_free_urb(mos7720_port->write_urb_pool[j]); mos7720_port->write_urb_pool[j] = NULL; continue; @@ -692,7 +696,8 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { - err("%s no more kernel memory...", __func__); + dev_err(&port->dev, "%s no more kernel memory...\n", + __func__); goto exit; } } @@ -712,8 +717,8 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - err("%s - usb_submit_urb(write bulk) failed with status = %d", - __func__, status); + dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + "with status = %d\n", __func__, status); bytes_sent = status; goto exit; } @@ -973,7 +978,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, /* Calculate the Divisor */ status = calc_baud_rate_divisor(baudrate, &divisor); if (status) { - err("%s - bad baud rate", __func__); + dev_err(&port->dev, "%s - bad baud rate\n", __func__); return status; } @@ -1267,29 +1272,6 @@ static int get_lsr_info(struct tty_struct *tty, return 0; } -/* - * get_number_bytes_avail - get number of bytes available - * - * Purpose: Let user call ioctl to get the count of number of bytes available. - */ -static int get_number_bytes_avail(struct moschip_port *mos7720_port, - unsigned int __user *value) -{ - unsigned int result = 0; - struct tty_struct *tty = mos7720_port->port->port.tty; - - if (!tty) - return -ENOIOCTLCMD; - - result = tty->read_cnt; - - dbg("%s(%d) = %d", __func__, mos7720_port->port->number, result); - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - - return -ENOIOCTLCMD; -} - static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, unsigned int __user *value) { @@ -1409,13 +1391,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file, dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); switch (cmd) { - case TIOCINQ: - /* return number of bytes available */ - dbg("%s (%d) TIOCINQ", __func__, port->number); - return get_number_bytes_avail(mos7720_port, - (unsigned int __user *)arg); - break; - case TIOCSERGETLSR: dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); return get_lsr_info(tty, mos7720_port, @@ -1506,7 +1481,7 @@ static int mos7720_startup(struct usb_serial *serial) /* create our private serial structure */ mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL); if (mos7720_serial == NULL) { - err("%s - Out of memory", __func__); + dev_err(&dev->dev, "%s - Out of memory\n", __func__); return -ENOMEM; } @@ -1519,7 +1494,7 @@ static int mos7720_startup(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); if (mos7720_port == NULL) { - err("%s - Out of memory", __func__); + dev_err(&dev->dev, "%s - Out of memory\n", __func__); usb_set_serial_data(serial, NULL); kfree(mos7720_serial); return -ENOMEM; @@ -1613,7 +1588,8 @@ static int __init moschip7720_init(void) if (retval) goto failed_port_device_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); /* Register with the usb */ retval = usb_register(&usb_driver); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 09d82062b973..fda4a6421c44 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -709,12 +709,13 @@ static void mos7840_bulk_in_callback(struct urb *urb) dbg("%s", "Entering ........... \n"); if (urb->actual_length) { - tty = mos7840_port->port->port.tty; + tty = tty_port_tty_get(&mos7840_port->port->port); if (tty) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); dbg(" %s \n", data); tty_flip_buffer_push(tty); + tty_kref_put(tty); } mos7840_port->icount.rx += urb->actual_length; smp_wmb(); @@ -773,10 +774,10 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) dbg("%s \n", "Entering ........."); - tty = mos7840_port->port->port.tty; - + tty = tty_port_tty_get(&mos7840_port->port->port); if (tty && mos7840_port->open) tty_wakeup(tty); + tty_kref_put(tty); } @@ -843,7 +844,7 @@ static int mos7840_open(struct tty_struct *tty, mos7840_port->write_urb_pool[j] = urb; if (urb == NULL) { - err("No more urbs???"); + dev_err(&port->dev, "No more urbs???\n"); continue; } @@ -852,7 +853,9 @@ static int mos7840_open(struct tty_struct *tty, if (!urb->transfer_buffer) { usb_free_urb(urb); mos7840_port->write_urb_pool[j] = NULL; - err("%s-out of memory for urb buffers.", __func__); + dev_err(&port->dev, + "%s-out of memory for urb buffers.\n", + __func__); continue; } } @@ -1020,8 +1023,8 @@ static int mos7840_open(struct tty_struct *tty, usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); if (response) { - err("%s - Error %d submitting interrupt urb", - __func__, response); + dev_err(&port->dev, "%s - Error %d submitting " + "interrupt urb\n", __func__, response); } } @@ -1054,8 +1057,8 @@ static int mos7840_open(struct tty_struct *tty, port->bulk_in_endpointAddress); response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); if (response) { - err("%s - Error %d submitting control urb", __func__, - response); + dev_err(&port->dev, "%s - Error %d submitting control urb\n", + __func__, response); } /* initialize our wait queues */ @@ -1491,7 +1494,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { - err("%s no more kernel memory...", __func__); + dev_err(&port->dev, "%s no more kernel memory...\n", + __func__); goto exit; } } @@ -1516,8 +1520,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, if (status) { mos7840_port->busy[i] = 0; - err("%s - usb_submit_urb(write bulk) failed with status = %d", - __func__, status); + dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + "with status = %d\n", __func__, status); bytes_sent = status; goto exit; } @@ -1855,8 +1859,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, /* Calculate the Divisor */ if (status) { - err("%s - bad baud rate", __func__); - dbg("%s\n", "bad baud rate"); + dev_err(&port->dev, "%s - bad baud rate\n", __func__); return status; } /* Enable access to divisor latch */ @@ -2445,7 +2448,7 @@ static int mos7840_startup(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); if (mos7840_port == NULL) { - err("%s - Out of memory", __func__); + dev_err(&dev->dev, "%s - Out of memory\n", __func__); status = -ENOMEM; i--; /* don't follow NULL pointer cleaning up */ goto error; @@ -2742,7 +2745,8 @@ static int __init moschip7840_init(void) goto failed_port_device_register; dbg("%s\n", "Entring..."); - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); /* Register with the usb */ retval = usb_register(&io_driver); diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index d6736531a0fa..bcdcbb822705 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -64,12 +64,13 @@ static void navman_read_int_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); exit: result = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index ae8e227f3db2..df6539712726 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -154,8 +154,8 @@ static int omninet_attach(struct usb_serial *serial) od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); if (!od) { - err("%s- kmalloc(%Zd) failed.", - __func__, sizeof(struct omninet_data)); + dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", + __func__, sizeof(struct omninet_data)); return -ENOMEM; } usb_set_serial_port_data(port, od); @@ -172,7 +172,7 @@ static int omninet_open(struct tty_struct *tty, dbg("%s - port %d", __func__, port->number); wport = serial->port[1]; - wport->port.tty = tty; /* FIXME */ + tty_port_tty_set(&wport->port, tty); /* Start reading from the device */ usb_fill_bulk_urb(port->read_urb, serial->dev, @@ -183,8 +183,9 @@ static int omninet_open(struct tty_struct *tty, omninet_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) - err("%s - failed submitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); return result; } @@ -229,9 +230,11 @@ static void omninet_read_bulk_callback(struct urb *urb) } if (urb->actual_length && header->oh_len) { - tty_insert_flip_string(port->port.tty, - data + OMNINET_DATAOFFSET, header->oh_len); - tty_flip_buffer_push(port->port.tty); + struct tty_struct *tty = tty_port_tty_get(&port->port); + tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET, + header->oh_len); + tty_flip_buffer_push(tty); + tty_kref_put(tty); } /* Continue trying to always read */ @@ -242,8 +245,9 @@ static void omninet_read_bulk_callback(struct urb *urb) omninet_read_bulk_callback, port); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); return; } @@ -296,8 +300,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); if (result) { wport->write_urb_busy = 0; - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); } else result = count; @@ -362,7 +367,8 @@ static int __init omninet_init(void) retval = usb_register(&omninet_driver); if (retval) goto failed_usb_register; - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&zyxel_omninet_device); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 73f8277f88f2..3d87eabcd922 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -79,27 +79,16 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define OPTION_PRODUCT_VIPER 0x6600 #define OPTION_PRODUCT_VIPER_BUS 0x6601 #define OPTION_PRODUCT_GT_MAX_READY 0x6701 -#define OPTION_PRODUCT_GT_MAX 0x6711 #define OPTION_PRODUCT_FUJI_MODEM_LIGHT 0x6721 #define OPTION_PRODUCT_FUJI_MODEM_GT 0x6741 #define OPTION_PRODUCT_FUJI_MODEM_EX 0x6761 -#define OPTION_PRODUCT_FUJI_NETWORK_LIGHT 0x6731 -#define OPTION_PRODUCT_FUJI_NETWORK_GT 0x6751 -#define OPTION_PRODUCT_FUJI_NETWORK_EX 0x6771 #define OPTION_PRODUCT_KOI_MODEM 0x6800 -#define OPTION_PRODUCT_KOI_NETWORK 0x6811 #define OPTION_PRODUCT_SCORPION_MODEM 0x6901 -#define OPTION_PRODUCT_SCORPION_NETWORK 0x6911 #define OPTION_PRODUCT_ETNA_MODEM 0x7001 -#define OPTION_PRODUCT_ETNA_NETWORK 0x7011 #define OPTION_PRODUCT_ETNA_MODEM_LITE 0x7021 #define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041 #define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061 -#define OPTION_PRODUCT_ETNA_NETWORK_LITE 0x7031 -#define OPTION_PRODUCT_ETNA_NETWORK_GT 0x7051 -#define OPTION_PRODUCT_ETNA_NETWORK_EX 0x7071 #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 -#define OPTION_PRODUCT_ETNA_KOI_NETWORK 0x7111 #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E600 0x1001 @@ -220,6 +209,16 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_CDMA_TECH 0xfffe +/* Ericsson products */ +#define ERICSSON_VENDOR_ID 0x0bdb +#define ERICSSON_PRODUCT_F3507G 0x1900 + +/* Pantech products */ +#define PANTECH_VENDOR_ID 0x106c +#define PANTECH_PRODUCT_PC5740 0x3701 +#define PANTECH_PRODUCT_PC5750 0x3702 /* PX-500 */ +#define PANTECH_PRODUCT_UM150 0x3711 + static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -235,27 +234,16 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, @@ -318,7 +306,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ - { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, + { USB_DEVICE(DELL_VENDOR_ID, 0x8147) }, /* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */ + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, @@ -349,6 +338,10 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, + { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) }, + { USB_DEVICE(PANTECH_VENDOR_ID, PANTECH_PRODUCT_PC5740) }, + { USB_DEVICE(PANTECH_VENDOR_ID, PANTECH_PRODUCT_PC5750) }, + { USB_DEVICE(PANTECH_VENDOR_ID, PANTECH_PRODUCT_UM150) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); @@ -427,7 +420,8 @@ static int __init option_init(void) if (retval) goto failed_driver_register; - info(DRIVER_DESC ": " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; @@ -571,14 +565,14 @@ static void option_indat_callback(struct urb *urb) dbg("%s: nonzero status: %d on endpoint %02x.", __func__, status, endpoint); } else { - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); - } else { + } else dbg("%s: empty read urb received", __func__); - } + tty_kref_put(tty); /* Resubmit urb so we continue receiving */ if (port->port.count && status != -ESHUTDOWN) { @@ -647,9 +641,13 @@ static void option_instat_callback(struct urb *urb) portdata->dsr_state = ((signals & 0x02) ? 1 : 0); portdata->ri_state = ((signals & 0x08) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) && - old_dcd_state && !portdata->dcd_state) - tty_hangup(port->port.tty); + if (old_dcd_state && !portdata->dcd_state) { + struct tty_struct *tty = + tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); + tty_kref_put(tty); + } } else { dbg("%s: type %x req %x", __func__, req_pkt->bRequestType, req_pkt->bRequest); @@ -793,7 +791,7 @@ static void option_close(struct tty_struct *tty, for (i = 0; i < N_OUT_URB; i++) usb_kill_urb(portdata->out_urbs[i]); } - port->port.tty = NULL; /* FIXME */ + tty_port_tty_set(&port->port, NULL); } /* Helper functions used by option_setup_urbs */ diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 81db5715ee25..ba551f00f16f 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -224,10 +224,6 @@ struct oti6858_private { struct usb_serial_port *port; /* USB port with which associated */ }; -#undef dbg -/* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */ -#define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg) - static void setup_line(struct work_struct *work) { struct oti6858_private *priv = container_of(work, @@ -1002,11 +998,12 @@ static void oti6858_read_bulk_callback(struct urb *urb) return; } - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty != NULL && urb->actual_length > 0) { tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* schedule the interrupt urb if we are still open */ if (port->port.count != 0) { diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1ede1441cb1b..491c8857b644 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -154,7 +154,6 @@ struct pl2303_private { wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; - u8 termios_initialized; enum pl2303_type type; }; @@ -526,16 +525,6 @@ static void pl2303_set_termios(struct tty_struct *tty, dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); - if (!priv->termios_initialized) { - *(tty->termios) = tty_std_termios; - tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty->termios->c_ispeed = 9600; - tty->termios->c_ospeed = 9600; - priv->termios_initialized = 1; - } - spin_unlock_irqrestore(&priv->lock, flags); - /* The PL2303 is reported to lose bytes if you change serial settings even to the same values as before. Thus we actually need to filter in this specific case */ @@ -1057,7 +1046,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) tty_flag = TTY_FRAME; dbg("%s - tty_flag = %d", __func__, tty_flag); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ @@ -1067,7 +1056,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) tty_insert_flip_char(tty, data[i], tty_flag); tty_flip_buffer_push(tty); } - + tty_kref_put(tty); /* Schedule the next read _if_ we are still open */ if (port->port.count) { urb->dev = port->serial->dev; @@ -1158,7 +1147,7 @@ static int __init pl2303_init(void) retval = usb_register(&pl2303_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&pl2303_device); diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index def52d07a4ea..4b463cd140ef 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -217,6 +217,7 @@ static void safe_read_bulk_callback(struct urb *urb) struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; unsigned char length = urb->actual_length; + struct tty_struct *tty; int result; int status = urb->status; @@ -242,28 +243,31 @@ static void safe_read_bulk_callback(struct urb *urb) printk("\n"); } #endif + tty = tty_port_tty_get(&port->port); if (safe) { __u16 fcs; fcs = fcs_compute10(data, length, CRC10_INITFCS); if (!fcs) { int actual_length = data[length - 2] >> 2; if (actual_length <= (length - 2)) { - info("%s - actual: %d", __func__, - actual_length); - tty_insert_flip_string(port->port.tty, + dev_info(&urb->dev->dev, "%s - actual: %d\n", + __func__, actual_length); + tty_insert_flip_string(tty, data, actual_length); - tty_flip_buffer_push(port->port.tty); + tty_flip_buffer_push(tty); } else { - err("%s - inconsistent lengths %d:%d", + dev_err(&port->dev, + "%s - inconsistent lengths %d:%d\n", __func__, actual_length, length); } } else { - err("%s - bad CRC %x", __func__, fcs); + dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs); } } else { - tty_insert_flip_string(port->port.tty, data, length); - tty_flip_buffer_push(port->port.tty); + tty_insert_flip_string(tty, data, length); + tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* Continue trying to always read */ usb_fill_bulk_urb(urb, port->serial->dev, @@ -274,8 +278,9 @@ static void safe_read_bulk_callback(struct urb *urb) result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); /* FIXME: Need a mechanism to retry later if this happens */ } @@ -366,8 +371,9 @@ static int safe_write(struct tty_struct *tty, struct usb_serial_port *port, result = usb_submit_urb(port->write_urb, GFP_KERNEL); if (result) { port->write_urb_busy = 0; - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); return 0; } dbg("%s urb: %p submitted", __func__, port->write_urb); @@ -425,14 +431,13 @@ static int __init safe_init(void) { int i, retval; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); - info("vendor: %x product: %x safe: %d padded: %d\n", - vendor, product, safe, padded); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); /* if we have vendor / product parameters patch them into id list */ if (vendor || product) { - info("vendor: %x product: %x\n", vendor, product); + printk(KERN_INFO KBUILD_MODNAME ": vendor: %x product: %x\n", + vendor, product); for (i = 0; i < ARRAY_SIZE(id_table); i++) { if (!id_table[i].idVendor && !id_table[i].idProduct) { diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ea1a103c99be..0f2b67244af6 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -247,7 +247,7 @@ static int sierra_send_setup(struct tty_struct *tty, struct sierra_port_private *portdata; __u16 interface = 0; - dbg("%s", __func__); + dev_dbg(&port->dev, "%s", __func__); portdata = usb_get_serial_port_data(port); @@ -284,7 +284,7 @@ static int sierra_send_setup(struct tty_struct *tty, static void sierra_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { - dbg("%s", __func__); + dev_dbg(&port->dev, "%s", __func__); tty_termios_copy_hw(tty->termios, old_termios); sierra_send_setup(tty, port); } @@ -295,6 +295,7 @@ static int sierra_tiocmget(struct tty_struct *tty, struct file *file) unsigned int value; struct sierra_port_private *portdata; + dev_dbg(&port->dev, "%s", __func__); portdata = usb_get_serial_port_data(port); value = ((portdata->rts_state) ? TIOCM_RTS : 0) | @@ -334,14 +335,14 @@ static void sierra_outdat_callback(struct urb *urb) int status = urb->status; unsigned long flags; - dbg("%s - port %d", __func__, port->number); + dev_dbg(&port->dev, "%s - port %d", __func__, port->number); /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree(urb->transfer_buffer); if (status) - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&port->dev, "%s - nonzero write bulk status " + "received: %d", __func__, status); spin_lock_irqsave(&portdata->lock, flags); --portdata->outstanding_urbs; @@ -363,12 +364,12 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, portdata = usb_get_serial_port_data(port); - dbg("%s: write (%d chars)", __func__, count); + dev_dbg(&port->dev, "%s: write (%d chars)", __func__, count); spin_lock_irqsave(&portdata->lock, flags); if (portdata->outstanding_urbs > N_OUT_URB) { spin_unlock_irqrestore(&portdata->lock, flags); - dbg("%s - write limit hit\n", __func__); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); return 0; } portdata->outstanding_urbs++; @@ -437,17 +438,18 @@ static void sierra_indat_callback(struct urb *urb) port = urb->context; if (status) { - dbg("%s: nonzero status: %d on endpoint %02x.", - __func__, status, endpoint); + dev_dbg(&port->dev, "%s: nonzero status: %d on" + " endpoint %02x.", __func__, status, endpoint); } else { - tty = port->port.tty; if (urb->actual_length) { + tty = tty_port_tty_get(&port->port); tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); - } else { - dbg("%s: empty read urb received", __func__); - } + tty_kref_put(tty); + } else + dev_dbg(&port->dev, "%s: empty read urb" + " received", __func__); /* Resubmit urb so we continue receiving */ if (port->port.count && status != -ESHUTDOWN) { @@ -468,15 +470,17 @@ static void sierra_instat_callback(struct urb *urb) struct sierra_port_private *portdata = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; - dbg("%s", __func__); - dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); + dev_dbg(&port->dev, "%s", __func__); + dev_dbg(&port->dev, "%s: urb %p port %p has data %p", __func__, + urb, port, portdata); if (status == 0) { struct usb_ctrlrequest *req_pkt = (struct usb_ctrlrequest *)urb->transfer_buffer; if (!req_pkt) { - dbg("%s: NULL req_pkt\n", __func__); + dev_dbg(&port->dev, "%s: NULL req_pkt\n", + __func__); return; } if ((req_pkt->bRequestType == 0xA1) && @@ -485,8 +489,10 @@ static void sierra_instat_callback(struct urb *urb) unsigned char signals = *((unsigned char *) urb->transfer_buffer + sizeof(struct usb_ctrlrequest)); + struct tty_struct *tty; - dbg("%s: signal x%x", __func__, signals); + dev_dbg(&port->dev, "%s: signal x%x", __func__, + signals); old_dcd_state = portdata->dcd_state; portdata->cts_state = 1; @@ -494,23 +500,26 @@ static void sierra_instat_callback(struct urb *urb) portdata->dsr_state = ((signals & 0x02) ? 1 : 0); portdata->ri_state = ((signals & 0x08) ? 1 : 0); - if (port->port.tty && !C_CLOCAL(port->port.tty) && + tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty) && old_dcd_state && !portdata->dcd_state) - tty_hangup(port->port.tty); + tty_hangup(tty); + tty_kref_put(tty); } else { - dbg("%s: type %x req %x", __func__, - req_pkt->bRequestType, req_pkt->bRequest); + dev_dbg(&port->dev, "%s: type %x req %x", + __func__, req_pkt->bRequestType, + req_pkt->bRequest); } } else - dbg("%s: error %d", __func__, status); + dev_dbg(&port->dev, "%s: error %d", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ if (status != -ESHUTDOWN) { urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) - dbg("%s: resubmit intr urb failed. (%d)", - __func__, err); + dev_dbg(&port->dev, "%s: resubmit intr urb " + "failed. (%d)", __func__, err); } } @@ -520,14 +529,14 @@ static int sierra_write_room(struct tty_struct *tty) struct sierra_port_private *portdata = usb_get_serial_port_data(port); unsigned long flags; - dbg("%s - port %d", __func__, port->number); + dev_dbg(&port->dev, "%s - port %d", __func__, port->number); /* try to give a good number back based on if we have any free urbs at * this point in time */ spin_lock_irqsave(&portdata->lock, flags); if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { spin_unlock_irqrestore(&portdata->lock, flags); - dbg("%s - write limit hit\n", __func__); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); return 0; } spin_unlock_irqrestore(&portdata->lock, flags); @@ -546,7 +555,7 @@ static int sierra_open(struct tty_struct *tty, portdata = usb_get_serial_port_data(port); - dbg("%s", __func__); + dev_dbg(&port->dev, "%s", __func__); /* Set some sane defaults */ portdata->rts_state = 1; @@ -558,8 +567,8 @@ static int sierra_open(struct tty_struct *tty, if (!urb) continue; if (urb->dev != serial->dev) { - dbg("%s: dev %p != %p", __func__, - urb->dev, serial->dev); + dev_dbg(&port->dev, "%s: dev %p != %p", + __func__, urb->dev, serial->dev); continue; } @@ -598,7 +607,7 @@ static void sierra_close(struct tty_struct *tty, struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; - dbg("%s", __func__); + dev_dbg(&port->dev, "%s", __func__); portdata = usb_get_serial_port_data(port); portdata->rts_state = 0; @@ -616,8 +625,7 @@ static void sierra_close(struct tty_struct *tty, } usb_kill_urb(port->interrupt_in_urb); - - port->port.tty = NULL; /* FIXME */ + tty_port_tty_set(&port->port, NULL); } static int sierra_startup(struct usb_serial *serial) @@ -628,7 +636,7 @@ static int sierra_startup(struct usb_serial *serial) int i; int j; - dbg("%s", __func__); + dev_dbg(&serial->dev->dev, "%s", __func__); /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -642,8 +650,9 @@ static int sierra_startup(struct usb_serial *serial) port = serial->port[i]; portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) { - dbg("%s: kmalloc for sierra_port_private (%d) failed!.", - __func__, i); + dev_dbg(&port->dev, "%s: kmalloc for " + "sierra_port_private (%d) failed!.", + __func__, i); return -ENOMEM; } spin_lock_init(&portdata->lock); @@ -663,8 +672,8 @@ static int sierra_startup(struct usb_serial *serial) for (j = 0; j < N_IN_URB; ++j) { urb = usb_alloc_urb(0, GFP_KERNEL); if (urb == NULL) { - dbg("%s: alloc for in port failed.", - __func__); + dev_dbg(&port->dev, "%s: alloc for in " + "port failed.", __func__); continue; } /* Fill URB using supplied data. */ @@ -686,7 +695,7 @@ static void sierra_shutdown(struct usb_serial *serial) struct usb_serial_port *port; struct sierra_port_private *portdata; - dbg("%s", __func__); + dev_dbg(&serial->dev->dev, "%s", __func__); for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -741,7 +750,8 @@ static int __init sierra_init(void) if (retval) goto failed_driver_register; - info(DRIVER_DESC ": " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 283cf6b36b2c..a65bc2bd8e71 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -589,8 +589,8 @@ static void spcp8x5_set_termios(struct tty_struct *tty, case 1000000: buf[0] = 0x0b; break; default: - err("spcp825 driver does not support the baudrate " - "requested, using default of 9600."); + dev_err(&port->dev, "spcp825 driver does not support the " + "baudrate requested, using default of 9600.\n"); } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ @@ -629,7 +629,8 @@ static void spcp8x5_set_termios(struct tty_struct *tty, SET_UART_FORMAT_TYPE, SET_UART_FORMAT, uartdata, 0, NULL, 0, 100); if (i < 0) - err("Set UART format %#x failed (error = %d)", uartdata, i); + dev_err(&port->dev, "Set UART format %#x failed (error = %d)\n", + uartdata, i); dbg("0x21:0x40:0:0 %d\n", i); if (cflag & CRTSCTS) { @@ -755,7 +756,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) tty_flag = TTY_FRAME; dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ @@ -765,6 +766,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) tty_insert_flip_char(tty, data[i], tty_flag); tty_flip_buffer_push(tty); } + tty_kref_put(tty); /* Schedule the next read _if_ we are still open */ if (port->port.count) { @@ -1053,7 +1055,8 @@ static int __init spcp8x5_init(void) retval = usb_register(&spcp8x5_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&spcp8x5_device); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 9a3e495c769c..31c42d1cae13 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -85,7 +85,6 @@ #include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> -#include <linux/firmware.h> #include "ti_usb_3410_5052.h" @@ -179,7 +178,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); static int ti_get_lsr(struct ti_port *tport); static int ti_get_serial_info(struct ti_port *tport, struct serial_struct __user *ret_arg); -static int ti_set_serial_info(struct ti_port *tport, +static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg); static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); @@ -383,7 +382,8 @@ static int __init ti_init(void) if (ret) goto failed_usb; - info(TI_DRIVER_DESC " " TI_DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":" + TI_DRIVER_DESC "\n"); return 0; @@ -857,8 +857,8 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file, (struct serial_struct __user *)arg); case TIOCSSERIAL: dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); - return ti_set_serial_info(tport, - (struct serial_struct __user *)arg); + return ti_set_serial_info(tty, tport, + (struct serial_struct __user *)arg); case TIOCMIWAIT: dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); cprev = tport->tp_icount; @@ -1211,6 +1211,7 @@ static void ti_bulk_in_callback(struct urb *urb) struct device *dev = &urb->dev->dev; int status = urb->status; int retval = 0; + struct tty_struct *tty; dbg("%s", __func__); @@ -1239,20 +1240,22 @@ static void ti_bulk_in_callback(struct urb *urb) return; } - if (port->port.tty && urb->actual_length) { + tty = tty_port_tty_get(&port->port); + if (tty && urb->actual_length) { usb_serial_debug_data(debug, dev, __func__, urb->actual_length, urb->transfer_buffer); if (!tport->tp_is_open) dbg("%s - port closed, dropping data", __func__); else - ti_recv(&urb->dev->dev, port->port.tty, + ti_recv(&urb->dev->dev, tty, urb->transfer_buffer, urb->actual_length); spin_lock(&tport->tp_lock); tport->tp_icount.rx += urb->actual_length; spin_unlock(&tport->tp_lock); + tty_kref_put(tty); } exit: @@ -1330,7 +1333,7 @@ static void ti_send(struct ti_port *tport) { int count, result; struct usb_serial_port *port = tport->tp_port; - struct tty_struct *tty = port->port.tty; /* FIXME */ + struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */ unsigned long flags; @@ -1338,19 +1341,15 @@ static void ti_send(struct ti_port *tport) spin_lock_irqsave(&tport->tp_lock, flags); - if (tport->tp_write_urb_in_use) { - spin_unlock_irqrestore(&tport->tp_lock, flags); - return; - } + if (tport->tp_write_urb_in_use) + goto unlock; count = ti_buf_get(tport->tp_write_buf, port->write_urb->transfer_buffer, port->bulk_out_size); - if (count == 0) { - spin_unlock_irqrestore(&tport->tp_lock, flags); - return; - } + if (count == 0) + goto unlock; tport->tp_write_urb_in_use = 1; @@ -1380,7 +1379,13 @@ static void ti_send(struct ti_port *tport) /* more room in the buffer for new writes, wakeup */ if (tty) tty_wakeup(tty); + tty_kref_put(tty); wake_up_interruptible(&tport->tp_write_wait); + return; +unlock: + spin_unlock_irqrestore(&tport->tp_lock, flags); + tty_kref_put(tty); + return; } @@ -1464,20 +1469,16 @@ static int ti_get_serial_info(struct ti_port *tport, } -static int ti_set_serial_info(struct ti_port *tport, +static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg) { - struct usb_serial_port *port = tport->tp_port; struct serial_struct new_serial; if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) return -EFAULT; tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; - /* FIXME */ - if (port->port.tty) - port->port.tty->low_latency = - (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; tport->tp_closing_wait = new_serial.closing_wait; return 0; @@ -1510,7 +1511,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) tport->tp_msr = msr & TI_MSR_MASK; /* handle CTS flow control */ - tty = tport->tp_port->port.tty; + tty = tty_port_tty_get(&tport->tp_port->port); if (tty && C_CRTSCTS(tty)) { if (msr & TI_MSR_CTS) { tty->hw_stopped = 0; @@ -1519,6 +1520,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) tty->hw_stopped = 1; } } + tty_kref_put(tty); } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4f7f9e3ae0a4..8be3f39891c7 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -214,7 +214,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) /* set up our port structure making the tty driver * remember our port object, and us it */ tty->driver_data = port; - port->port.tty = tty; + tty_port_tty_set(&port->port, tty); if (port->port.count == 1) { @@ -246,7 +246,7 @@ bailout_module_put: bailout_mutex_unlock: port->port.count = 0; tty->driver_data = NULL; - port->port.tty = NULL; + tty_port_tty_set(&port->port, NULL); mutex_unlock(&port->mutex); bailout_kref_put: usb_serial_put(serial); @@ -276,10 +276,11 @@ static void serial_close(struct tty_struct *tty, struct file *filp) port->serial->type->close(tty, port, filp); if (port->port.count == (port->console? 1 : 0)) { - if (port->port.tty) { - if (port->port.tty->driver_data) - port->port.tty->driver_data = NULL; - port->port.tty = NULL; + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) { + if (tty->driver_data) + tty->driver_data = NULL; + tty_port_tty_set(&port->port, NULL); } } @@ -508,11 +509,12 @@ static void usb_serial_port_work(struct work_struct *work) if (!port) return; - tty = port->port.tty; + tty = tty_port_tty_get(&port->port); if (!tty) return; tty_wakeup(tty); + tty_kref_put(tty); } static void port_release(struct device *dev) @@ -819,6 +821,7 @@ int usb_serial_probe(struct usb_interface *interface, port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); if (!port) goto probe_error; + tty_port_init(&port->port); port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); @@ -1040,8 +1043,11 @@ void usb_serial_disconnect(struct usb_interface *interface) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) { - if (port->port.tty) - tty_hangup(port->port.tty); + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) { + tty_hangup(tty); + tty_kref_put(tty); + } kill_traffic(port); } } @@ -1115,7 +1121,8 @@ static int __init usb_serial_init(void) result = bus_register(&usb_serial_bus_type); if (result) { - err("%s - registering bus driver failed", __func__); + printk(KERN_ERR "usb-serial: %s - registering bus driver " + "failed\n", __func__); goto exit_bus; } @@ -1136,25 +1143,28 @@ static int __init usb_serial_init(void) tty_set_operations(usb_serial_tty_driver, &serial_ops); result = tty_register_driver(usb_serial_tty_driver); if (result) { - err("%s - tty_register_driver failed", __func__); + printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n", + __func__); goto exit_reg_driver; } /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { - err("%s - usb_register failed", __func__); + printk(KERN_ERR "usb-serial: %s - usb_register failed\n", + __func__); goto exit_tty; } /* register the generic driver, if we should */ result = usb_serial_generic_register(debug); if (result < 0) { - err("%s - registering generic driver failed", __func__); + printk(KERN_ERR "usb-serial: %s - registering generic " + "driver failed\n", __func__); goto exit_generic; } - info(DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return result; @@ -1168,7 +1178,8 @@ exit_reg_driver: bus_unregister(&usb_serial_bus_type); exit_bus: - err("%s - returning with error %d", __func__, result); + printk(KERN_ERR "usb-serial: %s - returning with error %d\n", + __func__, result); put_tty_driver(usb_serial_tty_driver); return result; } @@ -1227,11 +1238,11 @@ int usb_serial_register(struct usb_serial_driver *driver) retval = usb_serial_bus_register(driver); if (retval) { - err("problem %d when registering driver %s", - retval, driver->description); + printk(KERN_ERR "usb-serial: problem %d when registering " + "driver %s\n", retval, driver->description); list_del(&driver->driver_list); } else - info("USB Serial support registered for %s", + printk(KERN_INFO "USB Serial support registered for %s\n", driver->description); return retval; @@ -1242,7 +1253,8 @@ EXPORT_SYMBOL_GPL(usb_serial_register); void usb_serial_deregister(struct usb_serial_driver *device) { /* must be called with BKL held */ - info("USB Serial deregistering driver %s", device->description); + printk(KERN_INFO "USB Serial deregistering driver %s\n", + device->description); list_del(&device->driver_list); usb_serial_bus_deregister(device); } diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index cf8924f9a2cc..4facce3d9364 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -499,7 +499,7 @@ static void visor_read_bulk_callback(struct urb *urb) int status = urb->status; struct tty_struct *tty; int result; - int available_room; + int available_room = 0; dbg("%s - port %d", __func__, port->number); @@ -512,13 +512,17 @@ static void visor_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; - if (tty && urb->actual_length) { - available_room = tty_buffer_request_room(tty, + if (urb->actual_length) { + tty = tty_port_tty_get(&port->port); + if (tty) { + available_room = tty_buffer_request_room(tty, urb->actual_length); - if (available_room) { - tty_insert_flip_string(tty, data, available_room); - tty_flip_buffer_push(tty); + if (available_room) { + tty_insert_flip_string(tty, data, + available_room); + tty_flip_buffer_push(tty); + } + tty_kref_put(tty); } spin_lock(&priv->lock); priv->bytes_in += available_room; @@ -764,7 +768,7 @@ static int visor_probe(struct usb_serial *serial, dbg("%s", __func__); if (serial->dev->actconfig->desc.bConfigurationValue != 1) { - err("active config #%d != 1 ??", + dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } @@ -967,11 +971,14 @@ static int __init visor_init(void) break; } } - info( - "Untested USB device specified at time of module insertion"); - info("Warning: This is not guaranteed to work"); - info("Using a newer kernel is preferred to this method"); - info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x", + printk(KERN_INFO KBUILD_MODNAME + ": Untested USB device specified at time of module insertion\n"); + printk(KERN_INFO KBUILD_MODNAME + ": Warning: This is not guaranteed to work\n"); + printk(KERN_INFO KBUILD_MODNAME + ": Using a newer kernel is preferred to this method\n"); + printk(KERN_INFO KBUILD_MODNAME + ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n", vendor, product); } retval = usb_serial_register(&handspring_device); @@ -986,7 +993,7 @@ static int __init visor_init(void) retval = usb_register(&visor_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return 0; failed_usb_register: diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 3a9d14384a43..5335d3211c07 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -303,12 +303,15 @@ static int whiteheat_firmware_download(struct usb_serial *serial, if (request_ihex_firmware(&firmware_fw, "whiteheat.fw", &serial->dev->dev)) { - err("%s - request \"whiteheat.fw\" failed", __func__); + dev_err(&serial->dev->dev, + "%s - request \"whiteheat.fw\" failed\n", __func__); goto out; } if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw", &serial->dev->dev)) { - err("%s - request \"whiteheat_loader.fw\" failed", __func__); + dev_err(&serial->dev->dev, + "%s - request \"whiteheat_loader.fw\" failed\n", + __func__); goto out; } ret = 0; @@ -320,9 +323,10 @@ static int whiteheat_firmware_download(struct usb_serial *serial, (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { - err("%s - ezusb_writememory failed for loader (%d %04X %p %d)", - __func__, response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); + dev_err(&serial->dev->dev, "%s - ezusb_writememory " + "failed for loader (%d %04X %p %d)\n", + __func__, response, be32_to_cpu(record->addr), + record->data, be16_to_cpu(record->len)); break; } record = ihex_next_binrec(record); @@ -338,9 +342,11 @@ static int whiteheat_firmware_download(struct usb_serial *serial, (unsigned char *)record->data, be16_to_cpu(record->len), 0xa3); if (response < 0) { - err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)", - __func__, response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); + dev_err(&serial->dev->dev, "%s - ezusb_writememory " + "failed for first firmware step " + "(%d %04X %p %d)\n", __func__, response, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); break; } ++record; @@ -354,9 +360,11 @@ static int whiteheat_firmware_download(struct usb_serial *serial, (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { - err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)", - __func__, response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); + dev_err(&serial->dev->dev, "%s - ezusb_writememory " + "failed for second firmware step " + "(%d %04X %p %d)\n", __func__, response, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); break; } ++record; @@ -421,12 +429,12 @@ static int whiteheat_attach(struct usb_serial *serial) ret = usb_bulk_msg(serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS); if (ret) { - err("%s: Couldn't send command [%d]", - serial->type->description, ret); + dev_err(&serial->dev->dev, "%s: Couldn't send command [%d]\n", + serial->type->description, ret); goto no_firmware; } else if (alen != 2) { - err("%s: Send command incomplete [%d]", - serial->type->description, alen); + dev_err(&serial->dev->dev, "%s: Send command incomplete [%d]\n", + serial->type->description, alen); goto no_firmware; } @@ -437,31 +445,33 @@ static int whiteheat_attach(struct usb_serial *serial) ret = usb_bulk_msg(serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS); if (ret) { - err("%s: Couldn't get results [%d]", - serial->type->description, ret); + dev_err(&serial->dev->dev, "%s: Couldn't get results [%d]\n", + serial->type->description, ret); goto no_firmware; } else if (alen != sizeof(*hw_info) + 1) { - err("%s: Get results incomplete [%d]", - serial->type->description, alen); + dev_err(&serial->dev->dev, "%s: Get results incomplete [%d]\n", + serial->type->description, alen); goto no_firmware; } else if (result[0] != command[0]) { - err("%s: Command failed [%d]", - serial->type->description, result[0]); + dev_err(&serial->dev->dev, "%s: Command failed [%d]\n", + serial->type->description, result[0]); goto no_firmware; } hw_info = (struct whiteheat_hw_info *)&result[1]; - info("%s: Driver %s: Firmware v%d.%02d", serial->type->description, - DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev); + dev_info(&serial->dev->dev, "%s: Driver %s: Firmware v%d.%02d\n", + serial->type->description, DRIVER_VERSION, + hw_info->sw_major_rev, hw_info->sw_minor_rev); for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); if (info == NULL) { - err("%s: Out of memory for port structures\n", - serial->type->description); + dev_err(&port->dev, + "%s: Out of memory for port structures\n", + serial->type->description); goto no_private; } @@ -481,18 +491,20 @@ static int whiteheat_attach(struct usb_serial *serial) for (j = 0; j < urb_pool_size; j++) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - err("No free urbs available"); + dev_err(&port->dev, "No free urbs available\n"); goto no_rx_urb; } buf_size = port->read_urb->transfer_buffer_length; urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); if (!urb->transfer_buffer) { - err("Couldn't allocate urb buffer"); + dev_err(&port->dev, + "Couldn't allocate urb buffer\n"); goto no_rx_buf; } wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); if (!wrap) { - err("Couldn't allocate urb wrapper"); + dev_err(&port->dev, + "Couldn't allocate urb wrapper\n"); goto no_rx_wrap; } usb_fill_bulk_urb(urb, serial->dev, @@ -505,18 +517,20 @@ static int whiteheat_attach(struct usb_serial *serial) urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - err("No free urbs available"); + dev_err(&port->dev, "No free urbs available\n"); goto no_tx_urb; } buf_size = port->write_urb->transfer_buffer_length; urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); if (!urb->transfer_buffer) { - err("Couldn't allocate urb buffer"); + dev_err(&port->dev, + "Couldn't allocate urb buffer\n"); goto no_tx_buf; } wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); if (!wrap) { - err("Couldn't allocate urb wrapper"); + dev_err(&port->dev, + "Couldn't allocate urb wrapper\n"); goto no_tx_wrap; } usb_fill_bulk_urb(urb, serial->dev, @@ -534,8 +548,9 @@ static int whiteheat_attach(struct usb_serial *serial) command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { - err("%s: Out of memory for port structures\n", - serial->type->description); + dev_err(&serial->dev->dev, + "%s: Out of memory for port structures\n", + serial->type->description); goto no_command_private; } @@ -552,12 +567,15 @@ static int whiteheat_attach(struct usb_serial *serial) no_firmware: /* Firmware likely not running */ - err("%s: Unable to retrieve firmware version, try replugging\n", - serial->type->description); - err("%s: If the firmware is not running (status led not blinking)\n", - serial->type->description); - err("%s: please contact support@connecttech.com\n", - serial->type->description); + dev_err(&serial->dev->dev, + "%s: Unable to retrieve firmware version, try replugging\n", + serial->type->description); + dev_err(&serial->dev->dev, + "%s: If the firmware is not running (status led not blinking)\n", + serial->type->description); + dev_err(&serial->dev->dev, + "%s: please contact support@connecttech.com\n", + serial->type->description); kfree(result); return -ENODEV; @@ -680,8 +698,9 @@ static int whiteheat_open(struct tty_struct *tty, /* Start reading from the device */ retval = start_port_read(port); if (retval) { - err("%s - failed submitting read urb, error %d", - __func__, retval); + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, retval); firm_close(port); stop_command_port(port->serial); goto exit; @@ -806,8 +825,9 @@ static int whiteheat_write(struct tty_struct *tty, urb->transfer_buffer_length = bytes; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", - __func__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); sent = result; spin_lock_irqsave(&info->lock, flags); list_add(tmp, &info->tx_urbs_free); @@ -1075,7 +1095,7 @@ static void whiteheat_read_callback(struct urb *urb) wrap = urb_to_wrap(urb, &info->rx_urbs_submitted); if (!wrap) { spin_unlock(&info->lock); - err("%s - Not my urb!", __func__); + dev_err(&port->dev, "%s - Not my urb!\n", __func__); return; } list_del(&wrap->list); @@ -1119,7 +1139,7 @@ static void whiteheat_write_callback(struct urb *urb) wrap = urb_to_wrap(urb, &info->tx_urbs_submitted); if (!wrap) { spin_unlock(&info->lock); - err("%s - Not my urb!", __func__); + dev_err(&port->dev, "%s - Not my urb!\n", __func__); return; } list_move(&wrap->list, &info->tx_urbs_free); @@ -1383,8 +1403,9 @@ static int start_command_port(struct usb_serial *serial) command_port->read_urb->dev = serial->dev; retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL); if (retval) { - err("%s - failed submitting read urb, error %d", - __func__, retval); + dev_err(&serial->dev->dev, + "%s - failed submitting read urb, error %d\n", + __func__, retval); goto exit; } } @@ -1481,7 +1502,7 @@ static void rx_data_softint(struct work_struct *work) struct whiteheat_private *info = container_of(work, struct whiteheat_private, rx_work); struct usb_serial_port *port = info->port; - struct tty_struct *tty = port->port.tty; + struct tty_struct *tty = tty_port_tty_get(&port->port); struct whiteheat_urb_wrap *wrap; struct urb *urb; unsigned long flags; @@ -1493,7 +1514,7 @@ static void rx_data_softint(struct work_struct *work) spin_lock_irqsave(&info->lock, flags); if (info->flags & THROTTLED) { spin_unlock_irqrestore(&info->lock, flags); - return; + goto out; } list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { @@ -1513,7 +1534,7 @@ static void rx_data_softint(struct work_struct *work) spin_unlock_irqrestore(&info->lock, flags); tty_flip_buffer_push(tty); schedule_work(&info->rx_work); - return; + goto out; } tty_insert_flip_string(tty, urb->transfer_buffer, len); sent += len; @@ -1522,7 +1543,8 @@ static void rx_data_softint(struct work_struct *work) urb->dev = port->serial->dev; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - err("%s - failed resubmitting read urb, error %d", + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", __func__, result); spin_lock_irqsave(&info->lock, flags); list_add(tmp, &info->rx_urbs_free); @@ -1536,6 +1558,8 @@ static void rx_data_softint(struct work_struct *work) if (sent) tty_flip_buffer_push(tty); +out: + tty_kref_put(tty); } @@ -1554,7 +1578,8 @@ static int __init whiteheat_init(void) retval = usb_register(&whiteheat_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; failed_usb_register: usb_serial_deregister(&whiteheat_device); diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 98b89ea9e312..c7bf8954b4e4 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -78,8 +78,8 @@ static void usb_onetouch_irq(struct urb *urb) resubmit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) - err ("can't resubmit intr, %s-%s/input0, retval %d", - onetouch->udev->bus->bus_name, + dev_err(&dev->dev, "can't resubmit intr, %s-%s/input0, " + "retval %d\n", onetouch->udev->bus->bus_name, onetouch->udev->devpath, retval); } @@ -90,7 +90,7 @@ static int usb_onetouch_open(struct input_dev *dev) onetouch->is_open = 1; onetouch->irq->dev = onetouch->udev; if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { - err("usb_submit_urb failed"); + dev_err(&dev->dev, "usb_submit_urb failed\n"); return -EIO; } @@ -117,7 +117,8 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action) break; case US_RESUME: if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0) - err("usb_submit_urb failed"); + dev_err(&onetouch->irq->dev->dev, + "usb_submit_urb failed\n"); break; default: break; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 3523a0bfa0ff..79108d5d3171 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -663,7 +663,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) } /* Did we transfer less than the minimum amount required? */ - if (srb->result == SAM_STAT_GOOD && + if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); |