This patch ports the pl2303 USB-Serial's attach() and shutdown() methods to
the Serial Core version of the USB-Serial's core.

 Also note that they have been renamed to avoid name collision in the next
patches:

  pl2303_startup()  -> pl2303_attach()
  pl2303_shutdown() -> pl2303_usb_shutdown()

  Additionally, this patch also adds refcouting to the struct pl2303_private
structure.

 This is needed because the p2l303 Serial Core version cannot free its
dynamic allocated struct pl2303_private in pl2303_usb_shutdown() anymore,
because we can get a NULL pointer in the other methods (eg. pl2303_shutdown()).

Signed-off-by: Luiz Fernando N. Capitulino <[EMAIL PROTECTED]>
---
 drivers/usb/serial/pl2303.c |   50 +++++++++++++++++++++++++------------------
 1 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index f9300b8..0b60c04 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -20,12 +20,12 @@ #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
-#include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
+#include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include "usb-serial.h"
@@ -145,8 +145,8 @@ static void pl2303_break_ctl(struct usb_
 static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
 static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
                            unsigned int set, unsigned int clear);
-static int pl2303_startup (struct usb_serial *serial);
-static void pl2303_shutdown (struct usb_serial *serial);
+static int pl2303_attach(struct usb_serial *serial);
+static void pl2303_usb_shutdown(struct usb_serial *serial);
 static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
 static void pl2303_buf_free(struct pl2303_buf *pb);
 static void pl2303_buf_clear(struct pl2303_buf *pb);
@@ -182,8 +182,8 @@ static struct usb_serial_driver pl2303_d
        .write_bulk_callback =  pl2303_write_bulk_callback,
        .write_room =           pl2303_write_room,
        .chars_in_buffer =      pl2303_chars_in_buffer,
-       .attach =               pl2303_startup,
-       .shutdown =             pl2303_shutdown,
+       .attach =               pl2303_attach,
+       .shutdown =             pl2303_usb_shutdown,
 };
 
 enum pl2303_type {
@@ -201,10 +201,20 @@ struct pl2303_private {
        u8 line_status;
        u8 termios_initialized;
        enum pl2303_type type;
+       struct kref kref;
 };
+#define to_pl2303_private(p) container_of(p, struct pl2303_private, kref)
 
+static void destroy_priv(struct kref *kref)
+{
+       struct pl2303_private *priv;
+
+       priv = to_pl2303_private(kref);
+       pl2303_buf_free(priv->buf);
+       kfree(priv);
+}
 
-static int pl2303_startup (struct usb_serial *serial)
+static int pl2303_attach(struct usb_serial *serial)
 {
        struct pl2303_private *priv;
        enum pl2303_type type = type_0;
@@ -222,15 +232,18 @@ static int pl2303_startup (struct usb_se
 
        for (i = 0; i < serial->num_ports; ++i) {
                priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
-               if (!priv)
+               if (!priv) {
+                       err("Couldn't allocate memory");
                        goto cleanup;
+               }
+               kref_init(&priv->kref);
                spin_lock_init(&priv->lock);
                priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
-               if (priv->buf == NULL) {
-                       kfree(priv);
+               if (!priv->buf) {
+                       err("Couldn't allocate memory");
+                       kref_put(&priv->kref, destroy_priv);
                        goto cleanup;
                }
-               init_waitqueue_head(&priv->delta_msr_wait);
                priv->type = type;
                usb_set_serial_port_data(serial->port[i], priv);
        }
@@ -239,8 +252,7 @@ static int pl2303_startup (struct usb_se
 cleanup:
        for (--i; i>=0; --i) {
                priv = usb_get_serial_port_data(serial->port[i]);
-               pl2303_buf_free(priv->buf);
-               kfree(priv);
+               kref_put(&priv->kref, destroy_priv);
                usb_set_serial_port_data(serial->port[i], NULL);
        }
        return -ENOMEM;
@@ -786,22 +798,18 @@ static void pl2303_break_ctl (struct usb
                dbg("error sending break = %d", result);
 }
 
-
-static void pl2303_shutdown (struct usb_serial *serial)
+static void pl2303_usb_shutdown(struct usb_serial *serial)
 {
        int i;
        struct pl2303_private *priv;
 
-       dbg("");
+       dbg("%s", serial->type->description);
 
        for (i = 0; i < serial->num_ports; ++i) {
                priv = usb_get_serial_port_data(serial->port[i]);
-               if (priv) {
-                       pl2303_buf_free(priv->buf);
-                       kfree(priv);
-                       usb_set_serial_port_data(serial->port[i], NULL);
-               }
-       }               
+               if (priv)
+                       kref_put(&priv->kref, destroy_priv);
+       }
 }
 
 static void pl2303_update_line_status(struct usb_serial_port *port,
-- 
1.3.3.g0825d



_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to