Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8de0a154 authored by Ville Tervo's avatar Ville Tervo Committed by Marcel Holtmann
Browse files

[Bluetooth] Keep rfcomm_dev on the list until it is freed



This patch changes the RFCOMM TTY release process so that the TTY is kept
on the list until it is really freed. A new device flag is used to keep
track of released TTYs.

Signed-off-by: default avatarVille Tervo <ville.tervo@nokia.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 84950cf0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc
#define RFCOMM_RELEASE_ONHUP  1
#define RFCOMM_HANGUP_NOW     2
#define RFCOMM_TTY_ATTACHED   3
#define RFCOMM_TTY_RELEASED   4

struct rfcomm_dev_req {
	s16      dev_id;
+22 −8
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)

	BT_DBG("dev %p dlc %p", dev, dlc);

	write_lock_bh(&rfcomm_dev_lock);
	list_del_init(&dev->list);
	write_unlock_bh(&rfcomm_dev_lock);

	rfcomm_dlc_lock(dlc);
	/* Detach DLC if it's owned by this dev */
	if (dlc->owner == dev)
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
	read_lock(&rfcomm_dev_lock);

	dev = __rfcomm_dev_get(id);
	if (dev)

	if (dev) {
		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
			dev = NULL;
		else
			rfcomm_dev_hold(dev);
	}

	read_unlock(&rfcomm_dev_lock);

@@ -265,6 +274,12 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)

	dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);

	if (IS_ERR(dev->tty_dev)) {
		list_del(&dev->list);
		kfree(dev);
		return PTR_ERR(dev->tty_dev);
	}

	return dev->id;
}

@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
{
	BT_DBG("dev %p", dev);

	write_lock_bh(&rfcomm_dev_lock);
	list_del_init(&dev->list);
	write_unlock_bh(&rfcomm_dev_lock);

	set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
	rfcomm_dev_put(dev);
}

@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg)
	if (copy_from_user(&req, arg, sizeof(req)))
		return -EFAULT;

	BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags);
	BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);

	if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
		return -EPERM;
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg)
	if (copy_from_user(&req, arg, sizeof(req)))
		return -EFAULT;

	BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags);
	BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);

	if (!(dev = rfcomm_dev_get(req.dev_id)))
		return -ENODEV;
@@ -419,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg)

	list_for_each(p, &rfcomm_dev_list) {
		struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
			continue;
		(di + n)->id      = dev->id;
		(di + n)->flags   = dev->flags;
		(di + n)->state   = dev->dlc->state;