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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel