diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index add9485ca5b6..128cae4e8629 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -143,6 +143,8 @@ static int ath3k_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { usb_set_intfdata(intf, NULL); + kfree(data->fw_data); + kfree(data); return -EIO; } diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index eafd4af0746e..b0c84c19f442 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -39,7 +39,7 @@ #define VERSION "1.2" -static struct usb_device_id bcm203x_table[] = { +static const struct usb_device_id bcm203x_table[] = { /* Broadcom Blutonium (BCM2033) */ { USB_DEVICE(0x0a5c, 0x2033) }, diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 2a00707aba3b..005919ab043c 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -703,7 +703,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i data->hdev = hdev; - hdev->type = HCI_USB; + hdev->bus = HCI_USB; hdev->driver_data = data; SET_HCIDEV_DEV(hdev, &intf->dev); diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index c2cf81144715..d9bf87ca9e83 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -736,7 +736,7 @@ static int bluecard_open(bluecard_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index c115285867c3..d945cd12433a 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -469,7 +469,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * return -ENOMEM; } - hdev->type = HCI_USB; + hdev->bus = HCI_USB; hdev->driver_data = data; data->hdev = hdev; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 9f5926aaf57f..027cb8bf650f 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -582,7 +582,7 @@ static int bt3c_open(bt3c_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index d43b5cb864ef..3126a3d0c45c 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -26,7 +26,8 @@ #include "btmrvl_drv.h" struct btmrvl_debugfs_data { - struct dentry *root_dir, *config_dir, *status_dir; + struct dentry *config_dir; + struct dentry *status_dir; /* config */ struct dentry *psmode; @@ -363,6 +364,9 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) struct btmrvl_private *priv = hdev->driver_data; struct btmrvl_debugfs_data *dbg; + if (!hdev->debugfs) + return; + dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); priv->debugfs_data = dbg; @@ -371,9 +375,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) return; } - dbg->root_dir = debugfs_create_dir("btmrvl", NULL); - - dbg->config_dir = debugfs_create_dir("config", dbg->root_dir); + dbg->config_dir = debugfs_create_dir("config", hdev->debugfs); dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir, hdev->driver_data, &btmrvl_psmode_fops); @@ -388,7 +390,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, hdev->driver_data, &btmrvl_hscfgcmd_fops); - dbg->status_dir = debugfs_create_dir("status", dbg->root_dir); + dbg->status_dir = debugfs_create_dir("status", hdev->debugfs); dbg->curpsmode = debugfs_create_file("curpsmode", 0444, dbg->status_dir, hdev->driver_data, @@ -425,7 +427,5 @@ void btmrvl_debugfs_remove(struct hci_dev *hdev) debugfs_remove(dbg->txdnldready); debugfs_remove(dbg->status_dir); - debugfs_remove(dbg->root_dir); - kfree(dbg); } diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index f97771ce432c..53a43adf2e21 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -563,7 +563,7 @@ struct btmrvl_private *btmrvl_add_card(void *card) priv->btmrvl_dev.tx_dnld_rdy = true; - hdev->type = HCI_SDIO; + hdev->bus = HCI_SDIO; hdev->open = btmrvl_open; hdev->close = btmrvl_close; hdev->flush = btmrvl_flush; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 57d965b7f521..94f1f55f81f0 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -976,7 +976,7 @@ static struct sdio_driver bt_mrvl_sdio = { .remove = btmrvl_sdio_remove, }; -static int btmrvl_sdio_init_module(void) +static int __init btmrvl_sdio_init_module(void) { if (sdio_register_driver(&bt_mrvl_sdio) != 0) { BT_ERR("SDIO Driver Registration Failed"); @@ -989,7 +989,7 @@ static int btmrvl_sdio_init_module(void) return 0; } -static void btmrvl_sdio_exit_module(void) +static void __exit btmrvl_sdio_exit_module(void) { /* Set the flag as user is removing this module. */ user_rmmod = 1; diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 7e298275c8f6..76e5127884f0 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -326,7 +326,7 @@ static int btsdio_probe(struct sdio_func *func, return -ENOMEM; } - hdev->type = HCI_SDIO; + hdev->bus = HCI_SDIO; hdev->driver_data = data; data->hdev = hdev; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 91c523099804..60c0953d7d00 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -500,7 +500,7 @@ static int btuart_open(btuart_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a699f09ddf7c..5d9cc53bd643 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -939,7 +939,7 @@ static int btusb_probe(struct usb_interface *intf, return -ENOMEM; } - hdev->type = HCI_USB; + hdev->bus = HCI_USB; hdev->driver_data = data; data->hdev = hdev; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 697591941e17..17788317c51a 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -485,7 +485,7 @@ static int dtl1_open(dtl1_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index aa0919386b8c..76a1abb8f214 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -383,7 +383,7 @@ static int hci_uart_register_dev(struct hci_uart *hu) hu->hdev = hdev; - hdev->type = HCI_UART; + hdev->bus = HCI_UART; hdev->driver_data = hu; hdev->open = hci_uart_open; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 7595274103fd..bb0aefdb4267 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -236,7 +236,7 @@ static int vhci_open(struct inode *inode, struct file *file) data->hdev = hdev; - hdev->type = HCI_VIRTUAL; + hdev->bus = HCI_VIRTUAL; hdev->driver_data = data; hdev->open = vhci_open_dev; diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ed3aea1605e8..fc0c502d9fd1 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -43,7 +43,7 @@ #define HCI_NOTIFY_CONN_DEL 2 #define HCI_NOTIFY_VOICE_SETTING 3 -/* HCI device types */ +/* HCI bus types */ #define HCI_VIRTUAL 0 #define HCI_USB 1 #define HCI_PCCARD 2 @@ -52,6 +52,10 @@ #define HCI_PCI 5 #define HCI_SDIO 6 +/* HCI controller types */ +#define HCI_BREDR 0x00 +#define HCI_80211 0x01 + /* HCI device quirks */ enum { HCI_QUIRK_NO_RESET, diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7b86094a894b..ce3c99e5fa25 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -70,7 +70,8 @@ struct hci_dev { char name[8]; unsigned long flags; __u16 id; - __u8 type; + __u8 bus; + __u8 dev_type; bdaddr_t bdaddr; __u8 dev_name[248]; __u8 dev_class[3]; @@ -134,6 +135,8 @@ struct hci_dev { atomic_t promisc; + struct dentry *debugfs; + struct device *parent; struct device dev; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 94ba34982021..4ad23192c7a5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -491,6 +491,10 @@ int hci_dev_open(__u16 dev) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) set_bit(HCI_RAW, &hdev->flags); + /* Treat all non BR/EDR controllers as raw devices for now */ + if (hdev->dev_type != HCI_BREDR) + set_bit(HCI_RAW, &hdev->flags); + if (hdev->open(hdev)) { ret = -EIO; goto done; @@ -797,7 +801,7 @@ int hci_get_dev_info(void __user *arg) strcpy(di.name, hdev->name); di.bdaddr = hdev->bdaddr; - di.type = hdev->type; + di.type = (hdev->bus & 0x0f) | (hdev->dev_type << 4); di.flags = hdev->flags; di.pkt_type = hdev->pkt_type; di.acl_mtu = hdev->acl_mtu; @@ -869,8 +873,8 @@ int hci_register_dev(struct hci_dev *hdev) struct list_head *head = &hci_dev_list, *p; int i, id = 0; - BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, - hdev->type, hdev->owner); + BT_DBG("%p name %s bus %d owner %p", hdev, hdev->name, + hdev->bus, hdev->owner); if (!hdev->open || !hdev->close || !hdev->destruct) return -EINVAL; @@ -946,7 +950,7 @@ int hci_unregister_dev(struct hci_dev *hdev) { int i; - BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); write_lock_bh(&hci_dev_list_lock); list_del(&hdev->list); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 592da5c909c1..6c57fc71c7e2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1698,6 +1698,7 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu hci_conn_add_sysfs(conn); break; + case 0x11: /* Unsupported Feature or Parameter Value */ case 0x1c: /* SCO interval rejected */ case 0x1a: /* Unsupported Remote Feature */ case 0x1f: /* Unspecified error */ diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 688cfebfbee0..38f08f6b86f6 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -329,6 +329,9 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_ } if (mask & HCI_CMSG_TSTAMP) { +#ifdef CONFIG_COMPAT + struct compat_timeval ctv; +#endif struct timeval tv; void *data; int len; @@ -339,7 +342,6 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_ len = sizeof(tv); #ifdef CONFIG_COMPAT if (msg->msg_flags & MSG_CMSG_COMPAT) { - struct compat_timeval ctv; ctv.tv_sec = tv.tv_sec; ctv.tv_usec = tv.tv_usec; data = &ctv; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 2bc6f6a8de68..1a79a6c7e30e 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -9,6 +10,9 @@ struct class *bt_class = NULL; EXPORT_SYMBOL_GPL(bt_class); +struct dentry *bt_debugfs = NULL; +EXPORT_SYMBOL_GPL(bt_debugfs); + static struct workqueue_struct *bt_workq; static inline char *link_typetostr(int type) @@ -166,9 +170,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn) queue_work(bt_workq, &conn->work_del); } -static inline char *host_typetostr(int type) +static inline char *host_bustostr(int bus) { - switch (type) { + switch (bus) { case HCI_VIRTUAL: return "VIRTUAL"; case HCI_USB: @@ -188,10 +192,28 @@ static inline char *host_typetostr(int type) } } +static inline char *host_typetostr(int type) +{ + switch (type) { + case HCI_BREDR: + return "BR/EDR"; + case HCI_80211: + return "802.11"; + default: + return "UNKNOWN"; + } +} + +static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_dev *hdev = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", host_bustostr(hdev->bus)); +} + static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", host_typetostr(hdev->type)); + return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type)); } static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -251,32 +273,6 @@ static ssize_t show_hci_revision(struct device *dev, struct device_attribute *at return sprintf(buf, "%d\n", hdev->hci_rev); } -static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_dev *hdev = dev_get_drvdata(dev); - struct inquiry_cache *cache = &hdev->inq_cache; - struct inquiry_entry *e; - int n = 0; - - hci_dev_lock_bh(hdev); - - for (e = cache->list; e; e = e->next) { - struct inquiry_data *data = &e->data; - bdaddr_t bdaddr; - baswap(&bdaddr, &data->bdaddr); - n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", - batostr(&bdaddr), - data->pscan_rep_mode, data->pscan_period_mode, - data->pscan_mode, data->dev_class[2], - data->dev_class[1], data->dev_class[0], - __le16_to_cpu(data->clock_offset), - data->rssi, data->ssp_mode, e->timestamp); - } - - hci_dev_unlock_bh(hdev); - return n; -} - static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); @@ -355,6 +351,7 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib return count; } +static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL); static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static DEVICE_ATTR(class, S_IRUGO, show_class, NULL); @@ -363,7 +360,6 @@ static DEVICE_ATTR(features, S_IRUGO, show_features, NULL); static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); -static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL); static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, show_idle_timeout, store_idle_timeout); @@ -373,6 +369,7 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, show_sniff_min_interval, store_sniff_min_interval); static struct attribute *bt_host_attrs[] = { + &dev_attr_bus.attr, &dev_attr_type.attr, &dev_attr_name.attr, &dev_attr_class.attr, @@ -381,7 +378,6 @@ static struct attribute *bt_host_attrs[] = { &dev_attr_manufacturer.attr, &dev_attr_hci_version.attr, &dev_attr_hci_revision.attr, - &dev_attr_inquiry_cache.attr, &dev_attr_idle_timeout.attr, &dev_attr_sniff_max_interval.attr, &dev_attr_sniff_min_interval.attr, @@ -409,12 +405,52 @@ static struct device_type bt_host = { .release = bt_host_release, }; +static int inquiry_cache_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct hci_dev *hdev = file->private_data; + struct inquiry_cache *cache = &hdev->inq_cache; + struct inquiry_entry *e; + char buf[4096]; + int n = 0; + + hci_dev_lock_bh(hdev); + + for (e = cache->list; e; e = e->next) { + struct inquiry_data *data = &e->data; + bdaddr_t bdaddr; + baswap(&bdaddr, &data->bdaddr); + n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", + batostr(&bdaddr), + data->pscan_rep_mode, data->pscan_period_mode, + data->pscan_mode, data->dev_class[2], + data->dev_class[1], data->dev_class[0], + __le16_to_cpu(data->clock_offset), + data->rssi, data->ssp_mode, e->timestamp); + } + + hci_dev_unlock_bh(hdev); + + return simple_read_from_buffer(userbuf, count, ppos, buf, n); +} + +static const struct file_operations inquiry_cache_fops = { + .open = inquiry_cache_open, + .read = inquiry_cache_read, +}; + int hci_register_sysfs(struct hci_dev *hdev) { struct device *dev = &hdev->dev; int err; - BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); dev->type = &bt_host; dev->class = bt_class; @@ -428,12 +464,24 @@ int hci_register_sysfs(struct hci_dev *hdev) if (err < 0) return err; + if (!bt_debugfs) + return 0; + + hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); + if (!hdev->debugfs) + return 0; + + debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, + hdev, &inquiry_cache_fops); + return 0; } void hci_unregister_sysfs(struct hci_dev *hdev) { - BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); + + debugfs_remove_recursive(hdev->debugfs); device_del(&hdev->dev); } @@ -444,6 +492,8 @@ int __init bt_sysfs_init(void) if (!bt_workq) return -ENOMEM; + bt_debugfs = debugfs_create_dir("bluetooth", NULL); + bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { destroy_workqueue(bt_workq); @@ -455,7 +505,9 @@ int __init bt_sysfs_init(void) void bt_sysfs_cleanup(void) { - destroy_workqueue(bt_workq); - class_destroy(bt_class); + + debugfs_remove_recursive(bt_debugfs); + + destroy_workqueue(bt_workq); }