aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/atm/usbatm.c15
-rw-r--r--drivers/usb/atm/usbatm.h10
-rw-r--r--drivers/usb/atm/xusbatm.c2
-rw-r--r--drivers/usb/class/Kconfig10
-rw-r--r--drivers/usb/class/Makefile1
-rw-r--r--drivers/usb/class/cdc-acm.c26
-rw-r--r--drivers/usb/class/cdc-wdm.c48
-rw-r--r--drivers/usb/class/usblp.c25
-rw-r--r--drivers/usb/class/usbtmc.c1087
-rw-r--r--drivers/usb/core/Kconfig2
-rw-r--r--drivers/usb/core/devio.c18
-rw-r--r--drivers/usb/core/driver.c3
-rw-r--r--drivers/usb/core/endpoint.c3
-rw-r--r--drivers/usb/core/file.c11
-rw-r--r--drivers/usb/core/hcd.c9
-rw-r--r--drivers/usb/core/hcd.h6
-rw-r--r--drivers/usb/core/hub.c102
-rw-r--r--drivers/usb/core/inode.c20
-rw-r--r--drivers/usb/core/message.c3
-rw-r--r--drivers/usb/core/sysfs.c24
-rw-r--r--drivers/usb/core/urb.c169
-rw-r--r--drivers/usb/gadget/Kconfig315
-rw-r--r--drivers/usb/gadget/Makefile24
-rw-r--r--drivers/usb/gadget/cdc2.c26
-rw-r--r--drivers/usb/gadget/composite.c68
-rw-r--r--drivers/usb/gadget/dummy_hcd.c33
-rw-r--r--drivers/usb/gadget/ether.c30
-rw-r--r--drivers/usb/gadget/f_ecm.c108
-rw-r--r--drivers/usb/gadget/f_loopback.c35
-rw-r--r--drivers/usb/gadget/f_obex.c493
-rw-r--r--drivers/usb/gadget/f_sourcesink.c1
-rw-r--r--drivers/usb/gadget/f_subset.c44
-rw-r--r--drivers/usb/gadget/file_storage.c35
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c2760
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.h437
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c176
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h21
-rw-r--r--drivers/usb/gadget/gadget_chips.h9
-rw-r--r--drivers/usb/gadget/gmidi.c17
-rw-r--r--drivers/usb/gadget/net2280.c40
-rw-r--r--drivers/usb/gadget/net2280.h1
-rw-r--r--drivers/usb/gadget/omap_udc.c7
-rw-r--r--drivers/usb/gadget/printer.c24
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c1
-rw-r--r--drivers/usb/gadget/rndis.c115
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c2
-rw-r--r--drivers/usb/gadget/serial.c33
-rw-r--r--drivers/usb/gadget/u_ether.c11
-rw-r--r--drivers/usb/gadget/u_serial.h1
-rw-r--r--drivers/usb/gadget/zero.c17
-rw-r--r--drivers/usb/host/ehci-dbg.c56
-rw-r--r--drivers/usb/host/ehci-hcd.c48
-rw-r--r--drivers/usb/host/ehci-hub.c27
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c2
-rw-r--r--drivers/usb/host/ehci-ppc-soc.c201
-rw-r--r--drivers/usb/host/ehci.h161
-rw-r--r--drivers/usb/host/isp116x-hcd.c13
-rw-r--r--drivers/usb/host/isp1760-if.c7
-rw-r--r--drivers/usb/host/ohci-dbg.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c10
-rw-r--r--drivers/usb/host/ohci-hub.c87
-rw-r--r--drivers/usb/host/ohci-omap.c18
-rw-r--r--drivers/usb/host/ohci-pnx4008.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c259
-rw-r--r--drivers/usb/host/ohci.h8
-rw-r--r--drivers/usb/host/r8a66597-hcd.c101
-rw-r--r--drivers/usb/host/sl811-hcd.c15
-rw-r--r--drivers/usb/host/sl811_cs.c133
-rw-r--r--drivers/usb/host/uhci-hcd.c10
-rw-r--r--drivers/usb/host/uhci-q.c41
-rw-r--r--drivers/usb/image/mdc800.c61
-rw-r--r--drivers/usb/misc/Kconfig24
-rw-r--r--drivers/usb/misc/Makefile2
-rw-r--r--drivers/usb/misc/adutux.c22
-rw-r--r--drivers/usb/misc/appledisplay.c26
-rw-r--r--drivers/usb/misc/cypress_cy7c63.c6
-rw-r--r--drivers/usb/misc/cytherm.c9
-rw-r--r--drivers/usb/misc/emi26.c17
-rw-r--r--drivers/usb/misc/emi62.c4
-rw-r--r--drivers/usb/misc/ftdi-elan.c10
-rw-r--r--drivers/usb/misc/idmouse.c5
-rw-r--r--drivers/usb/misc/legousbtower.c23
-rw-r--r--drivers/usb/misc/phidgetkit.c5
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c5
-rw-r--r--drivers/usb/misc/phidgetservo.c5
-rw-r--r--drivers/usb/misc/rio500.c11
-rw-r--r--drivers/usb/misc/trancevibrator.c3
-rw-r--r--drivers/usb/misc/usblcd.c13
-rw-r--r--drivers/usb/misc/usbsevseg.c394
-rw-r--r--drivers/usb/misc/uss720.c19
-rw-r--r--drivers/usb/misc/vstusb.c782
-rw-r--r--drivers/usb/mon/mon_bin.c6
-rw-r--r--drivers/usb/mon/mon_main.c2
-rw-r--r--drivers/usb/musb/Kconfig4
-rw-r--r--drivers/usb/musb/cppi_dma.h4
-rw-r--r--drivers/usb/musb/davinci.c20
-rw-r--r--drivers/usb/musb/musb_core.c41
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c24
-rw-r--r--drivers/usb/musb/musb_host.c19
-rw-r--r--drivers/usb/musb/musb_io.h4
-rw-r--r--drivers/usb/musb/musbhsdma.c306
-rw-r--r--drivers/usb/serial/aircable.c23
-rw-r--r--drivers/usb/serial/belkin_sa.c42
-rw-r--r--drivers/usb/serial/console.c8
-rw-r--r--drivers/usb/serial/cp2101.c3
-rw-r--r--drivers/usb/serial/cyberjack.c31
-rw-r--r--drivers/usb/serial/cypress_m8.c26
-rw-r--r--drivers/usb/serial/digi_acceleport.c87
-rw-r--r--drivers/usb/serial/empeg.c19
-rw-r--r--drivers/usb/serial/ezusb.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c107
-rw-r--r--drivers/usb/serial/ftdi_sio.h5
-rw-r--r--drivers/usb/serial/garmin_gps.c6
-rw-r--r--drivers/usb/serial/generic.c3
-rw-r--r--drivers/usb/serial/hp4x.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c62
-rw-r--r--drivers/usb/serial/io_ti.c29
-rw-r--r--drivers/usb/serial/ipaq.c33
-rw-r--r--drivers/usb/serial/ipw.c6
-rw-r--r--drivers/usb/serial/ir-usb.c6
-rw-r--r--drivers/usb/serial/iuu_phoenix.c6
-rw-r--r--drivers/usb/serial/keyspan.c80
-rw-r--r--drivers/usb/serial/keyspan_pda.c33
-rw-r--r--drivers/usb/serial/kl5kusb105.c72
-rw-r--r--drivers/usb/serial/kobil_sct.c7
-rw-r--r--drivers/usb/serial/mct_u232.c48
-rw-r--r--drivers/usb/serial/mos7720.c58
-rw-r--r--drivers/usb/serial/mos7840.c36
-rw-r--r--drivers/usb/serial/navman.c3
-rw-r--r--drivers/usb/serial/omninet.c32
-rw-r--r--drivers/usb/serial/option.c60
-rw-r--r--drivers/usb/serial/oti6858.c7
-rw-r--r--drivers/usb/serial/pl2303.c17
-rw-r--r--drivers/usb/serial/safe_serial.c39
-rw-r--r--drivers/usb/serial/sierra.c88
-rw-r--r--drivers/usb/serial/spcp8x5.c13
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c48
-rw-r--r--drivers/usb/serial/usb-serial.c50
-rw-r--r--drivers/usb/serial/visor.c35
-rw-r--r--drivers/usb/serial/whiteheat.c129
-rw-r--r--drivers/usb/storage/onetouch.c9
-rw-r--r--drivers/usb/storage/transport.c2
142 files changed, 8808 insertions, 2121 deletions
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 07228721caf..06dd114910d 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 e6887c6cf3c..f6f4508a9d4 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 8472543eee8..17d167bbd2d 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 66f17ed88cb..2519e320098 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 535d59a3060..32e85277b5c 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 c257453fa9d..fab23ee8702 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 7e8e1235e4e..7429f70b9d0 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 0647164d36d..b5775af3ba2 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 00000000000..543811f6e6e
--- /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 = &current_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 cc9f397e839..e1759d17ac5 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 20290c5b156..2bccefebff1 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 5a7fa6f0995..e935be7eb46 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 22912136fc1..946fae43d62 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 6b1b229e38c..997e659ff69 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 8ab389dca2b..fc9018e72a0 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 e710ce04e22..2dcde61c465 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 d99963873e3..d73ce262c36 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 db410e92c80..94632264dcc 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 286b4431a09..887738577b2 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 5e1f5d55bf0..f66fba11fbd 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 47111e88f79..f2638009a46 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 acc95b2ac6f..dd4cd5a5137 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 fcb5cb9094d..bd4041b47dc 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 a39a4b940c3..5495b171cf2 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 85c876c1f15..f2da0269e1b 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 7600a0c7875..9064696636a 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 bcac2e68660..37252d0012a 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 a2b5c092bda..4ae579948e5 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 *) &ether_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 *) &ether_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 eda4cde72c8..8affe1dfc2c 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 00000000000..80c2e7e9622
--- /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 f18c3a14d72..dc84d26d283 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 acb8d233aa1..fe183287577 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 *) &ether_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 *) &ether_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 ea2c31d1808..c4e62a6297d 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 00000000000..1fe8b44787b
--- /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 00000000000..31b2710882e
--- /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 45ad556169f..091bb55c9aa 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 6131752a38b..e63ef12645f 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 17d9905101b..4e3107dd2f3 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 ea8651e3da1..60d3f9e9b51 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 5cfb5ebf388..8ae70de2c37 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 81a71dbdc2c..c36852263d9 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 bb54cca4c54..34e9e393f92 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 e0090085b78..5a3034fdfe4 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 7cbc78a6853..bcf375ca3d7 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 7228e856223..8c26f5ea2b8 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 29d13ebe750..48f51b12d2e 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 b3699afff00..37879af1c43 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 3791e627190..66948b72bb9 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 af3910d01ae..300f0ed9475 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 aa0bd4f126a..361d9659ac4 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 b0f8ed5a7fb..0cb53ca8d34 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 8409e0705d6..15a803b206b 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
@@ -1104,7 +1111,9 @@ clean0:
#ifdef DEBUG
debugfs_remove(ehci_debug_root);
ehci_debug_root = NULL;
+err_debug:
#endif
+ 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 740835bb857..218f9660d7e 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 f9575c40912..9c32063a0c2 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 529590eb403..00000000000
--- 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 5799298364f..b11798d17ae 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 ce1ca0ba051..4dda31b2689 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 051ef7b6bdc..af849f59613 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 7cef1d2f7cc..d3269656aa4 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 89901962cbf..8647dab0d7f 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 7ea9a7b3115..32bbce9718f 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 95b3ec89c12..91697bdb399 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 658a2a978c3..e306ca6aef3 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 7f0f35c7818..e294d430733 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 faf622eafce..222011f6172 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 ea7126f99ca..c18d8790c41 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 8a74bbb57d0..e106e9d48d4 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 5da63f53500..516848dd9b4 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 3a7bfe7a887..cf5e4cf7ea4 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 db645936eed..5631d89c873 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 0fb114ca1eb..878c77ca086 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 4ea50e0abcb..e463db5d818 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 45b4e12afb0..1334f7bdd7b 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 965f6eaea6a..7b6922e08ed 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 a076c24a312..1d8e39a557d 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 937940404b7..5720bfef6a3 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 1cd9e7eba93..4fb3c38b924 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 4b994a0cd27..e762beb5f3c 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 5d859ded5bb..602ee05ba9f 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 97c28097153..79a7668ef26 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 4bcf7fb4e5d..6da8887538c 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 9370326a594..ab0f3226158 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 4cfa25b0f44..cc8e0a926f9 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 9b4696f21b2..38088b44349 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 1ca7ddb41d4..bef6fe16364 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 248a12aacef..deb95bb49fd 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 03368edf3f2..2e14102955c 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 2db4228fbb0..e0ff9ccd866 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 00000000000..28a6a3a0953
--- /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 f1255b0a182..9a6c27a0179 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 00000000000..8648470c81c
--- /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 6566fc0a322..c9de3f027aa 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 442d8076b20..5e0ab4201c0 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 58b2b8fc943..4b9542bbb35 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 fc5216b5d2c..729b4071787 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 75baf181a8c..dfb3bcbe00f 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 128e949db47..4a35745b30b 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 a57652fff39..3f5e30ddfa2 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 8b4be012669..3133990f04e 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 6bbedae83af..223f0a51409 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 9ba8fb7fcd2..8c734ef2c1e 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 79ea98c66fa..537f953bd7f 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 2ebe06c3405..b7eacad4d48 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 e980766bb84..5b20de130e0 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 1279553381e..8008d0bc80a 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 b4d72351cb9..858bdd038fb 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 22837a3f2f8..eae4740d448 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 240aad1acaa..69f84f0ea6f 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 a6ab5b58d9c..8a69cce40b6 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 711e84f6ed8..3cfc762f505 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 3dc93b542b3..51d7bdea286 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 8a5b6df3a97..07a3992abad 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 d9538208807..8e6a66e38db 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 fe84c88ec20..814909f1ee6 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 ab905869e95..43132927513 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 bfa508ddb0f..e85c8c0d1ad 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 cb4c54316cf..c3cdd00ddc4 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 cd9a2e138c8..132be74d2b8 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 a842025b9b5..3ac59a8a980 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 e59155c6607..b679a556b98 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 ddff37fa633..e320972cb22 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 704716f6f6d..9878c0fb385 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 040040a267d..bf1ae247da6 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 b84dddc7112..dc36a052766 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 deba28ec77e..6286baad939 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 0ded8bd6ec8..07710cf31d0 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 7c4917d77c0..e772cc0a97f 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 09d82062b97..fda4a6421c4 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 d6736531a0f..bcdcbb82270 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 ae8e227f3db..df653971272 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 73f8277f88f..3d87eabcd92 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 81db5715ee2..ba551f00f16 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 1ede1441cb1..491c8857b64 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 def52d07a4e..4b463cd140e 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 ea1a103c99b..0f2b67244af 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 283cf6b36b2..a65bc2bd8e7 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 9a3e495c769..31c42d1cae1 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 4f7f9e3ae0a..8be3f39891c 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 cf8924f9a2c..4facce3d936 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 3a9d14384a4..5335d3211c0 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 98b89ea9e31..c7bf8954b4e 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 3523a0bfa0f..79108d5d317 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);