All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/7] rfcomm: Take proper tty_struct references
@ 2013-07-22 16:27 Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close Gianluca Anzolin
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

In net/bluetooth/rfcomm/tty.c the struct tty_struct is used without taking
references. This may lead to a use-after-free of the rfcomm tty.

Fix this by taking references properly, using the tty_port_* helpers when
possible.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index b6e44ad..6c3efb5 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -333,10 +333,11 @@ static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
 static void rfcomm_wfree(struct sk_buff *skb)
 {
 	struct rfcomm_dev *dev = (void *) skb->sk;
-	struct tty_struct *tty = dev->port.tty;
+
 	atomic_sub(skb->truesize, &dev->wmem_alloc);
-	if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags) && tty)
-		tty_wakeup(tty);
+	if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
+		tty_port_tty_wakeup(&dev->port);
+
 	tty_port_put(&dev->port);
 }
 
@@ -410,6 +411,7 @@ static int rfcomm_release_dev(void __user *arg)
 {
 	struct rfcomm_dev_req req;
 	struct rfcomm_dev *dev;
+	struct tty_struct *tty;
 
 	if (copy_from_user(&req, arg, sizeof(req)))
 		return -EFAULT;
@@ -429,8 +431,11 @@ static int rfcomm_release_dev(void __user *arg)
 		rfcomm_dlc_close(dev->dlc, 0);
 
 	/* Shut down TTY synchronously before freeing rfcomm_dev */
-	if (dev->port.tty)
-		tty_vhangup(dev->port.tty);
+	tty = tty_port_tty_get(&dev->port);
+	if (tty) {
+		tty_vhangup(tty);
+		tty_kref_put(tty);
+	}
 
 	if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
 		rfcomm_dev_del(dev);
@@ -563,6 +568,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
 static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 {
 	struct rfcomm_dev *dev = dlc->owner;
+	struct tty_struct *tty;
 	if (!dev)
 		return;
 
@@ -572,7 +578,8 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 	wake_up_interruptible(&dev->wait);
 
 	if (dlc->state == BT_CLOSED) {
-		if (!dev->port.tty) {
+		tty = tty_port_tty_get(&dev->port);
+		if (!tty) {
 			if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
 				/* Drop DLC lock here to avoid deadlock
 				 * 1. rfcomm_dev_get will take rfcomm_dev_lock
@@ -591,8 +598,10 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 				tty_port_put(&dev->port);
 				rfcomm_dlc_lock(dlc);
 			}
-		} else
-			tty_hangup(dev->port.tty);
+		} else {
+			tty_hangup(tty);
+			tty_kref_put(tty);
+		}
 	}
 }
 
@@ -604,10 +613,8 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
 
 	BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
 
-	if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) {
-		if (dev->port.tty && !C_CLOCAL(dev->port.tty))
-			tty_hangup(dev->port.tty);
-	}
+	if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV))
+		tty_port_tty_hangup(&dev->port, true);
 
 	dev->modem_status =
 		((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |
@@ -674,7 +681,7 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
 
 	rfcomm_dlc_lock(dlc);
 	tty->driver_data = dev;
-	dev->port.tty = tty;
+	tty_port_tty_set(&dev->port, tty);
 	rfcomm_dlc_unlock(dlc);
 	set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
 
@@ -742,7 +749,7 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 
 		rfcomm_dlc_lock(dev->dlc);
 		tty->driver_data = NULL;
-		dev->port.tty = NULL;
+		tty_port_tty_set(&dev->port, NULL);
 		rfcomm_dlc_unlock(dev->dlc);
 
 		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close
  2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
@ 2013-07-22 16:27 ` Gianluca Anzolin
  2013-07-24 22:28   ` Peter Hurley
  2013-07-22 16:27 ` [PATCH v2 3/7] rfcomm: Move rfcomm_get_device before rfcomm_dev_state_change Gianluca Anzolin
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

Move the tty_struct initialization from rfcomm_tty_open to rfcomm_tty_install
and do the same for the cleanup moving the code from rfcomm_tty_close to
rfcomm_tty_cleanup.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 100 +++++++++++++++++++++++++++------------------
 1 file changed, 61 insertions(+), 39 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 6c3efb5..c9913dd 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -645,49 +645,60 @@ static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
 		tty_flip_buffer_push(&dev->port);
 }
 
-static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
+/* do the reverse of install, clearing the tty fields and releasing the
+ * reference to tty_port */
+static void rfcomm_tty_cleanup(struct tty_struct *tty)
+{
+	struct rfcomm_dev *dev = tty->driver_data;
+
+	if (dev->tty_dev->parent)
+		device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
+
+	/* Close DLC and dettach TTY */
+	rfcomm_dlc_close(dev->dlc, 0);
+
+	clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
+
+	rfcomm_dlc_lock(dev->dlc);
+	tty->driver_data = NULL;
+	rfcomm_dlc_unlock(dev->dlc);
+
+	tty_port_put(&dev->port);
+}
+
+/* here we acquire the tty_port reference since it's here the tty is first used
+ * by setting the termios. We also populate the driver_data field and install
+ * the tty port */
+static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct rfcomm_dev *dev;
 	struct rfcomm_dlc *dlc;
-	unsigned long flags;
-	int err, id;
-
-	id = tty->index;
-
-	BT_DBG("tty %p id %d", tty, id);
+	int err;
 
-	/* We don't leak this refcount. For reasons which are not entirely
-	   clear, the TTY layer will call our ->close() method even if the
-	   open fails. We decrease the refcount there, and decreasing it
-	   here too would cause breakage. */
-	dev = rfcomm_dev_get(id);
+	dev = rfcomm_dev_get(tty->index);
 	if (!dev)
 		return -ENODEV;
 
 	BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst,
 	       dev->channel, dev->port.count);
 
-	spin_lock_irqsave(&dev->port.lock, flags);
-	if (++dev->port.count > 1) {
-		spin_unlock_irqrestore(&dev->port.lock, flags);
-		return 0;
-	}
-	spin_unlock_irqrestore(&dev->port.lock, flags);
-
 	dlc = dev->dlc;
 
 	/* Attach TTY and open DLC */
-
 	rfcomm_dlc_lock(dlc);
 	tty->driver_data = dev;
-	tty_port_tty_set(&dev->port, tty);
 	rfcomm_dlc_unlock(dlc);
 	set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
 
+	/* install the tty_port */
+	err = tty_port_install(&dev->port, driver, tty);
+	if (err < 0)
+		goto error_no_dlc;
+
 	err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
 	if (err < 0)
-		return err;
+		goto error_no_dlc;
 
 	/* Wait for DLC to connect */
 	add_wait_queue(&dev->wait, &wait);
@@ -714,17 +725,40 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&dev->wait, &wait);
 
-	if (err == 0)
-		device_move(dev->tty_dev, rfcomm_get_device(dev),
-			    DPM_ORDER_DEV_AFTER_PARENT);
+	if (err < 0)
+		goto error_no_connection;
+
+	device_move(dev->tty_dev, rfcomm_get_device(dev),
+		    DPM_ORDER_DEV_AFTER_PARENT);
 
 	rfcomm_tty_copy_pending(dev);
 
 	rfcomm_dlc_unthrottle(dev->dlc);
 
+	return 0;
+
+error_no_connection:
+	rfcomm_dlc_close(dlc, err);
+error_no_dlc:
+	clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
+	tty_port_put(&dev->port);
 	return err;
 }
 
+static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct rfcomm_dev *dev = tty->driver_data;
+	unsigned long flags;
+
+	BT_DBG("tty %p id %d", tty, tty->index);
+
+	spin_lock_irqsave(&dev->port.lock, flags);
+	dev->port.count++;
+	spin_unlock_irqrestore(&dev->port.lock, flags);
+
+	return 0;
+}
+
 static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
@@ -739,18 +773,6 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 	spin_lock_irqsave(&dev->port.lock, flags);
 	if (!--dev->port.count) {
 		spin_unlock_irqrestore(&dev->port.lock, flags);
-		if (dev->tty_dev->parent)
-			device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
-
-		/* Close DLC and dettach TTY */
-		rfcomm_dlc_close(dev->dlc, 0);
-
-		clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
-
-		rfcomm_dlc_lock(dev->dlc);
-		tty->driver_data = NULL;
-		tty_port_tty_set(&dev->port, NULL);
-		rfcomm_dlc_unlock(dev->dlc);
 
 		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
 			spin_lock(&rfcomm_dev_lock);
@@ -761,8 +783,6 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 		}
 	} else
 		spin_unlock_irqrestore(&dev->port.lock, flags);
-
-	tty_port_put(&dev->port);
 }
 
 static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1135,6 +1155,8 @@ static const struct tty_operations rfcomm_ops = {
 	.wait_until_sent	= rfcomm_tty_wait_until_sent,
 	.tiocmget		= rfcomm_tty_tiocmget,
 	.tiocmset		= rfcomm_tty_tiocmset,
+	.install                = rfcomm_tty_install,
+	.cleanup                = rfcomm_tty_cleanup,
 };
 
 int __init rfcomm_init_ttys(void)
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/7] rfcomm: Move rfcomm_get_device before rfcomm_dev_state_change
  2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close Gianluca Anzolin
@ 2013-07-22 16:27 ` Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 4/7] rfcomm: Implement activate/shutdown/carrier tty_port methods Gianluca Anzolin
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

Move rfcomm_get_device before rfcomm_dev_state_change. This function will be
called later to move the device under the remote host when the connection is
established.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index c9913dd..fb5dde1 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -147,22 +147,6 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
 	return dev;
 }
 
-static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
-{
-	struct hci_dev *hdev;
-	struct hci_conn *conn;
-
-	hdev = hci_get_route(&dev->dst, &dev->src);
-	if (!hdev)
-		return NULL;
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
-
-	hci_dev_put(hdev);
-
-	return conn ? &conn->dev : NULL;
-}
-
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
 {
 	struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
@@ -565,6 +549,22 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
 	kfree_skb(skb);
 }
 
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
+{
+	struct hci_dev *hdev;
+	struct hci_conn *conn;
+
+	hdev = hci_get_route(&dev->dst, &dev->src);
+	if (!hdev)
+		return NULL;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+
+	hci_dev_put(hdev);
+
+	return conn ? &conn->dev : NULL;
+}
+
 static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 {
 	struct rfcomm_dev *dev = dlc->owner;
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/7] rfcomm: Implement activate/shutdown/carrier tty_port methods
  2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 3/7] rfcomm: Move rfcomm_get_device before rfcomm_dev_state_change Gianluca Anzolin
@ 2013-07-22 16:27 ` Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 5/7] rfcomm: Remove the device from the dev_list in the destructor Gianluca Anzolin
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

Implement .activate .shutdown and .carrier_raised tty_port methods that manage
the dlc by moving the relevant code from the rfcomm_tty_install and
rfcomm_tty_cleanup functions.

The tty_open/close/hangup functions are changed to use the tty_port functions
that properly call the tty_port methods.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 138 ++++++++++++++++++---------------------------
 1 file changed, 56 insertions(+), 82 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index fb5dde1..1258678 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -58,7 +58,6 @@ struct rfcomm_dev {
 	uint			modem_status;
 
 	struct rfcomm_dlc	*dlc;
-	wait_queue_head_t       wait;
 
 	struct device		*tty_dev;
 
@@ -112,8 +111,39 @@ static void rfcomm_dev_destruct(struct tty_port *port)
 	module_put(THIS_MODULE);
 }
 
+/* device-specific initialization: open the dlc */
+static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+
+	return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+}
+
+/* we block the open until the dlc->state becomes BT_CONNECTED */
+static int rfcomm_dev_carrier_raised(struct tty_port *port)
+{
+	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+
+	return (dev->dlc->state == BT_CONNECTED);
+}
+
+/* device-specific cleanup: close the dlc */
+static void rfcomm_dev_shutdown(struct tty_port *port)
+{
+	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+
+	if (dev->tty_dev->parent)
+		device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
+
+	/* close the dlc */
+	rfcomm_dlc_close(dev->dlc, 0);
+}
+
 static const struct tty_port_operations rfcomm_port_ops = {
 	.destruct = rfcomm_dev_destruct,
+	.activate = rfcomm_dev_activate,
+	.shutdown = rfcomm_dev_shutdown,
+	.carrier_raised = rfcomm_dev_carrier_raised,
 };
 
 static struct rfcomm_dev *__rfcomm_dev_get(int id)
@@ -220,7 +250,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 
 	tty_port_init(&dev->port);
 	dev->port.ops = &rfcomm_port_ops;
-	init_waitqueue_head(&dev->wait);
 
 	skb_queue_head_init(&dev->pending);
 
@@ -575,9 +604,12 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 	BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
 
 	dev->err = err;
-	wake_up_interruptible(&dev->wait);
+	if (dlc->state == BT_CONNECTED) {
+		device_move(dev->tty_dev, rfcomm_get_device(dev),
+			    DPM_ORDER_DEV_AFTER_PARENT);
 
-	if (dlc->state == BT_CLOSED) {
+		wake_up_interruptible(&dev->port.open_wait);
+	} else if (dlc->state == BT_CLOSED) {
 		tty = tty_port_tty_get(&dev->port);
 		if (!tty) {
 			if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
@@ -651,12 +683,6 @@ static void rfcomm_tty_cleanup(struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = tty->driver_data;
 
-	if (dev->tty_dev->parent)
-		device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
-
-	/* Close DLC and dettach TTY */
-	rfcomm_dlc_close(dev->dlc, 0);
-
 	clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
 
 	rfcomm_dlc_lock(dev->dlc);
@@ -671,7 +697,6 @@ static void rfcomm_tty_cleanup(struct tty_struct *tty)
  * the tty port */
 static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	struct rfcomm_dev *dev;
 	struct rfcomm_dlc *dlc;
 	int err;
@@ -693,96 +718,48 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
 
 	/* install the tty_port */
 	err = tty_port_install(&dev->port, driver, tty);
-	if (err < 0)
-		goto error_no_dlc;
-
-	err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
-	if (err < 0)
-		goto error_no_dlc;
-
-	/* Wait for DLC to connect */
-	add_wait_queue(&dev->wait, &wait);
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (dlc->state == BT_CLOSED) {
-			err = -dev->err;
-			break;
-		}
-
-		if (dlc->state == BT_CONNECTED)
-			break;
-
-		if (signal_pending(current)) {
-			err = -EINTR;
-			break;
-		}
-
-		tty_unlock(tty);
-		schedule();
-		tty_lock(tty);
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&dev->wait, &wait);
-
-	if (err < 0)
-		goto error_no_connection;
-
-	device_move(dev->tty_dev, rfcomm_get_device(dev),
-		    DPM_ORDER_DEV_AFTER_PARENT);
-
-	rfcomm_tty_copy_pending(dev);
+	if (err)
+		rfcomm_tty_cleanup(tty);
 
-	rfcomm_dlc_unthrottle(dev->dlc);
-
-	return 0;
-
-error_no_connection:
-	rfcomm_dlc_close(dlc, err);
-error_no_dlc:
-	clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
-	tty_port_put(&dev->port);
 	return err;
 }
 
 static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
 {
 	struct rfcomm_dev *dev = tty->driver_data;
-	unsigned long flags;
+	int err;
 
 	BT_DBG("tty %p id %d", tty, tty->index);
 
-	spin_lock_irqsave(&dev->port.lock, flags);
-	dev->port.count++;
-	spin_unlock_irqrestore(&dev->port.lock, flags);
+	err = tty_port_open(&dev->port, tty, filp);
+	if (err)
+		return err;
 
+	/* FIXME: rfcomm should use proper flow control for
+	 * received data. This hack will be unnecessary and can
+	 * be removed when that's implemented
+	 */
+	rfcomm_tty_copy_pending(dev);
+	rfcomm_dlc_unthrottle(dev->dlc);
 	return 0;
 }
 
 static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
-	unsigned long flags;
-
-	if (!dev)
-		return;
 
 	BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
 						dev->port.count);
 
-	spin_lock_irqsave(&dev->port.lock, flags);
-	if (!--dev->port.count) {
-		spin_unlock_irqrestore(&dev->port.lock, flags);
+	tty_port_close(&dev->port, tty, filp);
 
-		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
-			spin_lock(&rfcomm_dev_lock);
-			list_del_init(&dev->list);
-			spin_unlock(&rfcomm_dev_lock);
+	if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
+		spin_lock(&rfcomm_dev_lock);
+		list_del_init(&dev->list);
+		spin_unlock(&rfcomm_dev_lock);
 
-			tty_port_put(&dev->port);
-		}
-	} else
-		spin_unlock_irqrestore(&dev->port.lock, flags);
+		tty_port_put(&dev->port);
+	}
 }
 
 static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1082,10 +1059,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
 
 	BT_DBG("tty %p dev %p", tty, dev);
 
-	if (!dev)
-		return;
-
-	rfcomm_tty_flush_buffer(tty);
+	tty_port_hangup(&dev->port);
 
 	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
 		if (rfcomm_dev_get(dev->id) == NULL)
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 5/7] rfcomm: Remove the device from the dev_list in the destructor
  2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
                   ` (2 preceding siblings ...)
  2013-07-22 16:27 ` [PATCH v2 4/7] rfcomm: Implement activate/shutdown/carrier tty_port methods Gianluca Anzolin
@ 2013-07-22 16:27 ` Gianluca Anzolin
  2013-07-24 22:04   ` Peter Hurley
  2013-07-22 16:27 ` [PATCH v2 6/7] rfcomm: Fix the reference counting of tty_port Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 7/7] rfcomm: Purge the dlc->tx_queue to avoid circular dependency Gianluca Anzolin
  5 siblings, 1 reply; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

Remove the device from rfcomm_dev_list in the tty_port destructor.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 27 ++++++---------------------
 1 file changed, 6 insertions(+), 21 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 1258678..17e5faa 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -75,13 +75,6 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
 
 /* ---- Device functions ---- */
 
-/*
- * The reason this isn't actually a race, as you no doubt have a little voice
- * screaming at you in your head, is that the refcount should never actually
- * reach zero unless the device has already been taken off the list, in
- * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in
- * rfcomm_dev_destruct() anyway.
- */
 static void rfcomm_dev_destruct(struct tty_port *port)
 {
 	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
@@ -89,10 +82,9 @@ static void rfcomm_dev_destruct(struct tty_port *port)
 
 	BT_DBG("dev %p dlc %p", dev, dlc);
 
-	/* Refcount should only hit zero when called from rfcomm_dev_del()
-	   which will have taken us off the list. Everything else are
-	   refcounting bugs. */
-	BUG_ON(!list_empty(&dev->list));
+	spin_lock(&rfcomm_dev_lock);
+	list_del(&dev->list);
+	spin_unlock(&rfcomm_dev_lock);
 
 	rfcomm_dlc_lock(dlc);
 	/* Detach DLC if it's owned by this dev */
@@ -295,7 +287,9 @@ out:
 			dev->id, NULL);
 	if (IS_ERR(dev->tty_dev)) {
 		err = PTR_ERR(dev->tty_dev);
+		spin_lock(&rfcomm_dev_lock);
 		list_del(&dev->list);
+		spin_unlock(&rfcomm_dev_lock);
 		goto free;
 	}
 
@@ -328,10 +322,6 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
 	}
 	spin_unlock_irqrestore(&dev->port.lock, flags);
 
-	spin_lock(&rfcomm_dev_lock);
-	list_del_init(&dev->list);
-	spin_unlock(&rfcomm_dev_lock);
-
 	tty_port_put(&dev->port);
 }
 
@@ -753,13 +743,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 
 	tty_port_close(&dev->port, tty, filp);
 
-	if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
-		spin_lock(&rfcomm_dev_lock);
-		list_del_init(&dev->list);
-		spin_unlock(&rfcomm_dev_lock);
-
+	if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
 		tty_port_put(&dev->port);
-	}
 }
 
 static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 6/7] rfcomm: Fix the reference counting of tty_port
  2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
                   ` (3 preceding siblings ...)
  2013-07-22 16:27 ` [PATCH v2 5/7] rfcomm: Remove the device from the dev_list in the destructor Gianluca Anzolin
@ 2013-07-22 16:27 ` Gianluca Anzolin
  2013-07-22 16:27 ` [PATCH v2 7/7] rfcomm: Purge the dlc->tx_queue to avoid circular dependency Gianluca Anzolin
  5 siblings, 0 replies; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

The tty_port can be released in two cases: when we get a HUP in the fuctions
rfcomm_tty_hangup or rfcomm_dev_state_change. Or when the user releases the
device in rfcomm_release_dev.

In these cases we set the flag RFCOMM_TTY_RELEASED so that no other function can
get a reference to the tty_port.

The rfcomm_dev_del function is removed because it isn't used anymore.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 36 ++++++++++--------------------------
 1 file changed, 10 insertions(+), 26 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 17e5faa..428543e 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -308,23 +308,6 @@ free:
 	return err;
 }
 
-static void rfcomm_dev_del(struct rfcomm_dev *dev)
-{
-	unsigned long flags;
-	BT_DBG("dev %p", dev);
-
-	BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
-
-	spin_lock_irqsave(&dev->port.lock, flags);
-	if (dev->port.count > 0) {
-		spin_unlock_irqrestore(&dev->port.lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&dev->port.lock, flags);
-
-	tty_port_put(&dev->port);
-}
-
 /* ---- Send buffer ---- */
 static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
 {
@@ -440,8 +423,9 @@ static int rfcomm_release_dev(void __user *arg)
 		tty_kref_put(tty);
 	}
 
-	if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
-		rfcomm_dev_del(dev);
+	if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+		tty_port_put(&dev->port);
+
 	tty_port_put(&dev->port);
 	return 0;
 }
@@ -609,6 +593,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 				 *    rfcomm_dev_lock -> dlc lock
 				 * 2. tty_port_put will deadlock if it's
 				 *    the last reference
+				 *
+				 * FIXME: when we release the lock anything
+				 * could happen to dev, even its destruction
 				 */
 				rfcomm_dlc_unlock(dlc);
 				if (rfcomm_dev_get(dev->id) == NULL) {
@@ -616,7 +603,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 					return;
 				}
 
-				rfcomm_dev_del(dev);
+				set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
+				tty_port_put(&dev->port);
+
 				tty_port_put(&dev->port);
 				rfcomm_dlc_lock(dlc);
 			}
@@ -742,9 +731,6 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
 						dev->port.count);
 
 	tty_port_close(&dev->port, tty, filp);
-
-	if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
-		tty_port_put(&dev->port);
 }
 
 static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1047,9 +1033,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
 	tty_port_hangup(&dev->port);
 
 	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
-		if (rfcomm_dev_get(dev->id) == NULL)
-			return;
-		rfcomm_dev_del(dev);
+		set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
 		tty_port_put(&dev->port);
 	}
 }
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 7/7] rfcomm: Purge the dlc->tx_queue to avoid circular dependency
  2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
                   ` (4 preceding siblings ...)
  2013-07-22 16:27 ` [PATCH v2 6/7] rfcomm: Fix the reference counting of tty_port Gianluca Anzolin
@ 2013-07-22 16:27 ` Gianluca Anzolin
  5 siblings, 0 replies; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-22 16:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: peter, gustavo, marcel, Gianluca Anzolin

In rfcomm_tty_cleanup we purge the dlc->tx_queue which may contain socket
buffers that could prevent the tty_port destruction.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 428543e..50b38d7 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -668,6 +668,10 @@ static void rfcomm_tty_cleanup(struct tty_struct *tty)
 	tty->driver_data = NULL;
 	rfcomm_dlc_unlock(dev->dlc);
 
+	/* purge the dlc->tx_queue to avoid circular dependencies
+	 * between dev and dlc */
+	skb_queue_purge(&dev->dlc->tx_queue);
+
 	tty_port_put(&dev->port);
 }
 
-- 
1.8.3.3

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 5/7] rfcomm: Remove the device from the dev_list in the destructor
  2013-07-22 16:27 ` [PATCH v2 5/7] rfcomm: Remove the device from the dev_list in the destructor Gianluca Anzolin
@ 2013-07-24 22:04   ` Peter Hurley
  0 siblings, 0 replies; 13+ messages in thread
From: Peter Hurley @ 2013-07-24 22:04 UTC (permalink / raw)
  To: Gianluca Anzolin; +Cc: linux-bluetooth, gustavo, marcel

On 07/22/2013 12:27 PM, Gianluca Anzolin wrote:
> Remove the device from rfcomm_dev_list in the tty_port destructor.
>
> Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
> ---
>   net/bluetooth/rfcomm/tty.c | 27 ++++++---------------------
>   1 file changed, 6 insertions(+), 21 deletions(-)
>
> diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
> index 1258678..17e5faa 100644
> --- a/net/bluetooth/rfcomm/tty.c
> +++ b/net/bluetooth/rfcomm/tty.c
> @@ -75,13 +75,6 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
>
>   /* ---- Device functions ---- */
>
> -/*
> - * The reason this isn't actually a race, as you no doubt have a little voice
> - * screaming at you in your head, is that the refcount should never actually
> - * reach zero unless the device has already been taken off the list, in
> - * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in
> - * rfcomm_dev_destruct() anyway.
> - */
>   static void rfcomm_dev_destruct(struct tty_port *port)
>   {
>   	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
> @@ -89,10 +82,9 @@ static void rfcomm_dev_destruct(struct tty_port *port)
>
>   	BT_DBG("dev %p dlc %p", dev, dlc);
>
> -	/* Refcount should only hit zero when called from rfcomm_dev_del()
> -	   which will have taken us off the list. Everything else are
> -	   refcounting bugs. */
> -	BUG_ON(!list_empty(&dev->list));
> +	spin_lock(&rfcomm_dev_lock);
> +	list_del(&dev->list);
> +	spin_unlock(&rfcomm_dev_lock);
>
>   	rfcomm_dlc_lock(dlc);
>   	/* Detach DLC if it's owned by this dev */
> @@ -295,7 +287,9 @@ out:
>   			dev->id, NULL);
>   	if (IS_ERR(dev->tty_dev)) {
>   		err = PTR_ERR(dev->tty_dev);
> +		spin_lock(&rfcomm_dev_lock);
>   		list_del(&dev->list);
> +		spin_unlock(&rfcomm_dev_lock);
>   		goto free;
>   	}
>
> @@ -328,10 +322,6 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
>   	}
>   	spin_unlock_irqrestore(&dev->port.lock, flags);
>
> -	spin_lock(&rfcomm_dev_lock);
> -	list_del_init(&dev->list);
> -	spin_unlock(&rfcomm_dev_lock);
> -
>   	tty_port_put(&dev->port);
>   }
>
> @@ -753,13 +743,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
>
>   	tty_port_close(&dev->port, tty, filp);
>
> -	if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
> -		spin_lock(&rfcomm_dev_lock);
> -		list_del_init(&dev->list);
> -		spin_unlock(&rfcomm_dev_lock);
> -

Gianluca,

I think you may have missed my comment that this patch should
be earlier in the series. That way you wouldn't be adding code
in 4/7 that you're removing here.

Regards,
Peter Hurley


> +	if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
>   		tty_port_put(&dev->port);
> -	}
>   }
>
>   static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close
  2013-07-22 16:27 ` [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close Gianluca Anzolin
@ 2013-07-24 22:28   ` Peter Hurley
  2013-07-25  5:37     ` Gianluca Anzolin
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Hurley @ 2013-07-24 22:28 UTC (permalink / raw)
  To: Gianluca Anzolin; +Cc: linux-bluetooth, gustavo, marcel

On 07/22/2013 12:27 PM, Gianluca Anzolin wrote:
> Move the tty_struct initialization from rfcomm_tty_open to rfcomm_tty_install
> and do the same for the cleanup moving the code from rfcomm_tty_close to
> rfcomm_tty_cleanup.
>
> Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
> ---
>   net/bluetooth/rfcomm/tty.c | 100 +++++++++++++++++++++++++++------------------
>   1 file changed, 61 insertions(+), 39 deletions(-)
>
> diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
> index 6c3efb5..c9913dd 100644
> --- a/net/bluetooth/rfcomm/tty.c
> +++ b/net/bluetooth/rfcomm/tty.c
> @@ -645,49 +645,60 @@ static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
>   		tty_flip_buffer_push(&dev->port);
>   }
>
> -static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)

Gianluca,

The code you intend to keep in rfcomm_tty_open() should not be moved to
rfcomm_tty_install() in this patch and then moved back to rfcomm_tty_open()
in 4/7. It should stay in rfcomm_tty_open().

Likewise, the code being deleted in rfcomm_tty_install() in 4/7 should
remain in rfcomm_tty_open() here, and be deleted from rfcomm_tty_open() in
4/7 instead.

IOW, there's a much smaller changeset that will achieve the same end
product.


> +/* do the reverse of install, clearing the tty fields and releasing the
> + * reference to tty_port */
> +static void rfcomm_tty_cleanup(struct tty_struct *tty)
> +{
> +	struct rfcomm_dev *dev = tty->driver_data;
> +
> +	if (dev->tty_dev->parent)
> +		device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
> +
> +	/* Close DLC and dettach TTY */
> +	rfcomm_dlc_close(dev->dlc, 0);
> +
> +	clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
> +
> +	rfcomm_dlc_lock(dev->dlc);
> +	tty->driver_data = NULL;
> +	rfcomm_dlc_unlock(dev->dlc);
> +
> +	tty_port_put(&dev->port);
> +}
> +
> +/* here we acquire the tty_port reference since it's here the tty is first used
> + * by setting the termios. We also populate the driver_data field and install
> + * the tty port */
> +static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
>   {
>   	DECLARE_WAITQUEUE(wait, current);
>   	struct rfcomm_dev *dev;
>   	struct rfcomm_dlc *dlc;
> -	unsigned long flags;
> -	int err, id;
> -
> -	id = tty->index;
> -
> -	BT_DBG("tty %p id %d", tty, id);
> +	int err;
>
> -	/* We don't leak this refcount. For reasons which are not entirely
> -	   clear, the TTY layer will call our ->close() method even if the
> -	   open fails. We decrease the refcount there, and decreasing it
> -	   here too would cause breakage. */
> -	dev = rfcomm_dev_get(id);
> +	dev = rfcomm_dev_get(tty->index);
>   	if (!dev)
>   		return -ENODEV;
>
>   	BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst,
>   	       dev->channel, dev->port.count);
>
> -	spin_lock_irqsave(&dev->port.lock, flags);
> -	if (++dev->port.count > 1) {
> -		spin_unlock_irqrestore(&dev->port.lock, flags);
> -		return 0;
> -	}
> -	spin_unlock_irqrestore(&dev->port.lock, flags);
> -
>   	dlc = dev->dlc;
>
>   	/* Attach TTY and open DLC */
> -
>   	rfcomm_dlc_lock(dlc);
>   	tty->driver_data = dev;
> -	tty_port_tty_set(&dev->port, tty);
>   	rfcomm_dlc_unlock(dlc);
>   	set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
>
> +	/* install the tty_port */
> +	err = tty_port_install(&dev->port, driver, tty);
> +	if (err < 0)
> +		goto error_no_dlc;
> +
>   	err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
>   	if (err < 0)
> -		return err;
> +		goto error_no_dlc;
>
>   	/* Wait for DLC to connect */
>   	add_wait_queue(&dev->wait, &wait);
> @@ -714,17 +725,40 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
>   	set_current_state(TASK_RUNNING);
>   	remove_wait_queue(&dev->wait, &wait);
>
> -	if (err == 0)
> -		device_move(dev->tty_dev, rfcomm_get_device(dev),
> -			    DPM_ORDER_DEV_AFTER_PARENT);
> +	if (err < 0)
> +		goto error_no_connection;
> +
> +	device_move(dev->tty_dev, rfcomm_get_device(dev),
> +		    DPM_ORDER_DEV_AFTER_PARENT);
>
>   	rfcomm_tty_copy_pending(dev);
>
>   	rfcomm_dlc_unthrottle(dev->dlc);
>
> +	return 0;
> +
> +error_no_connection:
> +	rfcomm_dlc_close(dlc, err);
> +error_no_dlc:
> +	clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
> +	tty_port_put(&dev->port);
>   	return err;
>   }
>
> +static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
> +{
> +	struct rfcomm_dev *dev = tty->driver_data;
> +	unsigned long flags;
> +
> +	BT_DBG("tty %p id %d", tty, tty->index);
> +
> +	spin_lock_irqsave(&dev->port.lock, flags);
> +	dev->port.count++;
> +	spin_unlock_irqrestore(&dev->port.lock, flags);
> +
> +	return 0;
> +}
> +
>   static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
>   {
>   	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
> @@ -739,18 +773,6 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
>   	spin_lock_irqsave(&dev->port.lock, flags);
>   	if (!--dev->port.count) {
>   		spin_unlock_irqrestore(&dev->port.lock, flags);
> -		if (dev->tty_dev->parent)
> -			device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
> -
> -		/* Close DLC and dettach TTY */
> -		rfcomm_dlc_close(dev->dlc, 0);
> -
> -		clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
> -
> -		rfcomm_dlc_lock(dev->dlc);
> -		tty->driver_data = NULL;
> -		tty_port_tty_set(&dev->port, NULL);
> -		rfcomm_dlc_unlock(dev->dlc);
>
>   		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
>   			spin_lock(&rfcomm_dev_lock);
> @@ -761,8 +783,6 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
>   		}
>   	} else
>   		spin_unlock_irqrestore(&dev->port.lock, flags);
> -
> -	tty_port_put(&dev->port);
>   }
>
>   static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
> @@ -1135,6 +1155,8 @@ static const struct tty_operations rfcomm_ops = {
>   	.wait_until_sent	= rfcomm_tty_wait_until_sent,
>   	.tiocmget		= rfcomm_tty_tiocmget,
>   	.tiocmset		= rfcomm_tty_tiocmset,
> +	.install                = rfcomm_tty_install,
> +	.cleanup                = rfcomm_tty_cleanup,
>   };
>
>   int __init rfcomm_init_ttys(void)
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close
  2013-07-24 22:28   ` Peter Hurley
@ 2013-07-25  5:37     ` Gianluca Anzolin
  2013-07-25 12:59       ` Peter Hurley
  0 siblings, 1 reply; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-25  5:37 UTC (permalink / raw)
  To: Peter Hurley; +Cc: linux-bluetooth, gustavo, marcel

On Wed, Jul 24, 2013 at 06:28:26PM -0400, Peter Hurley wrote:
> Gianluca,
> 
> The code you intend to keep in rfcomm_tty_open() should not be moved to
> rfcomm_tty_install() in this patch and then moved back to rfcomm_tty_open()
> in 4/7. It should stay in rfcomm_tty_open().
> 
> Likewise, the code being deleted in rfcomm_tty_install() in 4/7 should
> remain in rfcomm_tty_open() here, and be deleted from rfcomm_tty_open() in
> 4/7 instead.
> 
> IOW, there's a much smaller changeset that will achieve the same end
> product.

Hello,

sorry I'm not very used to submit patches "the right way" and I missed the
point that I have to keep the changes to the minimum.

I also resent the tty_port patch, I hope it's fine now, I assumed it
was accepted but it wasn't and I also missed your last comment... I should lose
this bad habit to read only the the visible part of the mail body. :D

Ok, I'll rearrange the code and resend the rfcomm patches.

Thank you,
Gianluca

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close
  2013-07-25  5:37     ` Gianluca Anzolin
@ 2013-07-25 12:59       ` Peter Hurley
  2013-07-25 18:07         ` Gianluca Anzolin
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Hurley @ 2013-07-25 12:59 UTC (permalink / raw)
  To: Gianluca Anzolin; +Cc: linux-bluetooth, gustavo, marcel

On 07/25/2013 01:37 AM, Gianluca Anzolin wrote:
> On Wed, Jul 24, 2013 at 06:28:26PM -0400, Peter Hurley wrote:
>> Gianluca,
>>
>> The code you intend to keep in rfcomm_tty_open() should not be moved to
>> rfcomm_tty_install() in this patch and then moved back to rfcomm_tty_open()
>> in 4/7. It should stay in rfcomm_tty_open().
>>
>> Likewise, the code being deleted in rfcomm_tty_install() in 4/7 should
>> remain in rfcomm_tty_open() here, and be deleted from rfcomm_tty_open() in
>> 4/7 instead.
>>
>> IOW, there's a much smaller changeset that will achieve the same end
>> product.
>
> Hello,
>
> sorry I'm not very used to submit patches "the right way" and I missed the
> point that I have to keep the changes to the minimum.

No need to apologize.
Every kernel contributor goes through this learning curve.

> I also resent the tty_port patch, I hope it's fine now,

Looks good. With Jiri's ack, that'll go into Greg's tree in the next day or
two.

> I assumed it
> was accepted but it wasn't and I also missed your last comment... I should lose
> this bad habit to read only the the visible part of the mail body. :D
>
> Ok, I'll rearrange the code and resend the rfcomm patches.

Ok.

A subtlety I overlooked regarding the .carrier_raised() method is
CLOCAL must _not_ be set in the driver's init_termios. This initialization is
done in rfcomm_init_ttys().

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close
  2013-07-25 12:59       ` Peter Hurley
@ 2013-07-25 18:07         ` Gianluca Anzolin
  2013-07-25 18:20           ` Peter Hurley
  0 siblings, 1 reply; 13+ messages in thread
From: Gianluca Anzolin @ 2013-07-25 18:07 UTC (permalink / raw)
  To: Peter Hurley; +Cc: linux-bluetooth, gustavo, marcel

On Thu, Jul 25, 2013 at 08:59:40AM -0400, Peter Hurley wrote:
> On 07/25/2013 01:37 AM, Gianluca Anzolin wrote:
> >Hello,
> >
> >sorry I'm not very used to submit patches "the right way" and I missed the
> >point that I have to keep the changes to the minimum.
> 
> No need to apologize.
> Every kernel contributor goes through this learning curve.
> 

Hello,

I'm trying to reach the minimal changeset to reach my target, and in the
process I figured out that if I implement the .activate and .shutdown port
methods before the .install and .cleanup methods I could produce less changes.

However I'm stuck now because I cannot guarantee that the intermediate code
between the patches works at all (however it compiles). What should I do?

Thanks,
Gianluca

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close
  2013-07-25 18:07         ` Gianluca Anzolin
@ 2013-07-25 18:20           ` Peter Hurley
  0 siblings, 0 replies; 13+ messages in thread
From: Peter Hurley @ 2013-07-25 18:20 UTC (permalink / raw)
  To: Gianluca Anzolin; +Cc: linux-bluetooth, gustavo, marcel

On 07/25/2013 02:07 PM, Gianluca Anzolin wrote:
> On Thu, Jul 25, 2013 at 08:59:40AM -0400, Peter Hurley wrote:
>> On 07/25/2013 01:37 AM, Gianluca Anzolin wrote:
>>> Hello,
>>>
>>> sorry I'm not very used to submit patches "the right way" and I missed the
>>> point that I have to keep the changes to the minimum.
>>
>> No need to apologize.
>> Every kernel contributor goes through this learning curve.
>>
>
> Hello,
>
> I'm trying to reach the minimal changeset to reach my target, and in the
> process I figured out that if I implement the .activate and .shutdown port
> methods before the .install and .cleanup methods I could produce less changes.
>
> However I'm stuck now because I cannot guarantee that the intermediate code
> between the patches works at all (however it compiles). What should I do?

The tty .install and .cleanup methods should be introduced first.
Then the tty_port methods.

The dev_list patch should be before both.

If you want, feel free to send me private email with questions and/or
code snippets, and I'll do my best to respond quickly.

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-07-25 18:20 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-22 16:27 [PATCH v2 1/7] rfcomm: Take proper tty_struct references Gianluca Anzolin
2013-07-22 16:27 ` [PATCH v2 2/7] rfcomm: Move the tty initialization and cleanup out of open/close Gianluca Anzolin
2013-07-24 22:28   ` Peter Hurley
2013-07-25  5:37     ` Gianluca Anzolin
2013-07-25 12:59       ` Peter Hurley
2013-07-25 18:07         ` Gianluca Anzolin
2013-07-25 18:20           ` Peter Hurley
2013-07-22 16:27 ` [PATCH v2 3/7] rfcomm: Move rfcomm_get_device before rfcomm_dev_state_change Gianluca Anzolin
2013-07-22 16:27 ` [PATCH v2 4/7] rfcomm: Implement activate/shutdown/carrier tty_port methods Gianluca Anzolin
2013-07-22 16:27 ` [PATCH v2 5/7] rfcomm: Remove the device from the dev_list in the destructor Gianluca Anzolin
2013-07-24 22:04   ` Peter Hurley
2013-07-22 16:27 ` [PATCH v2 6/7] rfcomm: Fix the reference counting of tty_port Gianluca Anzolin
2013-07-22 16:27 ` [PATCH v2 7/7] rfcomm: Purge the dlc->tx_queue to avoid circular dependency Gianluca Anzolin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.