diff options
Diffstat (limited to 'net/bluetooth/rfcomm/tty.c')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 45 |
1 files changed, 22 insertions, 23 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index c258796313e0..fa8f4de53b99 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/capability.h> | 34 | #include <linux/capability.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
37 | #include <linux/workqueue.h> | ||
37 | 38 | ||
38 | #include <net/bluetooth/bluetooth.h> | 39 | #include <net/bluetooth/bluetooth.h> |
39 | #include <net/bluetooth/hci_core.h> | 40 | #include <net/bluetooth/hci_core.h> |
@@ -65,7 +66,7 @@ struct rfcomm_dev { | |||
65 | struct rfcomm_dlc *dlc; | 66 | struct rfcomm_dlc *dlc; |
66 | struct tty_struct *tty; | 67 | struct tty_struct *tty; |
67 | wait_queue_head_t wait; | 68 | wait_queue_head_t wait; |
68 | struct tasklet_struct wakeup_task; | 69 | struct work_struct wakeup_task; |
69 | 70 | ||
70 | struct device *tty_dev; | 71 | struct device *tty_dev; |
71 | 72 | ||
@@ -81,7 +82,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb); | |||
81 | static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); | 82 | static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); |
82 | static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig); | 83 | static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig); |
83 | 84 | ||
84 | static void rfcomm_tty_wakeup(unsigned long arg); | 85 | static void rfcomm_tty_wakeup(struct work_struct *work); |
85 | 86 | ||
86 | /* ---- Device functions ---- */ | 87 | /* ---- Device functions ---- */ |
87 | static void rfcomm_dev_destruct(struct rfcomm_dev *dev) | 88 | static void rfcomm_dev_destruct(struct rfcomm_dev *dev) |
@@ -133,13 +134,10 @@ static inline void rfcomm_dev_put(struct rfcomm_dev *dev) | |||
133 | static struct rfcomm_dev *__rfcomm_dev_get(int id) | 134 | static struct rfcomm_dev *__rfcomm_dev_get(int id) |
134 | { | 135 | { |
135 | struct rfcomm_dev *dev; | 136 | struct rfcomm_dev *dev; |
136 | struct list_head *p; | ||
137 | 137 | ||
138 | list_for_each(p, &rfcomm_dev_list) { | 138 | list_for_each_entry(dev, &rfcomm_dev_list, list) |
139 | dev = list_entry(p, struct rfcomm_dev, list); | ||
140 | if (dev->id == id) | 139 | if (dev->id == id) |
141 | return dev; | 140 | return dev; |
142 | } | ||
143 | 141 | ||
144 | return NULL; | 142 | return NULL; |
145 | } | 143 | } |
@@ -197,7 +195,7 @@ static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); | |||
197 | 195 | ||
198 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | 196 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) |
199 | { | 197 | { |
200 | struct rfcomm_dev *dev; | 198 | struct rfcomm_dev *dev, *entry; |
201 | struct list_head *head = &rfcomm_dev_list, *p; | 199 | struct list_head *head = &rfcomm_dev_list, *p; |
202 | int err = 0; | 200 | int err = 0; |
203 | 201 | ||
@@ -212,8 +210,8 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
212 | if (req->dev_id < 0) { | 210 | if (req->dev_id < 0) { |
213 | dev->id = 0; | 211 | dev->id = 0; |
214 | 212 | ||
215 | list_for_each(p, &rfcomm_dev_list) { | 213 | list_for_each_entry(entry, &rfcomm_dev_list, list) { |
216 | if (list_entry(p, struct rfcomm_dev, list)->id != dev->id) | 214 | if (entry->id != dev->id) |
217 | break; | 215 | break; |
218 | 216 | ||
219 | dev->id++; | 217 | dev->id++; |
@@ -222,9 +220,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
222 | } else { | 220 | } else { |
223 | dev->id = req->dev_id; | 221 | dev->id = req->dev_id; |
224 | 222 | ||
225 | list_for_each(p, &rfcomm_dev_list) { | 223 | list_for_each_entry(entry, &rfcomm_dev_list, list) { |
226 | struct rfcomm_dev *entry = list_entry(p, struct rfcomm_dev, list); | ||
227 | |||
228 | if (entry->id == dev->id) { | 224 | if (entry->id == dev->id) { |
229 | err = -EADDRINUSE; | 225 | err = -EADDRINUSE; |
230 | goto out; | 226 | goto out; |
@@ -257,7 +253,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
257 | atomic_set(&dev->opened, 0); | 253 | atomic_set(&dev->opened, 0); |
258 | 254 | ||
259 | init_waitqueue_head(&dev->wait); | 255 | init_waitqueue_head(&dev->wait); |
260 | tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev); | 256 | INIT_WORK(&dev->wakeup_task, rfcomm_tty_wakeup); |
261 | 257 | ||
262 | skb_queue_head_init(&dev->pending); | 258 | skb_queue_head_init(&dev->pending); |
263 | 259 | ||
@@ -351,7 +347,7 @@ static void rfcomm_wfree(struct sk_buff *skb) | |||
351 | struct rfcomm_dev *dev = (void *) skb->sk; | 347 | struct rfcomm_dev *dev = (void *) skb->sk; |
352 | atomic_sub(skb->truesize, &dev->wmem_alloc); | 348 | atomic_sub(skb->truesize, &dev->wmem_alloc); |
353 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) | 349 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) |
354 | tasklet_schedule(&dev->wakeup_task); | 350 | queue_work(system_nrt_wq, &dev->wakeup_task); |
355 | rfcomm_dev_put(dev); | 351 | rfcomm_dev_put(dev); |
356 | } | 352 | } |
357 | 353 | ||
@@ -455,9 +451,9 @@ static int rfcomm_release_dev(void __user *arg) | |||
455 | 451 | ||
456 | static int rfcomm_get_dev_list(void __user *arg) | 452 | static int rfcomm_get_dev_list(void __user *arg) |
457 | { | 453 | { |
454 | struct rfcomm_dev *dev; | ||
458 | struct rfcomm_dev_list_req *dl; | 455 | struct rfcomm_dev_list_req *dl; |
459 | struct rfcomm_dev_info *di; | 456 | struct rfcomm_dev_info *di; |
460 | struct list_head *p; | ||
461 | int n = 0, size, err; | 457 | int n = 0, size, err; |
462 | u16 dev_num; | 458 | u16 dev_num; |
463 | 459 | ||
@@ -479,8 +475,7 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
479 | 475 | ||
480 | read_lock_bh(&rfcomm_dev_lock); | 476 | read_lock_bh(&rfcomm_dev_lock); |
481 | 477 | ||
482 | list_for_each(p, &rfcomm_dev_list) { | 478 | list_for_each_entry(dev, &rfcomm_dev_list, list) { |
483 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); | ||
484 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | 479 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) |
485 | continue; | 480 | continue; |
486 | (di + n)->id = dev->id; | 481 | (di + n)->id = dev->id; |
@@ -635,9 +630,10 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig) | |||
635 | } | 630 | } |
636 | 631 | ||
637 | /* ---- TTY functions ---- */ | 632 | /* ---- TTY functions ---- */ |
638 | static void rfcomm_tty_wakeup(unsigned long arg) | 633 | static void rfcomm_tty_wakeup(struct work_struct *work) |
639 | { | 634 | { |
640 | struct rfcomm_dev *dev = (void *) arg; | 635 | struct rfcomm_dev *dev = container_of(work, struct rfcomm_dev, |
636 | wakeup_task); | ||
641 | struct tty_struct *tty = dev->tty; | 637 | struct tty_struct *tty = dev->tty; |
642 | if (!tty) | 638 | if (!tty) |
643 | return; | 639 | return; |
@@ -762,7 +758,7 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
762 | rfcomm_dlc_close(dev->dlc, 0); | 758 | rfcomm_dlc_close(dev->dlc, 0); |
763 | 759 | ||
764 | clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags); | 760 | clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags); |
765 | tasklet_kill(&dev->wakeup_task); | 761 | cancel_work_sync(&dev->wakeup_task); |
766 | 762 | ||
767 | rfcomm_dlc_lock(dev->dlc); | 763 | rfcomm_dlc_lock(dev->dlc); |
768 | tty->driver_data = NULL; | 764 | tty->driver_data = NULL; |
@@ -1155,9 +1151,11 @@ static const struct tty_operations rfcomm_ops = { | |||
1155 | 1151 | ||
1156 | int __init rfcomm_init_ttys(void) | 1152 | int __init rfcomm_init_ttys(void) |
1157 | { | 1153 | { |
1154 | int error; | ||
1155 | |||
1158 | rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS); | 1156 | rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS); |
1159 | if (!rfcomm_tty_driver) | 1157 | if (!rfcomm_tty_driver) |
1160 | return -1; | 1158 | return -ENOMEM; |
1161 | 1159 | ||
1162 | rfcomm_tty_driver->owner = THIS_MODULE; | 1160 | rfcomm_tty_driver->owner = THIS_MODULE; |
1163 | rfcomm_tty_driver->driver_name = "rfcomm"; | 1161 | rfcomm_tty_driver->driver_name = "rfcomm"; |
@@ -1172,10 +1170,11 @@ int __init rfcomm_init_ttys(void) | |||
1172 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; | 1170 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; |
1173 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); | 1171 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); |
1174 | 1172 | ||
1175 | if (tty_register_driver(rfcomm_tty_driver)) { | 1173 | error = tty_register_driver(rfcomm_tty_driver); |
1174 | if (error) { | ||
1176 | BT_ERR("Can't register RFCOMM TTY driver"); | 1175 | BT_ERR("Can't register RFCOMM TTY driver"); |
1177 | put_tty_driver(rfcomm_tty_driver); | 1176 | put_tty_driver(rfcomm_tty_driver); |
1178 | return -1; | 1177 | return error; |
1179 | } | 1178 | } |
1180 | 1179 | ||
1181 | BT_INFO("RFCOMM TTY layer initialized"); | 1180 | BT_INFO("RFCOMM TTY layer initialized"); |