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