USB: ipaq: reimplement using generic framework
authorJohan Hovold <jhovold@gmail.com>
Sat, 15 May 2010 15:53:46 +0000 (17:53 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 20 May 2010 20:21:48 +0000 (13:21 -0700)
Kill custom fifo, read and write implementations (single-urb and fifo,
but still maintained list of 256*256b urb buffers per port).

Compile-only tested.

Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipaq.h [deleted file]

index 87b1146..28913fa 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include "ipaq.h"
 
 #define KP_RETRIES     100
 
@@ -64,7 +63,7 @@
  * Version Information
  */
 
-#define DRIVER_VERSION "v0.5"
+#define DRIVER_VERSION "v1.0"
 #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
 #define DRIVER_DESC "USB PocketPC PDA driver"
 
@@ -76,20 +75,8 @@ static int initial_wait;
 /* Function prototypes for an ipaq */
 static int  ipaq_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
-static void ipaq_close(struct usb_serial_port *port);
 static int  ipaq_calc_num_ports(struct usb_serial *serial);
 static int  ipaq_startup(struct usb_serial *serial);
-static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
-                       const unsigned char *buf, int count);
-static int ipaq_write_bulk(struct usb_serial_port *port,
-                               const unsigned char *buf, int count);
-static void ipaq_write_gather(struct usb_serial_port *port);
-static void ipaq_read_bulk_callback(struct urb *urb);
-static void ipaq_write_bulk_callback(struct urb *urb);
-static int ipaq_write_room(struct tty_struct *tty);
-static int ipaq_chars_in_buffer(struct tty_struct *tty);
-static void ipaq_destroy_lists(struct usb_serial_port *port);
-
 
 static struct usb_device_id ipaq_id_table [] = {
        /* The first entry is a placeholder for the insmod-specified device */
@@ -558,7 +545,7 @@ static struct usb_driver ipaq_driver = {
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     ipaq_id_table,
-       .no_dynamic_id =        1,
+       .no_dynamic_id =        1,
 };
 
 
@@ -569,67 +556,24 @@ static struct usb_serial_driver ipaq_device = {
                .name =         "ipaq",
        },
        .description =          "PocketPC PDA",
-       .usb_driver =           &ipaq_driver,
+       .usb_driver =           &ipaq_driver,
        .id_table =             ipaq_id_table,
-       .bulk_in_size =         URBDATA_SIZE,
-       .bulk_out_size =        URBDATA_SIZE,
+       .bulk_in_size =         256,
+       .bulk_out_size =        256,
        .open =                 ipaq_open,
-       .close =                ipaq_close,
        .attach =               ipaq_startup,
        .calc_num_ports =       ipaq_calc_num_ports,
-       .write =                ipaq_write,
-       .write_room =           ipaq_write_room,
-       .chars_in_buffer =      ipaq_chars_in_buffer,
-       .read_bulk_callback =   ipaq_read_bulk_callback,
-       .write_bulk_callback =  ipaq_write_bulk_callback,
 };
 
-static spinlock_t      write_list_lock;
-static int             bytes_in;
-static int             bytes_out;
-
 static int ipaq_open(struct tty_struct *tty,
                        struct usb_serial_port *port)
 {
        struct usb_serial       *serial = port->serial;
-       struct ipaq_private     *priv;
-       struct ipaq_packet      *pkt;
-       int                     i, result = 0;
+       int                     result = 0;
        int                     retries = connect_retries;
 
        dbg("%s - port %d", __func__, port->number);
 
-       bytes_in = 0;
-       bytes_out = 0;
-       priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
-       if (priv == NULL) {
-               dev_err(&port->dev, "%s - Out of memory\n", __func__);
-               return -ENOMEM;
-       }
-       usb_set_serial_port_data(port, priv);
-       priv->active = 0;
-       priv->queue_len = 0;
-       priv->free_len = 0;
-       INIT_LIST_HEAD(&priv->queue);
-       INIT_LIST_HEAD(&priv->freelist);
-
-       for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
-               pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
-               if (pkt == NULL)
-                       goto enomem;
-
-               pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
-               if (pkt->data == NULL) {
-                       kfree(pkt);
-                       goto enomem;
-               }
-               pkt->len = 0;
-               pkt->written = 0;
-               INIT_LIST_HEAD(&pkt->list);
-               list_add(&pkt->list, &priv->freelist);
-               priv->free_len += PACKET_SIZE;
-       }
-
        msleep(1000*initial_wait);
 
        /*
@@ -639,7 +583,6 @@ static int ipaq_open(struct tty_struct *tty,
         * through. Since this has a reasonably high failure rate, we retry
         * several times.
         */
-
        while (retries--) {
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
@@ -649,269 +592,15 @@ static int ipaq_open(struct tty_struct *tty,
 
                msleep(1000);
        }
-
        if (!retries && result) {
-               dev_err(&port->dev, "%s - failed doing control urb, error %d\n",                        __func__, result);
-               goto error;
-       }
-
-       /* Start reading from the device */
-       usb_fill_bulk_urb(port->read_urb, serial->dev,
-               usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-               port->read_urb->transfer_buffer,
-               port->read_urb->transfer_buffer_length,
-               ipaq_read_bulk_callback, port);
-
-       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-       if (result) {
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
-                       __func__, result);
-               goto error;
-       }
-
-       return 0;
-
-enomem:
-       result = -ENOMEM;
-       dev_err(&port->dev, "%s - Out of memory\n", __func__);
-error:
-       ipaq_destroy_lists(port);
-       kfree(priv);
-       return result;
-}
-
-
-static void ipaq_close(struct usb_serial_port *port)
-{
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-
-       dbg("%s - port %d", __func__, port->number);
-
-       /*
-        * shut down bulk read and write
-        */
-       usb_kill_urb(port->write_urb);
-       usb_kill_urb(port->read_urb);
-       ipaq_destroy_lists(port);
-       kfree(priv);
-       usb_set_serial_port_data(port, NULL);
-
-       /* Uncomment the following line if you want to see some statistics
-        * in your syslog */
-       /* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
-}
-
-static void ipaq_read_bulk_callback(struct urb *urb)
-{
-       struct usb_serial_port  *port = urb->context;
-       struct tty_struct       *tty;
-       unsigned char           *data = urb->transfer_buffer;
-       int                     result;
-       int status = urb->status;
-
-       dbg("%s - port %d", __func__, port->number);
-
-       if (status) {
-               dbg("%s - nonzero read bulk status received: %d",
-                   __func__, status);
-               return;
+               dev_err(&port->dev, "%s - failed doing control urb, error %d\n",
+                                                       __func__, result);
+               return result;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __func__,
-                                               urb->actual_length, data);
-
-       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);
-               bytes_in += urb->actual_length;
-       }
-       tty_kref_put(tty);
-
-       /* Continue trying to always read  */
-       usb_fill_bulk_urb(port->read_urb, port->serial->dev,
-           usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
-           port->read_urb->transfer_buffer,
-           port->read_urb->transfer_buffer_length,
-           ipaq_read_bulk_callback, port);
-       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed resubmitting read urb, error %d\n",
-                       __func__, result);
-       return;
+       return usb_serial_generic_open(tty, port);
 }
 
-static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
-                       const unsigned char *buf, int count)
-{
-       const unsigned char     *current_position = buf;
-       int                     bytes_sent = 0;
-       int                     transfer_size;
-
-       dbg("%s - port %d", __func__, port->number);
-
-       while (count > 0) {
-               transfer_size = min(count, PACKET_SIZE);
-               if (ipaq_write_bulk(port, current_position, transfer_size))
-                       break;
-               current_position += transfer_size;
-               bytes_sent += transfer_size;
-               count -= transfer_size;
-               bytes_out += transfer_size;
-       }
-
-       return bytes_sent;
-}
-
-static int ipaq_write_bulk(struct usb_serial_port *port,
-                                       const unsigned char *buf, int count)
-{
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-       struct ipaq_packet      *pkt = NULL;
-       int                     result = 0;
-       unsigned long           flags;
-
-       if (priv->free_len <= 0) {
-               dbg("%s - we're stuffed", __func__);
-               return -EAGAIN;
-       }
-
-       spin_lock_irqsave(&write_list_lock, flags);
-       if (!list_empty(&priv->freelist)) {
-               pkt = list_entry(priv->freelist.next, struct ipaq_packet, list);
-               list_del(&pkt->list);
-               priv->free_len -= PACKET_SIZE;
-       }
-       spin_unlock_irqrestore(&write_list_lock, flags);
-       if (pkt == NULL) {
-               dbg("%s - we're stuffed", __func__);
-               return -EAGAIN;
-       }
-
-       memcpy(pkt->data, buf, count);
-       usb_serial_debug_data(debug, &port->dev, __func__, count, pkt->data);
-
-       pkt->len = count;
-       pkt->written = 0;
-       spin_lock_irqsave(&write_list_lock, flags);
-       list_add_tail(&pkt->list, &priv->queue);
-       priv->queue_len += count;
-       if (priv->active == 0) {
-               priv->active = 1;
-               ipaq_write_gather(port);
-               spin_unlock_irqrestore(&write_list_lock, flags);
-               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-               if (result)
-                       dev_err(&port->dev,
-                               "%s - failed submitting write urb, error %d\n",
-                               __func__, result);
-       } else {
-               spin_unlock_irqrestore(&write_list_lock, flags);
-       }
-       return result;
-}
-
-static void ipaq_write_gather(struct usb_serial_port *port)
-{
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-       struct usb_serial       *serial = port->serial;
-       int                     count, room;
-       struct ipaq_packet      *pkt, *tmp;
-       struct urb              *urb = port->write_urb;
-
-       room = URBDATA_SIZE;
-       list_for_each_entry_safe(pkt, tmp, &priv->queue, list) {
-               count = min(room, (int)(pkt->len - pkt->written));
-               memcpy(urb->transfer_buffer + (URBDATA_SIZE - room),
-                      pkt->data + pkt->written, count);
-               room -= count;
-               pkt->written += count;
-               priv->queue_len -= count;
-               if (pkt->written == pkt->len) {
-                       list_move(&pkt->list, &priv->freelist);
-                       priv->free_len += PACKET_SIZE;
-               }
-               if (room == 0)
-                       break;
-       }
-
-       count = URBDATA_SIZE - room;
-       usb_fill_bulk_urb(port->write_urb, serial->dev,
-               usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
-               port->write_urb->transfer_buffer, count,
-               ipaq_write_bulk_callback, port);
-       return;
-}
-
-static void ipaq_write_bulk_callback(struct urb *urb)
-{
-       struct usb_serial_port  *port = urb->context;
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-       unsigned long           flags;
-       int                     result;
-       int status = urb->status;
-
-       dbg("%s - port %d", __func__, port->number);
-
-       if (status) {
-               dbg("%s - nonzero write bulk status received: %d",
-                   __func__, status);
-               return;
-       }
-
-       spin_lock_irqsave(&write_list_lock, flags);
-       if (!list_empty(&priv->queue)) {
-               ipaq_write_gather(port);
-               spin_unlock_irqrestore(&write_list_lock, flags);
-               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-               if (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);
-       }
-
-       usb_serial_port_softint(port);
-}
-
-static int ipaq_write_room(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-
-       dbg("%s - freelen %d", __func__, priv->free_len);
-       return priv->free_len;
-}
-
-static int ipaq_chars_in_buffer(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-
-       dbg("%s - queuelen %d", __func__, priv->queue_len);
-       return priv->queue_len;
-}
-
-static void ipaq_destroy_lists(struct usb_serial_port *port)
-{
-       struct ipaq_private     *priv = usb_get_serial_port_data(port);
-       struct ipaq_packet      *pkt, *tmp;
-
-       list_for_each_entry_safe(pkt, tmp, &priv->queue, list) {
-               kfree(pkt->data);
-               kfree(pkt);
-       }
-       list_for_each_entry_safe(pkt, tmp, &priv->freelist, list) {
-               kfree(pkt->data);
-               kfree(pkt);
-       }
-}
-
-
 static int ipaq_calc_num_ports(struct usb_serial *serial)
 {
        /*
@@ -970,7 +659,6 @@ static int ipaq_startup(struct usb_serial *serial)
 static int __init ipaq_init(void)
 {
        int retval;
-       spin_lock_init(&write_list_lock);
        retval = usb_serial_register(&ipaq_device);
        if (retval)
                goto failed_usb_serial_register;
@@ -991,7 +679,6 @@ failed_usb_serial_register:
        return retval;
 }
 
-
 static void __exit ipaq_exit(void)
 {
        usb_deregister(&ipaq_driver);
diff --git a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
deleted file mode 100644 (file)
index 2b90359..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * USB Compaq iPAQ driver
- *
- *     Copyright (C) 2001 - 2002
- *         Ganesh Varadarajan <ganesh@veritas.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; either version 2 of the License, or
- *     (at your option) any later version.
- *
- */
-
-#ifndef __LINUX_USB_SERIAL_IPAQ_H
-#define __LINUX_USB_SERIAL_IPAQ_H
-
-/*
- * Since we can't queue our bulk write urbs (don't know why - it just
- * doesn't work), we can send down only one write urb at a time. The simplistic
- * approach taken by the generic usbserial driver will work, but it's not good
- * for performance. Therefore, we buffer upto URBDATA_QUEUE_MAX bytes of write
- * requests coming from the line discipline. This is done by chaining them
- * in lists of struct ipaq_packet, each packet holding a maximum of
- * PACKET_SIZE bytes.
- *
- * ipaq_write() can be called from bottom half context; hence we can't
- * allocate memory for packets there. So we initialize a pool of packets at
- * the first open and maintain a freelist.
- *
- * The value of PACKET_SIZE was empirically determined by
- * checking the maximum write sizes sent down by the ppp ldisc.
- * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size.
- */
-
-struct ipaq_packet {
-       char                    *data;
-       size_t                  len;
-       size_t                  written;
-       struct list_head        list;
-};
-
-struct ipaq_private {
-       int                     active;
-       int                     queue_len;
-       int                     free_len;
-       struct list_head        queue;
-       struct list_head        freelist;
-};
-
-#define URBDATA_SIZE           4096
-#define URBDATA_QUEUE_MAX      (64 * 1024)
-#define PACKET_SIZE            256
-
-#endif