git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Bluetooth: Fix RFCOMM release oops when device is still in use
[pandora-kernel.git]
/
net
/
bluetooth
/
rfcomm
/
tty.c
diff --git
a/net/bluetooth/rfcomm/tty.c
b/net/bluetooth/rfcomm/tty.c
index
d3340dd
..
111c6c8
100644
(file)
--- a/
net/bluetooth/rfcomm/tty.c
+++ b/
net/bluetooth/rfcomm/tty.c
@@
-39,11
+39,6
@@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/rfcomm.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/rfcomm.h>
-#ifndef CONFIG_BT_RFCOMM_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define RFCOMM_TTY_MAGIC 0x6d02 /* magic number for rfcomm struct */
#define RFCOMM_TTY_PORTS RFCOMM_MAX_DEV /* whole lotta rfcomm devices */
#define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */
#define RFCOMM_TTY_MAGIC 0x6d02 /* magic number for rfcomm struct */
#define RFCOMM_TTY_PORTS RFCOMM_MAX_DEV /* whole lotta rfcomm devices */
#define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */
@@
-58,7
+53,7
@@
struct rfcomm_dev {
char name[12];
int id;
unsigned long flags;
char name[12];
int id;
unsigned long flags;
-
int
opened;
+
atomic_t
opened;
int err;
bdaddr_t src;
int err;
bdaddr_t src;
@@
-261,6
+256,8
@@
static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev->flags = req->flags &
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
dev->flags = req->flags &
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
+ atomic_set(&dev->opened, 0);
+
init_waitqueue_head(&dev->wait);
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
init_waitqueue_head(&dev->wait);
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
@@
-330,10
+327,10
@@
static void rfcomm_dev_del(struct rfcomm_dev *dev)
{
BT_DBG("dev %p", dev);
{
BT_DBG("dev %p", dev);
- if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
- BUG_ON(1);
- else
-
set_bit(RFCOMM_TTY_RELEASED, &dev->flags)
;
+ BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
+
+ if (atomic_read(&dev->opened) > 0)
+
return
;
write_lock_bh(&rfcomm_dev_lock);
list_del_init(&dev->list);
write_lock_bh(&rfcomm_dev_lock);
list_del_init(&dev->list);
@@
-689,9
+686,10
@@
static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
if (!dev)
return -ENODEV;
if (!dev)
return -ENODEV;
- BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), dev->channel, dev->opened);
+ BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
+ dev->channel, atomic_read(&dev->opened));
- if (
dev->opened++ != 0
)
+ if (
atomic_inc_return(&dev->opened) > 1
)
return 0;
dlc = dev->dlc;
return 0;
dlc = dev->dlc;
@@
-747,9
+745,10
@@
static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
if (!dev)
return;
if (!dev)
return;
- BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
+ BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
+ atomic_read(&dev->opened));
- if (
--dev->opened == 0
) {
+ if (
atomic_dec_and_test(&dev->opened)
) {
if (dev->tty_dev->parent)
device_move(dev->tty_dev, NULL);
if (dev->tty_dev->parent)
device_move(dev->tty_dev, NULL);
@@
-763,6
+762,14
@@
static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
tty->driver_data = NULL;
dev->tty = NULL;
rfcomm_dlc_unlock(dev->dlc);
tty->driver_data = NULL;
dev->tty = NULL;
rfcomm_dlc_unlock(dev->dlc);
+
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
+ write_lock_bh(&rfcomm_dev_lock);
+ list_del_init(&dev->list);
+ write_unlock_bh(&rfcomm_dev_lock);
+
+ rfcomm_dev_put(dev);
+ }
}
rfcomm_dev_put(dev);
}
rfcomm_dev_put(dev);