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