Commit bf0373f1 authored by Won Kang's avatar Won Kang Committed by Greg Kroah-Hartman

staging: gdm7240: a TTY rewrite according to the latest TTY APIs

Fixed mis-use of mutex for gdm_table. gdm_table is refered to only
inside tty_install and port destrcut, and usb callbacks use internal
reference which was saved during urb submission
Signed-off-by: default avatarWon Kang <wonkang@gctsemi.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7ee4c1b9
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/usb/cdc.h> #include <linux/usb/cdc.h>
#include "gdm_mux.h" #include "gdm_mux.h"
#include "gdm_tty.h"
struct workqueue_struct *mux_rx_wq; struct workqueue_struct *mux_rx_wq;
...@@ -196,7 +195,7 @@ static int up_to_host(struct mux_rx *r) ...@@ -196,7 +195,7 @@ static int up_to_host(struct mux_rx *r)
ret = r->callback(mux_header->data, ret = r->callback(mux_header->data,
payload_size, payload_size,
index, index,
mux_dev->minor[index], mux_dev->tty_dev,
RECV_PACKET_PROCESS_CONTINUE RECV_PACKET_PROCESS_CONTINUE
); );
if (ret == TO_HOST_BUFFER_REQUEST_FAIL) { if (ret == TO_HOST_BUFFER_REQUEST_FAIL) {
...@@ -209,7 +208,7 @@ static int up_to_host(struct mux_rx *r) ...@@ -209,7 +208,7 @@ static int up_to_host(struct mux_rx *r)
ret = r->callback(NULL, ret = r->callback(NULL,
0, 0,
index, index,
mux_dev->minor[index], mux_dev->tty_dev,
RECV_PACKET_PROCESS_COMPLETE RECV_PACKET_PROCESS_COMPLETE
); );
break; break;
...@@ -283,7 +282,7 @@ static void gdm_mux_rcv_complete(struct urb *urb) ...@@ -283,7 +282,7 @@ static void gdm_mux_rcv_complete(struct urb *urb)
} }
static int gdm_mux_recv(void *priv_dev, static int gdm_mux_recv(void *priv_dev,
int (*cb)(void *data, int len, int tty_index, int minor, int complete) int (*cb)(void *data, int len, int tty_index, struct tty_dev *tty_dev, int complete)
) )
{ {
struct mux_dev *mux_dev = priv_dev; struct mux_dev *mux_dev = priv_dev;
...@@ -562,7 +561,7 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -562,7 +561,7 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id
goto out; goto out;
} }
for (i = 0; i < TTY_MAX_COUNT; i++) for (i = 0; i < TTY_MAX_COUNT; i++)
mux_dev->minor[i] = tty_dev->minor[i]; mux_dev->tty_dev = tty_dev;
out: out:
if (ret < 0) { if (ret < 0) {
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/list.h> #include <linux/list.h>
#include "gdm_tty.h"
#define PM_NORMAL 0 #define PM_NORMAL 0
#define PM_SUSPEND 1 #define PM_SUSPEND 1
...@@ -57,7 +59,10 @@ struct mux_rx { ...@@ -57,7 +59,10 @@ struct mux_rx {
void *mux_dev; void *mux_dev;
u32 offset; u32 offset;
u32 len; u32 len;
int (*callback)(void *data, int len, int tty_index, int minor, int (*callback)(void *data,
int len,
int tty_index,
struct tty_dev *tty_dev,
int complete); int complete);
}; };
...@@ -78,10 +83,13 @@ struct mux_dev { ...@@ -78,10 +83,13 @@ struct mux_dev {
struct delayed_work work_rx; struct delayed_work work_rx;
struct usb_interface *intf; struct usb_interface *intf;
int usb_state; int usb_state;
int (*rx_cb)(void *data, int len, int tty_index, int minor, int (*rx_cb)(void *data,
int len,
int tty_index,
struct tty_dev *tty_dev,
int complete); int complete);
spinlock_t write_lock; spinlock_t write_lock;
u8 minor[2]; struct tty_dev *tty_dev;
}; };
#endif /* _GDM_MUX_H_ */ #endif /* _GDM_MUX_H_ */
...@@ -89,19 +89,22 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -89,19 +89,22 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
mutex_lock(&gdm_table_lock); mutex_lock(&gdm_table_lock);
gdm = gdm_table[i][j]; gdm = gdm_table[i][j];
mutex_unlock(&gdm_table_lock); if (gdm == NULL) {
if (gdm == NULL) mutex_unlock(&gdm_table_lock);
return -ENODEV; return -ENODEV;
}
tty_port_get(&gdm->port); tty_port_get(&gdm->port);
ret = tty_standard_install(driver, tty); ret = tty_standard_install(driver, tty);
if (ret) { if (ret) {
tty_port_put(&gdm->port); tty_port_put(&gdm->port);
mutex_unlock(&gdm_table_lock);
return ret; return ret;
} }
tty->driver_data = gdm; tty->driver_data = gdm;
mutex_unlock(&gdm_table_lock);
return 0; return 0;
} }
...@@ -130,14 +133,13 @@ static void gdm_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -130,14 +133,13 @@ static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
tty_port_close(&gdm->port, tty, filp); tty_port_close(&gdm->port, tty, filp);
} }
static int gdm_tty_recv_complete(void *data, int len, int index, int minor, int complete) static int gdm_tty_recv_complete(void *data,
int len,
int index,
struct tty_dev *tty_dev,
int complete)
{ {
struct gdm *gdm; struct gdm *gdm = tty_dev->gdm[index];
mutex_lock(&gdm_table_lock);
gdm = gdm_table[index][minor];
mutex_unlock(&gdm_table_lock);
if (!GDM_TTY_READY(gdm)) { if (!GDM_TTY_READY(gdm)) {
if (complete == RECV_PACKET_PROCESS_COMPLETE) if (complete == RECV_PACKET_PROCESS_COMPLETE)
gdm_tty_recv(gdm, gdm_tty_recv_complete); gdm_tty_recv(gdm, gdm_tty_recv_complete);
...@@ -223,31 +225,29 @@ int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) ...@@ -223,31 +225,29 @@ int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device)
return -ENOMEM; return -ENOMEM;
mutex_lock(&gdm_table_lock); mutex_lock(&gdm_table_lock);
for (j = 0; j < GDM_TTY_MINOR; j++) { for (j = 0; j < GDM_TTY_MINOR; j++) {
if (!gdm_table[i][j]) if (!gdm_table[i][j])
break; break;
} }
if (j == GDM_TTY_MINOR) { if (j == GDM_TTY_MINOR) {
tty_dev->minor[i] = GDM_TTY_MINOR; kfree(gdm);
mutex_unlock(&gdm_table_lock); mutex_unlock(&gdm_table_lock);
return -EINVAL; return -EINVAL;
} }
gdm_table[i][j] = gdm; gdm_table[i][j] = gdm;
mutex_unlock(&gdm_table_lock); mutex_unlock(&gdm_table_lock);
tty_dev->minor[i] = j; tty_dev->gdm[i] = gdm;
tty_port_init(&gdm->port); tty_port_init(&gdm->port);
gdm->port.ops = &gdm_port_ops; gdm->port.ops = &gdm_port_ops;
gdm->index = i; gdm->index = i;
gdm->minor = j; gdm->minor = j;
gdm->tty_dev = tty_dev; gdm->tty_dev = tty_dev;
tty_port_register_device(&gdm->port, gdm_driver[i], j, device); tty_port_register_device(&gdm->port, gdm_driver[i], gdm->minor, device);
} }
for (i = 0; i < MAX_ISSUE_NUM; i++) for (i = 0; i < MAX_ISSUE_NUM; i++)
...@@ -261,31 +261,24 @@ void unregister_lte_tty_device(struct tty_dev *tty_dev) ...@@ -261,31 +261,24 @@ void unregister_lte_tty_device(struct tty_dev *tty_dev)
struct gdm *gdm; struct gdm *gdm;
struct tty_struct *tty; struct tty_struct *tty;
int i; int i;
int j;
for (i = 0; i < TTY_MAX_COUNT; i++) { for (i = 0; i < TTY_MAX_COUNT; i++) {
gdm = tty_dev->gdm[i];
j = tty_dev->minor[i]; if (!gdm)
if (j >= GDM_TTY_MINOR)
continue; continue;
mutex_lock(&gdm_table_lock); mutex_lock(&gdm_table_lock);
gdm = gdm_table[i][j]; gdm_table[gdm->index][gdm->minor] = NULL;
mutex_unlock(&gdm_table_lock); mutex_unlock(&gdm_table_lock);
if (!gdm)
continue;
tty = tty_port_tty_get(&gdm->port); tty = tty_port_tty_get(&gdm->port);
if (tty) { if (tty) {
tty_vhangup(tty); tty_vhangup(tty);
tty_kref_put(tty); tty_kref_put(tty);
} }
tty_unregister_device(gdm_driver[i], j); tty_unregister_device(gdm_driver[i], gdm->minor);
tty_port_put(&gdm->port); tty_port_put(&gdm->port);
} }
} }
......
...@@ -33,17 +33,6 @@ enum RECV_PACKET_PROCESS { ...@@ -33,17 +33,6 @@ enum RECV_PACKET_PROCESS {
RECV_PACKET_PROCESS_CONTINUE = 1, RECV_PACKET_PROCESS_CONTINUE = 1,
}; };
struct tty_dev {
void *priv_dev;
int (*send_func)(void *priv_dev, void *data, int len, int tty_index,
void (*cb)(void *cb_data), void *cb_data);
int (*recv_func)(void *priv_dev, int (*cb)(void *data, int len,
int tty_index, int minor, int complete));
int (*send_control)(void *priv_dev, int request, int value, void *data,
int len);
u8 minor[2];
};
struct gdm { struct gdm {
struct tty_dev *tty_dev; struct tty_dev *tty_dev;
struct tty_port port; struct tty_port port;
...@@ -51,6 +40,28 @@ struct gdm { ...@@ -51,6 +40,28 @@ struct gdm {
unsigned int minor; unsigned int minor;
}; };
struct tty_dev {
void *priv_dev;
int (*send_func)(void *priv_dev,
void *data,
int len,
int tty_index,
void (*cb)(void *cb_data),
void *cb_data);
int (*recv_func)(void *priv_dev,
int (*cb)(void *data,
int len,
int tty_index,
struct tty_dev *tty_dev,
int complete));
int (*send_control)(void *priv_dev,
int request,
int value,
void *data,
int len);
struct gdm *gdm[2];
};
int register_lte_tty_driver(void); int register_lte_tty_driver(void);
void unregister_lte_tty_driver(void); void unregister_lte_tty_driver(void);
int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev); int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment