aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Tervo <ville.tervo@nokia.com>2007-07-11 03:23:41 -0400
committerMarcel Holtmann <marcel@holtmann.org>2007-07-11 01:06:51 -0400
commit8de0a15483b357d0f0b821330ec84d1660cadc4e (patch)
treeb53fe490c95066dfc95f58d52b26e3f1f75ecdba
parent84950cf0ba02fd6a5defe2511bc41f9aa2237632 (diff)
[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: Ville Tervo <ville.tervo@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/rfcomm.h1
-rw-r--r--net/bluetooth/rfcomm/tty.c30
2 files changed, 23 insertions, 8 deletions
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 3c563f02907c..25aa575db807 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc
323#define RFCOMM_RELEASE_ONHUP 1 323#define RFCOMM_RELEASE_ONHUP 1
324#define RFCOMM_HANGUP_NOW 2 324#define RFCOMM_HANGUP_NOW 2
325#define RFCOMM_TTY_ATTACHED 3 325#define RFCOMM_TTY_ATTACHED 3
326#define RFCOMM_TTY_RELEASED 4
326 327
327struct rfcomm_dev_req { 328struct rfcomm_dev_req {
328 s16 dev_id; 329 s16 dev_id;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index ba469b038ea0..23ba61a13bdd 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
95 95
96 BT_DBG("dev %p dlc %p", dev, dlc); 96 BT_DBG("dev %p dlc %p", dev, dlc);
97 97
98 write_lock_bh(&rfcomm_dev_lock);
99 list_del_init(&dev->list);
100 write_unlock_bh(&rfcomm_dev_lock);
101
98 rfcomm_dlc_lock(dlc); 102 rfcomm_dlc_lock(dlc);
99 /* Detach DLC if it's owned by this dev */ 103 /* Detach DLC if it's owned by this dev */
100 if (dlc->owner == dev) 104 if (dlc->owner == dev)
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
156 read_lock(&rfcomm_dev_lock); 160 read_lock(&rfcomm_dev_lock);
157 161
158 dev = __rfcomm_dev_get(id); 162 dev = __rfcomm_dev_get(id);
159 if (dev) 163
160 rfcomm_dev_hold(dev); 164 if (dev) {
165 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
166 dev = NULL;
167 else
168 rfcomm_dev_hold(dev);
169 }
161 170
162 read_unlock(&rfcomm_dev_lock); 171 read_unlock(&rfcomm_dev_lock);
163 172
@@ -265,6 +274,12 @@ out:
265 274
266 dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); 275 dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
267 276
277 if (IS_ERR(dev->tty_dev)) {
278 list_del(&dev->list);
279 kfree(dev);
280 return PTR_ERR(dev->tty_dev);
281 }
282
268 return dev->id; 283 return dev->id;
269} 284}
270 285
@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
272{ 287{
273 BT_DBG("dev %p", dev); 288 BT_DBG("dev %p", dev);
274 289
275 write_lock_bh(&rfcomm_dev_lock); 290 set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
276 list_del_init(&dev->list);
277 write_unlock_bh(&rfcomm_dev_lock);
278
279 rfcomm_dev_put(dev); 291 rfcomm_dev_put(dev);
280} 292}
281 293
@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg)
329 if (copy_from_user(&req, arg, sizeof(req))) 341 if (copy_from_user(&req, arg, sizeof(req)))
330 return -EFAULT; 342 return -EFAULT;
331 343
332 BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags); 344 BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);
333 345
334 if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) 346 if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
335 return -EPERM; 347 return -EPERM;
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg)
370 if (copy_from_user(&req, arg, sizeof(req))) 382 if (copy_from_user(&req, arg, sizeof(req)))
371 return -EFAULT; 383 return -EFAULT;
372 384
373 BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags); 385 BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
374 386
375 if (!(dev = rfcomm_dev_get(req.dev_id))) 387 if (!(dev = rfcomm_dev_get(req.dev_id)))
376 return -ENODEV; 388 return -ENODEV;
@@ -419,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg)
419 431
420 list_for_each(p, &rfcomm_dev_list) { 432 list_for_each(p, &rfcomm_dev_list) {
421 struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); 433 struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
434 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
435 continue;
422 (di + n)->id = dev->id; 436 (di + n)->id = dev->id;
423 (di + n)->flags = dev->flags; 437 (di + n)->flags = dev->flags;
424 (di + n)->state = dev->dlc->state; 438 (di + n)->state = dev->dlc->state;