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

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
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include <linux/usb/cdc.h>

#include "gdm_mux.h"
#include "gdm_tty.h"

struct workqueue_struct *mux_rx_wq;

@@ -196,7 +195,7 @@ static int up_to_host(struct mux_rx *r)
		ret = r->callback(mux_header->data,
				payload_size,
				index,
				mux_dev->minor[index],
				mux_dev->tty_dev,
				RECV_PACKET_PROCESS_CONTINUE
				);
		if (ret == TO_HOST_BUFFER_REQUEST_FAIL) {
@@ -209,7 +208,7 @@ static int up_to_host(struct mux_rx *r)
			ret = r->callback(NULL,
					0,
					index,
					mux_dev->minor[index],
					mux_dev->tty_dev,
					RECV_PACKET_PROCESS_COMPLETE
					);
			break;
@@ -283,7 +282,7 @@ static void gdm_mux_rcv_complete(struct urb *urb)
}

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;
@@ -562,7 +561,7 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id
		goto out;
	}
	for (i = 0; i < TTY_MAX_COUNT; i++)
		mux_dev->minor[i] = tty_dev->minor[i];
		mux_dev->tty_dev = tty_dev;

out:
	if (ret < 0) {
+11 −3
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#include <linux/usb.h>
#include <linux/list.h>

#include "gdm_tty.h"

#define PM_NORMAL 0
#define PM_SUSPEND 1

@@ -57,7 +59,10 @@ struct mux_rx {
	void *mux_dev;
	u32 offset;
	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);
};

@@ -78,10 +83,13 @@ struct mux_dev {
	struct delayed_work work_rx;
	struct usb_interface *intf;
	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);
	spinlock_t write_lock;
	u8 minor[2];
	struct tty_dev *tty_dev;
};

#endif /* _GDM_MUX_H_ */
+19 −26
Original line number Diff line number Diff line
@@ -89,19 +89,22 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)

	mutex_lock(&gdm_table_lock);
	gdm = gdm_table[i][j];
	if (gdm == NULL) {
		mutex_unlock(&gdm_table_lock);
	if (gdm == NULL)
		return -ENODEV;
	}

	tty_port_get(&gdm->port);

	ret = tty_standard_install(driver, tty);
	if (ret) {
		tty_port_put(&gdm->port);
		mutex_unlock(&gdm_table_lock);
		return ret;
	}

	tty->driver_data = gdm;
	mutex_unlock(&gdm_table_lock);

	return 0;
}
@@ -130,14 +133,13 @@ static void gdm_tty_close(struct tty_struct *tty, struct file *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;

	mutex_lock(&gdm_table_lock);
	gdm = gdm_table[index][minor];
	mutex_unlock(&gdm_table_lock);

	struct gdm *gdm = tty_dev->gdm[index];
	if (!GDM_TTY_READY(gdm)) {
		if (complete == RECV_PACKET_PROCESS_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)
			return -ENOMEM;

		mutex_lock(&gdm_table_lock);

		for (j = 0; j < GDM_TTY_MINOR; j++) {
			if (!gdm_table[i][j])
				break;
		}

		if (j == GDM_TTY_MINOR) {
			tty_dev->minor[i] = GDM_TTY_MINOR;
			kfree(gdm);
			mutex_unlock(&gdm_table_lock);
			return -EINVAL;
		}

		gdm_table[i][j] = gdm;

		mutex_unlock(&gdm_table_lock);

		tty_dev->minor[i] = j;

		tty_dev->gdm[i] = gdm;
		tty_port_init(&gdm->port);

		gdm->port.ops = &gdm_port_ops;
		gdm->index = i;
		gdm->minor = j;
		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++)
@@ -261,31 +261,24 @@ void unregister_lte_tty_device(struct tty_dev *tty_dev)
	struct gdm *gdm;
	struct tty_struct *tty;
	int i;
	int j;

	for (i = 0; i < TTY_MAX_COUNT; i++) {

		j = tty_dev->minor[i];

		if (j >= GDM_TTY_MINOR)
		gdm = tty_dev->gdm[i];
		if (!gdm)
			continue;

		mutex_lock(&gdm_table_lock);
		gdm = gdm_table[i][j];
		gdm_table[gdm->index][gdm->minor] = NULL;
		mutex_unlock(&gdm_table_lock);

		if (!gdm)
			continue;

		tty = tty_port_tty_get(&gdm->port);
		if (tty) {
			tty_vhangup(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);

	}
}

+22 −11
Original line number Diff line number Diff line
@@ -33,17 +33,6 @@ enum RECV_PACKET_PROCESS {
	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 tty_dev *tty_dev;
	struct tty_port port;
@@ -51,6 +40,28 @@ struct gdm {
	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);
void unregister_lte_tty_driver(void);
int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev);