Commit cfc8d68f authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy

Convert Bluetooth HCI devices to new module refcounting.

parent d7105887
...@@ -789,6 +789,8 @@ int bluecard_open(bluecard_info_t *info) ...@@ -789,6 +789,8 @@ int bluecard_open(bluecard_info_t *info)
hdev->destruct = bluecard_hci_destruct; hdev->destruct = bluecard_hci_destruct;
hdev->ioctl = bluecard_hci_ioctl; hdev->ioctl = bluecard_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "bluecard_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "bluecard_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -1002,8 +1004,6 @@ void bluecard_config(dev_link_t *link) ...@@ -1002,8 +1004,6 @@ void bluecard_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (bluecard_open(info) != 0) if (bluecard_open(info) != 0)
goto failed; goto failed;
...@@ -1029,8 +1029,6 @@ void bluecard_release(u_long arg) ...@@ -1029,8 +1029,6 @@ void bluecard_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
bluecard_close(info); bluecard_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
...@@ -593,6 +593,8 @@ int bt3c_open(bt3c_info_t *info) ...@@ -593,6 +593,8 @@ int bt3c_open(bt3c_info_t *info)
hdev->destruct = bt3c_hci_destruct; hdev->destruct = bt3c_hci_destruct;
hdev->ioctl = bt3c_hci_ioctl; hdev->ioctl = bt3c_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -835,8 +837,6 @@ void bt3c_config(dev_link_t *link) ...@@ -835,8 +837,6 @@ void bt3c_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (bt3c_open(info) != 0) if (bt3c_open(info) != 0)
goto failed; goto failed;
...@@ -862,8 +862,6 @@ void bt3c_release(u_long arg) ...@@ -862,8 +862,6 @@ void bt3c_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
bt3c_close(info); bt3c_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
...@@ -541,6 +541,8 @@ int btuart_open(btuart_info_t *info) ...@@ -541,6 +541,8 @@ int btuart_open(btuart_info_t *info)
hdev->destruct = btuart_hci_destruct; hdev->destruct = btuart_hci_destruct;
hdev->ioctl = btuart_hci_ioctl; hdev->ioctl = btuart_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "btuart_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "btuart_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -795,8 +797,6 @@ void btuart_config(dev_link_t *link) ...@@ -795,8 +797,6 @@ void btuart_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (btuart_open(info) != 0) if (btuart_open(info) != 0)
goto failed; goto failed;
...@@ -822,8 +822,6 @@ void btuart_release(u_long arg) ...@@ -822,8 +822,6 @@ void btuart_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
btuart_close(info); btuart_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
...@@ -520,6 +520,8 @@ int dtl1_open(dtl1_info_t *info) ...@@ -520,6 +520,8 @@ int dtl1_open(dtl1_info_t *info)
hdev->destruct = dtl1_hci_destruct; hdev->destruct = dtl1_hci_destruct;
hdev->ioctl = dtl1_hci_ioctl; hdev->ioctl = dtl1_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -747,8 +749,6 @@ void dtl1_config(dev_link_t *link) ...@@ -747,8 +749,6 @@ void dtl1_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (dtl1_open(info) != 0) if (dtl1_open(info) != 0)
goto failed; goto failed;
...@@ -774,8 +774,6 @@ void dtl1_release(u_long arg) ...@@ -774,8 +774,6 @@ void dtl1_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
dtl1_close(info); dtl1_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
...@@ -250,8 +250,6 @@ static void hci_uart_destruct(struct hci_dev *hdev) ...@@ -250,8 +250,6 @@ static void hci_uart_destruct(struct hci_dev *hdev)
hu = (struct hci_uart *) hdev->driver_data; hu = (struct hci_uart *) hdev->driver_data;
kfree(hu); kfree(hu);
MOD_DEC_USE_COUNT;
} }
/* ------ LDISC part ------ */ /* ------ LDISC part ------ */
...@@ -291,7 +289,6 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -291,7 +289,6 @@ static int hci_uart_tty_open(struct tty_struct *tty)
if (tty->driver.flush_buffer) if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty); tty->driver.flush_buffer(tty);
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -317,8 +314,6 @@ static void hci_uart_tty_close(struct tty_struct *tty) ...@@ -317,8 +314,6 @@ static void hci_uart_tty_close(struct tty_struct *tty)
hu->proto->close(hu); hu->proto->close(hu);
hci_unregister_dev(hdev); hci_unregister_dev(hdev);
} }
MOD_DEC_USE_COUNT;
} }
} }
...@@ -411,11 +406,13 @@ static int hci_uart_register_dev(struct hci_uart *hu) ...@@ -411,11 +406,13 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev->send = hci_uart_send_frame; hdev->send = hci_uart_send_frame;
hdev->destruct = hci_uart_destruct; hdev->destruct = hci_uart_destruct;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device %s", hdev->name); BT_ERR("Can't register HCI device %s", hdev->name);
return -ENODEV; return -ENODEV;
} }
MOD_INC_USE_COUNT;
return 0; return 0;
} }
......
...@@ -207,18 +207,15 @@ static int hci_usb_open(struct hci_dev *hdev) ...@@ -207,18 +207,15 @@ static int hci_usb_open(struct hci_dev *hdev)
if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0; return 0;
MOD_INC_USE_COUNT;
write_lock_irqsave(&husb->completion_lock, flags); write_lock_irqsave(&husb->completion_lock, flags);
err = hci_usb_enable_intr(husb); err = hci_usb_enable_intr(husb);
if (!err) { if (!err) {
for (i = 0; i < HCI_MAX_BULK_RX; i++) for (i = 0; i < HCI_MAX_BULK_RX; i++)
hci_usb_rx_submit(husb, NULL); hci_usb_rx_submit(husb, NULL);
} else { } else
clear_bit(HCI_RUNNING, &hdev->flags); clear_bit(HCI_RUNNING, &hdev->flags);
MOD_DEC_USE_COUNT;
}
write_unlock_irqrestore(&husb->completion_lock, flags); write_unlock_irqrestore(&husb->completion_lock, flags);
return err; return err;
...@@ -271,8 +268,6 @@ static int hci_usb_close(struct hci_dev *hdev) ...@@ -271,8 +268,6 @@ static int hci_usb_close(struct hci_dev *hdev)
hci_usb_flush(hdev); hci_usb_flush(hdev);
write_unlock_irqrestore(&husb->completion_lock, flags); write_unlock_irqrestore(&husb->completion_lock, flags);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -758,6 +753,8 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -758,6 +753,8 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
hdev->send = hci_usb_send_frame; hdev->send = hci_usb_send_frame;
hdev->destruct = hci_usb_destruct; hdev->destruct = hci_usb_destruct;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
goto probe_error; goto probe_error;
......
...@@ -84,8 +84,6 @@ static void hci_vhci_destruct(struct hci_dev *hdev) ...@@ -84,8 +84,6 @@ static void hci_vhci_destruct(struct hci_dev *hdev)
vhci = (struct hci_vhci_struct *) hdev->driver_data; vhci = (struct hci_vhci_struct *) hdev->driver_data;
kfree(vhci); kfree(vhci);
MOD_DEC_USE_COUNT;
} }
static int hci_vhci_send_frame(struct sk_buff *skb) static int hci_vhci_send_frame(struct sk_buff *skb)
...@@ -288,11 +286,12 @@ static int hci_vhci_chr_open(struct inode *inode, struct file * file) ...@@ -288,11 +286,12 @@ static int hci_vhci_chr_open(struct inode *inode, struct file * file)
hdev->send = hci_vhci_send_frame; hdev->send = hci_vhci_send_frame;
hdev->destruct = hci_vhci_destruct; hdev->destruct = hci_vhci_destruct;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
kfree(hci_vhci); kfree(hci_vhci);
return -EBUSY; return -EBUSY;
} }
MOD_INC_USE_COUNT;
file->private_data = hci_vhci; file->private_data = hci_vhci;
return 0; return 0;
......
...@@ -118,6 +118,8 @@ struct hci_dev { ...@@ -118,6 +118,8 @@ struct hci_dev {
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
#endif #endif
struct module *owner;
int (*open)(struct hci_dev *hdev); int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev);
...@@ -299,12 +301,30 @@ static inline void hci_sched_tx(struct hci_dev *hdev) ...@@ -299,12 +301,30 @@ static inline void hci_sched_tx(struct hci_dev *hdev)
} }
/* ----- HCI Devices ----- */ /* ----- HCI Devices ----- */
static inline void hci_dev_put(struct hci_dev *d) static inline void __hci_dev_put(struct hci_dev *d)
{ {
if (atomic_dec_and_test(&d->refcnt)) if (atomic_dec_and_test(&d->refcnt))
d->destruct(d); d->destruct(d);
} }
#define hci_dev_hold(d) atomic_inc(&d->refcnt)
static inline void hci_dev_put(struct hci_dev *d)
{
__hci_dev_put(d);
module_put(d->owner);
}
static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
{
atomic_inc(&d->refcnt);
return d;
}
static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
{
if (try_module_get(d->owner))
return __hci_dev_hold(d);
return NULL;
}
#define hci_dev_lock(d) spin_lock(&d->lock) #define hci_dev_lock(d) spin_lock(&d->lock)
#define hci_dev_unlock(d) spin_unlock(&d->lock) #define hci_dev_unlock(d) spin_unlock(&d->lock)
......
...@@ -218,8 +218,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -218,8 +218,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
read_lock_bh(&hci_dev_list_lock); read_lock_bh(&hci_dev_list_lock);
list_for_each(p, &hci_dev_list) { list_for_each(p, &hci_dev_list) {
struct hci_dev *d; struct hci_dev *d = list_entry(p, struct hci_dev, list);
d = list_entry(p, struct hci_dev, list);
if (!test_bit(HCI_UP, &d->flags)) if (!test_bit(HCI_UP, &d->flags))
continue; continue;
...@@ -241,7 +240,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -241,7 +240,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
} }
if (hdev) if (hdev)
hci_dev_hold(hdev); hdev = hci_dev_hold(hdev);
read_unlock_bh(&hci_dev_list_lock); read_unlock_bh(&hci_dev_list_lock);
return hdev; return hdev;
......
...@@ -287,10 +287,10 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) ...@@ -287,10 +287,10 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
} }
/* Get HCI device by index. /* Get HCI device by index.
* Device is locked on return. */ * Device is held on return. */
struct hci_dev *hci_dev_get(int index) struct hci_dev *hci_dev_get(int index)
{ {
struct hci_dev *hdev; struct hci_dev *hdev = NULL;
struct list_head *p; struct list_head *p;
BT_DBG("%d", index); BT_DBG("%d", index);
...@@ -300,14 +300,12 @@ struct hci_dev *hci_dev_get(int index) ...@@ -300,14 +300,12 @@ struct hci_dev *hci_dev_get(int index)
read_lock(&hci_dev_list_lock); read_lock(&hci_dev_list_lock);
list_for_each(p, &hci_dev_list) { list_for_each(p, &hci_dev_list) {
hdev = list_entry(p, struct hci_dev, list); struct hci_dev *d = list_entry(p, struct hci_dev, list);
if (hdev->id == index) { if (d->id == index) {
hci_dev_hold(hdev); hdev = hci_dev_hold(d);
goto done; break;
} }
} }
hdev = NULL;
done:
read_unlock(&hci_dev_list_lock); read_unlock(&hci_dev_list_lock);
return hdev; return hdev;
} }
...@@ -483,6 +481,7 @@ int hci_dev_open(__u16 dev) ...@@ -483,6 +481,7 @@ int hci_dev_open(__u16 dev)
} }
if (!ret) { if (!ret) {
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags); set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP); hci_notify(hdev, HCI_DEV_UP);
} else { } else {
...@@ -567,6 +566,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -567,6 +566,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hdev->flags = 0; hdev->flags = 0;
hci_req_unlock(hdev); hci_req_unlock(hdev);
hci_dev_put(hdev);
return 0; return 0;
} }
...@@ -790,7 +791,7 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -790,7 +791,7 @@ int hci_register_dev(struct hci_dev *hdev)
struct list_head *head = &hci_dev_list, *p; struct list_head *head = &hci_dev_list, *p;
int id = 0; int id = 0;
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner);
if (!hdev->open || !hdev->close || !hdev->destruct) if (!hdev->open || !hdev->close || !hdev->destruct)
return -EINVAL; return -EINVAL;
...@@ -834,8 +835,6 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -834,8 +835,6 @@ int hci_register_dev(struct hci_dev *hdev)
atomic_set(&hdev->promisc, 0); atomic_set(&hdev->promisc, 0);
MOD_INC_USE_COUNT;
write_unlock_bh(&hci_dev_list_lock); write_unlock_bh(&hci_dev_list_lock);
hci_dev_proc_init(hdev); hci_dev_proc_init(hdev);
...@@ -862,9 +861,7 @@ int hci_unregister_dev(struct hci_dev *hdev) ...@@ -862,9 +861,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_UNREG); hci_notify(hdev, HCI_DEV_UNREG);
hci_run_hotplug(hdev->name, "unregister"); hci_run_hotplug(hdev->name, "unregister");
hci_dev_put(hdev); __hci_dev_put(hdev);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment