fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / usb / gadget / serial.c
index 4d591c7..f8a3ec6 100644 (file)
@@ -17,7 +17,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 
 #include <linux/usb_ch9.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 #include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
 
 
-/* Wait Cond */
-
-#define __wait_cond_interruptible(wq, condition, lock, flags, ret)     \
-do {                                                                   \
-       wait_queue_t __wait;                                            \
-       init_waitqueue_entry(&__wait, current);                         \
-                                                                       \
-       add_wait_queue(&wq, &__wait);                                   \
-       for (;;) {                                                      \
-               set_current_state(TASK_INTERRUPTIBLE);                  \
-               if (condition)                                          \
-                       break;                                          \
-               if (!signal_pending(current)) {                         \
-                       spin_unlock_irqrestore(lock, flags);            \
-                       schedule();                                     \
-                       spin_lock_irqsave(lock, flags);                 \
-                       continue;                                       \
-               }                                                       \
-               ret = -ERESTARTSYS;                                     \
-               break;                                                  \
-       }                                                               \
-       current->state = TASK_RUNNING;                                  \
-       remove_wait_queue(&wq, &__wait);                                \
-} while (0)
-       
-#define wait_cond_interruptible(wq, condition, lock, flags)            \
-({                                                                     \
-       int __ret = 0;                                                  \
-       if (!(condition))                                               \
-               __wait_cond_interruptible(wq, condition, lock, flags,   \
-                                               __ret);                 \
-       __ret;                                                          \
-})
-
-#define __wait_cond_interruptible_timeout(wq, condition, lock, flags,  \
-                                               timeout, ret)           \
-do {                                                                   \
-       signed long __timeout = timeout;                                \
-       wait_queue_t __wait;                                            \
-       init_waitqueue_entry(&__wait, current);                         \
-                                                                       \
-       add_wait_queue(&wq, &__wait);                                   \
-       for (;;) {                                                      \
-               set_current_state(TASK_INTERRUPTIBLE);                  \
-               if (__timeout == 0)                                     \
-                       break;                                          \
-               if (condition)                                          \
-                       break;                                          \
-               if (!signal_pending(current)) {                         \
-                       spin_unlock_irqrestore(lock, flags);            \
-                       __timeout = schedule_timeout(__timeout);        \
-                       spin_lock_irqsave(lock, flags);                 \
-                       continue;                                       \
-               }                                                       \
-               ret = -ERESTARTSYS;                                     \
-               break;                                                  \
-       }                                                               \
-       current->state = TASK_RUNNING;                                  \
-       remove_wait_queue(&wq, &__wait);                                \
-} while (0)
-       
-#define wait_cond_interruptible_timeout(wq, condition, lock, flags,    \
-                                               timeout)                \
-({                                                                     \
-       int __ret = 0;                                                  \
-       if (!(condition))                                               \
-               __wait_cond_interruptible_timeout(wq, condition, lock,  \
-                                               flags, timeout, __ret); \
-       __ret;                                                          \
-})
-
-
 /* Defines */
 
-#define GS_VERSION_STR                 "v2.0"
-#define GS_VERSION_NUM                 0x0200
+#define GS_VERSION_STR                 "v2.2"
+#define GS_VERSION_NUM                 0x0202
 
 #define GS_LONG_NAME                   "Gadget Serial"
 #define GS_SHORT_NAME                  "g_serial"
@@ -273,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty);
 static void gs_break(struct tty_struct *tty, int break_state);
 static int  gs_ioctl(struct tty_struct *tty, struct file *file,
        unsigned int cmd, unsigned long arg);
-static void gs_set_termios(struct tty_struct *tty, struct termios *old);
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old);
 
 static int gs_send(struct gs_dev *dev);
 static int gs_send_packet(struct gs_dev *dev, char *packet,
@@ -300,18 +227,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
                u8 type, unsigned int index, int is_otg);
 
 static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
-       int kmalloc_flags);
+       gfp_t kmalloc_flags);
 static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
 
 static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,
-       int kmalloc_flags);
+       gfp_t kmalloc_flags);
 static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);
 
-static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags);
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
 static void gs_free_ports(struct gs_dev *dev);
 
 /* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags);
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
 static void gs_buf_free(struct gs_buf *gb);
 static void gs_buf_clear(struct gs_buf *gb);
 static unsigned int gs_buf_data_avail(struct gs_buf *gb);
@@ -344,7 +271,7 @@ static unsigned int use_acm = GS_DEFAULT_USE_ACM;
 
 
 /* tty driver struct */
-static struct tty_operations gs_tty_ops = {
+static const struct tty_operations gs_tty_ops = {
        .open =                 gs_open,
        .close =                gs_close,
        .write =                gs_write,
@@ -374,9 +301,6 @@ static struct usb_gadget_driver gs_gadget_driver = {
        .disconnect =           gs_disconnect,
        .driver = {
                .name =         GS_SHORT_NAME,
-               /* .shutdown = ... */
-               /* .suspend = ...  */
-               /* .resume = ...   */
        },
 };
 
@@ -663,12 +587,11 @@ static int __init gs_module_init(void)
        gs_tty_driver->owner = THIS_MODULE;
        gs_tty_driver->driver_name = GS_SHORT_NAME;
        gs_tty_driver->name = "ttygs";
-       gs_tty_driver->devfs_name = "usb/ttygs/";
        gs_tty_driver->major = GS_MAJOR;
        gs_tty_driver->minor_start = GS_MINOR_START;
        gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
        gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-       gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+       gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        gs_tty_driver->init_termios = tty_std_termios;
        gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
        tty_set_operations(gs_tty_driver, &gs_tty_ops);
@@ -846,9 +769,19 @@ exit_unlock_dev:
 /*
  * gs_close
  */
+
+#define GS_WRITE_FINISHED_EVENT_SAFELY(p)                      \
+({                                                             \
+       int cond;                                               \
+                                                               \
+       spin_lock_irq(&(p)->port_lock);                         \
+       cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \
+       spin_unlock_irq(&(p)->port_lock);                       \
+       cond;                                                   \
+})
+
 static void gs_close(struct tty_struct *tty, struct file *file)
 {
-       unsigned long flags;
        struct gs_port *port = tty->driver_data;
        struct semaphore *sem;
 
@@ -862,7 +795,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
        sem = &gs_open_close_sem[port->port_num];
        down(sem);
 
-       spin_lock_irqsave(&port->port_lock, flags);
+       spin_lock_irq(&port->port_lock);
 
        if (port->port_open_count == 0) {
                printk(KERN_ERR
@@ -890,10 +823,11 @@ static void gs_close(struct tty_struct *tty, struct file *file)
        /* wait for write buffer to drain, or */
        /* at most GS_CLOSE_TIMEOUT seconds */
        if (gs_buf_data_avail(port->port_write_buf) > 0) {
-               wait_cond_interruptible_timeout(port->port_write_wait,
-               port->port_dev == NULL
-               || gs_buf_data_avail(port->port_write_buf) == 0,
-               &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);
+               spin_unlock_irq(&port->port_lock);
+               wait_event_interruptible_timeout(port->port_write_wait,
+                                       GS_WRITE_FINISHED_EVENT_SAFELY(port),
+                                       GS_CLOSE_TIMEOUT * HZ);
+               spin_lock_irq(&port->port_lock);
        }
 
        /* free disconnected port on final close */
@@ -913,7 +847,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
                port->port_num, tty, file);
 
 exit:
-       spin_unlock_irqrestore(&port->port_lock, flags);
+       spin_unlock_irq(&port->port_lock);
        up(sem);
 }
 
@@ -1143,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
 /*
  * gs_set_termios
  */
-static void gs_set_termios(struct tty_struct *tty, struct termios *old)
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
 }
 
@@ -1186,12 +1120,15 @@ static int gs_send(struct gs_dev *dev)
 gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
                        list_del(&req_entry->re_entry);
                        req->length = len;
+                       spin_unlock_irqrestore(&dev->dev_lock, flags);
                        if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
                                printk(KERN_ERR
                                "gs_send: cannot queue read request, ret=%d\n",
                                        ret);
+                               spin_lock_irqsave(&dev->dev_lock, flags);
                                break;
                        }
+                       spin_lock_irqsave(&dev->dev_lock, flags);
                } else {
                        break;
                }
@@ -1269,6 +1206,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
        unsigned int len;
        struct gs_port *port;
        int ret;
+       struct tty_struct *tty;
 
        /* TEMPORARY -- only port 0 is supported right now */
        port = dev->dev_port[0];
@@ -1288,7 +1226,10 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
                goto exit;
        }
 
-       if (port->port_tty == NULL) {
+
+       tty = port->port_tty;
+
+       if (tty == NULL) {
                printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
                        port->port_num);
                ret = -EIO;
@@ -1302,20 +1243,13 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
                goto exit;
        }
 
-       len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count);
-       if (len < size)
-               size = len;
-
-       if (size > 0) {
-               memcpy(port->port_tty->flip.char_buf_ptr, packet, size);
-               port->port_tty->flip.char_buf_ptr += size;
-               port->port_tty->flip.count += size;
+       len = tty_buffer_request_room(tty, size);
+       if (len > 0) {
+               tty_insert_flip_string(tty, packet, len);
                tty_flip_buffer_push(port->port_tty);
                wake_up_interruptible(&port->port_tty->read_wait);
        }
-
        ret = 0;
-
 exit:
        spin_unlock(&port->port_lock);
        return ret;
@@ -1417,54 +1351,25 @@ requeue:
  * Called on module load.  Allocates and initializes the device
  * structure and a control request.
  */
-static int gs_bind(struct usb_gadget *gadget)
+static int __init gs_bind(struct usb_gadget *gadget)
 {
        int ret;
        struct usb_ep *ep;
        struct gs_dev *dev;
+       int gcnum;
 
-       /* device specific */
-       if (gadget_is_net2280(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0001);
-       } else if (gadget_is_pxa(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0002);
-       } else if (gadget_is_sh(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0003);
-               /* sh doesn't support multiple interfaces or configs */
-               use_acm = 0;
-       } else if (gadget_is_sa1100(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0004);
-               /* sa1100 doesn't support necessary endpoints */
+       /* Some controllers can't support CDC ACM:
+        * - sh doesn't support multiple interfaces or configs;
+        * - sa1100 doesn't have a third interrupt endpoint
+        */
+       if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget))
                use_acm = 0;
-       } else if (gadget_is_goku(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0005);
-       } else if (gadget_is_mq11xx(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0006);
-       } else if (gadget_is_omap(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
-       } else if (gadget_is_lh7a40x(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
-       } else if (gadget_is_n9604(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0009);
-       } else if (gadget_is_pxa27x(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0011);
-       } else if (gadget_is_s3c2410(gadget)) {
-               gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
-       } else if (gadget_is_at91(gadget)) {
+
+       gcnum = usb_gadget_controller_number(gadget);
+       if (gcnum >= 0)
                gs_device_desc.bcdDevice =
-                       __constant_cpu_to_le16(GS_VERSION_NUM|0x0013);
-       else {
+                               cpu_to_le16(GS_VERSION_NUM | gcnum);
+       else {
                printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
                        gadget->name);
                /* unrecognized, but safe unless bulk is REALLY quirky */
@@ -1529,7 +1434,7 @@ static int gs_bind(struct usb_gadget *gadget)
                return -ENOMEM;
 
        snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
-               system_utsname.sysname, system_utsname.release,
+               init_utsname()->sysname, init_utsname()->release,
                gadget->name);
 
        memset(dev, 0, sizeof(struct gs_dev));
@@ -1571,7 +1476,7 @@ autoconf_fail:
  * Called on module unload.  Frees the control request and device
  * structure.
  */
-static void gs_unbind(struct usb_gadget *gadget)
+static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
 {
        struct gs_dev *dev = get_gadget_data(gadget);
 
@@ -1607,9 +1512,9 @@ static int gs_setup(struct usb_gadget *gadget,
        int ret = -EOPNOTSUPP;
        struct gs_dev *dev = get_gadget_data(gadget);
        struct usb_request *req = dev->dev_ctrl_req;
-       u16 wIndex = ctrl->wIndex;
-       u16 wValue = ctrl->wValue;
-       u16 wLength = ctrl->wLength;
+       u16 wIndex = le16_to_cpu(ctrl->wIndex);
+       u16 wValue = le16_to_cpu(ctrl->wValue);
+       u16 wLength = le16_to_cpu(ctrl->wLength);
 
        switch (ctrl->bRequestType & USB_TYPE_MASK) {
        case USB_TYPE_STANDARD:
@@ -1651,9 +1556,9 @@ static int gs_setup_standard(struct usb_gadget *gadget,
        int ret = -EOPNOTSUPP;
        struct gs_dev *dev = get_gadget_data(gadget);
        struct usb_request *req = dev->dev_ctrl_req;
-       u16 wIndex = ctrl->wIndex;
-       u16 wValue = ctrl->wValue;
-       u16 wLength = ctrl->wLength;
+       u16 wIndex = le16_to_cpu(ctrl->wIndex);
+       u16 wValue = le16_to_cpu(ctrl->wValue);
+       u16 wLength = le16_to_cpu(ctrl->wLength);
 
        switch (ctrl->bRequest) {
        case USB_REQ_GET_DESCRIPTOR:
@@ -1782,9 +1687,9 @@ static int gs_setup_class(struct usb_gadget *gadget,
        struct gs_dev *dev = get_gadget_data(gadget);
        struct gs_port *port = dev->dev_port[0];        /* ACM only has one port */
        struct usb_request *req = dev->dev_ctrl_req;
-       u16 wIndex = ctrl->wIndex;
-       u16 wValue = ctrl->wValue;
-       u16 wLength = ctrl->wLength;
+       u16 wIndex = le16_to_cpu(ctrl->wIndex);
+       u16 wValue = le16_to_cpu(ctrl->wValue);
+       u16 wLength = le16_to_cpu(ctrl->wLength);
 
        switch (ctrl->bRequest) {
        case USB_CDC_REQ_SET_LINE_CODING:
@@ -2119,7 +2024,8 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
  * Allocate a usb_request and its buffer.  Returns a pointer to the
  * usb_request or NULL if there is an error.
  */
-static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int kmalloc_flags)
+static struct usb_request *
+gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
 {
        struct usb_request *req;
 
@@ -2159,7 +2065,8 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
  * Allocates a request and its buffer, using the given
  * endpoint, buffer len, and kmalloc flags.
  */
-static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, int kmalloc_flags)
+static struct gs_req_entry *
+gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
 {
        struct gs_req_entry     *req;
 
@@ -2200,7 +2107,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req)
  *
  * The device lock is normally held when calling this function.
  */
-static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags)
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
 {
        int i;
        struct gs_port *port;
@@ -2209,10 +2116,9 @@ static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags)
                return -EIO;
 
        for (i=0; i<GS_NUM_PORTS; i++) {
-               if ((port=(struct gs_port *)kmalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
+               if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
                        return -ENOMEM;
 
-               memset(port, 0, sizeof(struct gs_port));
                port->port_dev = dev;
                port->port_num = i;
                port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
@@ -2282,14 +2188,14 @@ static void gs_free_ports(struct gs_dev *dev)
  *
  * Allocate a circular buffer and all associated memory.
  */
-static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags)
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
 {
        struct gs_buf *gb;
 
        if (size == 0)
                return NULL;
 
-       gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags);
+       gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
        if (gb == NULL)
                return NULL;