diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-08-10 21:13:12 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-08-10 21:13:12 +0200 |
commit | 57f784fed3b9a33084c0cd0f6d08d98f87d2193f (patch) | |
tree | 8af841487980e1efea4942b057195e43847afd4d | |
parent | mwifiex: add AES_CMAC support in key_material cmd (diff) | |
parent | Bluetooth: Refactor in hci_le_conn_complete_evt (diff) | |
download | linux-57f784fed3b9a33084c0cd0f6d08d98f87d2193f.tar.xz linux-57f784fed3b9a33084c0cd0f6d08d98f87d2193f.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
29 files changed, 415 insertions, 197 deletions
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 37ae175162f3..364f82b34d03 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) { BT_ERR("Can't allocate memory for data structure"); return -ENOMEM; @@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id data->urb = usb_alloc_urb(0, GFP_KERNEL); if (!data->urb) { BT_ERR("Can't allocate URB"); - kfree(data); return -ENOMEM; } if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) { BT_ERR("Mini driver request failed"); usb_free_urb(data->urb); - kfree(data); return -EIO; } @@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id BT_ERR("Can't allocate memory for mini driver"); release_firmware(firmware); usb_free_urb(data->urb); - kfree(data); return -ENOMEM; } @@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id BT_ERR("Firmware request failed"); usb_free_urb(data->urb); kfree(data->buffer); - kfree(data); return -EIO; } @@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id release_firmware(firmware); usb_free_urb(data->urb); kfree(data->buffer); - kfree(data); return -ENOMEM; } @@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf) usb_free_urb(data->urb); kfree(data->fw_data); kfree(data->buffer); - kfree(data); } static struct usb_driver bcm203x_driver = { diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 32e825144fe9..995aee9cba22 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i } /* Initialize control structure and load firmware */ - data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL); if (!data) { BT_ERR("Can't allocate memory for control structure"); goto done; @@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) { BT_ERR("Firmware request failed"); - goto error; + goto done; } BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); @@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can't allocate HCI device"); - goto error; + goto done; } data->hdev = hdev; @@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); hci_free_dev(hdev); - goto error; + goto done; } usb_set_intfdata(intf, data); @@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i release: release_firmware(firmware); -error: - kfree(data); - done: return -EIO; } @@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf) hci_unregister_dev(hdev); hci_free_dev(hdev); - kfree(data); } static struct usb_driver bfusb_driver = { diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 66c3a6770c41..0c0838d9b56c 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link) bluecard_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link) static void bluecard_detach(struct pcmcia_device *link) { - bluecard_info_t *info = link->priv; - bluecard_release(link); - kfree(info); } diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 29caaed2d715..2fe4a8031348 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * init_usb_anchor(&data->rx_anchor); hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); + if (!hdev) return -ENOMEM; - } hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); @@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } @@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf) hci_free_dev(data->hdev); kfree_skb(data->rx_skb[0]); kfree_skb(data->rx_skb[1]); - kfree(data); } static struct usb_driver bpa10x_driver = { diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 8925b6d672a6..7ffd3f407144 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link) bt3c_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link) static void bt3c_detach(struct pcmcia_device *link) { - bt3c_info_t *info = link->priv; - bt3c_release(link); - kfree(info); } static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data) diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 6a9e9717d3ab..03b3acba6143 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -956,11 +956,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d", id->vendor, id->device, id->class, func->num); - card = kzalloc(sizeof(*card), GFP_KERNEL); - if (!card) { - ret = -ENOMEM; - goto done; - } + card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; card->func = func; @@ -974,8 +972,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func, if (btmrvl_sdio_register_dev(card) < 0) { BT_ERR("Failed to register BT device!"); - ret = -ENODEV; - goto free_card; + return -ENODEV; } /* Disable the interrupts on the card */ @@ -1023,9 +1020,6 @@ disable_host_int: btmrvl_sdio_disable_host_int(card); unreg_dev: btmrvl_sdio_unregister_dev(card); -free_card: - kfree(card); -done: return ret; } @@ -1047,7 +1041,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func) BT_DBG("unregester dev"); btmrvl_sdio_unregister_dev(card); btmrvl_remove_card(card->priv); - kfree(card); } } } diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index e10ea0347051..4a9909713874 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func, tuple = tuple->next; } - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func, skb_queue_head_init(&data->txq); hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); + if (!hdev) return -ENOMEM; - } hdev->bus = HCI_SDIO; hci_set_drvdata(hdev, data); @@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func, err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } @@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func) hci_unregister_dev(hdev); hci_free_dev(hdev); - kfree(data); } static struct sdio_driver btsdio_driver = { diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 21e803a6a281..2f510a87b28f 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link) btuart_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link) static void btuart_detach(struct pcmcia_device *link) { - btuart_info_t *info = link->priv; - btuart_release(link); - kfree(info); } static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e27221411036..f637c2550016 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -952,7 +952,7 @@ static int btusb_probe(struct usb_interface *intf, return -ENODEV; } - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -975,10 +975,8 @@ static int btusb_probe(struct usb_interface *intf, } } - if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) { - kfree(data); + if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) return -ENODEV; - } data->cmdreq_type = USB_TYPE_CLASS; @@ -998,10 +996,8 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->deferred); hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); + if (!hdev) return -ENOMEM; - } hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); @@ -1069,7 +1065,6 @@ static int btusb_probe(struct usb_interface *intf, data->isoc, data); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } } @@ -1077,7 +1072,6 @@ static int btusb_probe(struct usb_interface *intf, err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } @@ -1110,7 +1104,6 @@ static void btusb_disconnect(struct usb_interface *intf) usb_driver_release_interface(&btusb_driver, data->isoc); hci_free_dev(hdev); - kfree(data); } #ifdef CONFIG_PM diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c index 88694697f34f..4ad7b35cfc0e 100644 --- a/drivers/bluetooth/btwilink.c +++ b/drivers/bluetooth/btwilink.c @@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev) struct hci_dev *hdev; int err; - hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL); + hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL); if (!hst) return -ENOMEM; /* Expose "hciX" device to user space */ hdev = hci_alloc_dev(); - if (!hdev) { - kfree(hst); + if (!hdev) return -ENOMEM; - } BT_DBG("hdev %p", hdev); @@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev) err = hci_register_dev(hdev); if (err < 0) { BT_ERR("Can't register HCI device error %d", err); - kfree(hst); hci_free_dev(hdev); return err; } @@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev) hci_unregister_dev(hdev); hci_free_dev(hdev); - kfree(hst); dev_set_drvdata(&pdev->dev, NULL); return 0; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 97a7784db4a2..036cb366fe6e 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link) dtl1_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link) dtl1_close(info); pcmcia_disable_device(link); - kfree(info); } static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 565d4bee1e49..ede036977ae8 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -27,6 +27,7 @@ #include <linux/poll.h> #include <net/sock.h> +#include <linux/seq_file.h> #ifndef AF_BLUETOOTH #define AF_BLUETOOTH 31 @@ -202,6 +203,10 @@ enum { struct bt_sock_list { struct hlist_head head; rwlock_t lock; +#ifdef CONFIG_PROC_FS + struct file_operations fops; + int (* custom_seq_show)(struct seq_file *, void *); +#endif }; int bt_sock_register(int proto, const struct net_proto_family *ops); @@ -292,6 +297,11 @@ extern void hci_sock_cleanup(void); extern int bt_sysfs_init(void); extern void bt_sysfs_cleanup(void); +extern int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)); +extern void bt_procfs_cleanup(struct net *net, const char *name); + extern struct dentry *bt_debugfs; int l2cap_init(void); diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ccd723e0f783..23cf413e2acf 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -62,6 +62,15 @@ /* First BR/EDR Controller shall have ID = 0 */ #define HCI_BREDR_ID 0 +/* AMP controller status */ +#define AMP_CTRL_POWERED_DOWN 0x00 +#define AMP_CTRL_BLUETOOTH_ONLY 0x01 +#define AMP_CTRL_NO_CAPACITY 0x02 +#define AMP_CTRL_LOW_CAPACITY 0x03 +#define AMP_CTRL_MEDIUM_CAPACITY 0x04 +#define AMP_CTRL_HIGH_CAPACITY 0x05 +#define AMP_CTRL_FULL_CAPACITY 0x06 + /* HCI device quirks */ enum { HCI_QUIRK_RESET_ON_CLOSE, @@ -1295,6 +1304,8 @@ struct hci_ev_num_comp_blocks { } __packed; /* Low energy meta events */ +#define LE_CONN_ROLE_MASTER 0x00 + #define HCI_EV_LE_CONN_COMPLETE 0x01 struct hci_ev_le_conn_complete { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 475b8c04ba52..41d943926d2c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -115,12 +115,6 @@ struct oob_data { u8 randomizer[16]; }; -struct adv_entry { - struct list_head list; - bdaddr_t bdaddr; - u8 bdaddr_type; -}; - struct le_scan_params { u8 type; u16 interval; @@ -356,16 +350,16 @@ extern rwlock_t hci_cb_list_lock; /* ----- HCI interface to upper protocols ----- */ extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status); +extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); extern int l2cap_disconn_ind(struct hci_conn *hcon); -extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); +extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status); -extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); +extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); +extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); /* ----- Inquiry cache ----- */ @@ -587,8 +581,7 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { - BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt), - atomic_read(&conn->refcnt) + 1); + BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt)); atomic_inc(&conn->refcnt); cancel_delayed_work(&conn->disc_work); @@ -596,8 +589,7 @@ static inline void hci_conn_hold(struct hci_conn *conn) static inline void hci_conn_put(struct hci_conn *conn) { - BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt), - atomic_read(&conn->refcnt) - 1); + BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt)); if (atomic_dec_and_test(&conn->refcnt)) { unsigned long timeo; @@ -1056,7 +1048,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_interleaved_discovery(struct hci_dev *hdev); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); - +bool mgmt_valid_hdev(struct hci_dev *hdev); int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); /* HCI info for socket */ diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index a7679f8913d2..d206296137e2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -671,20 +671,8 @@ enum { L2CAP_EV_RECV_FRAME, }; -static inline void l2cap_chan_hold(struct l2cap_chan *c) -{ - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); - - atomic_inc(&c->refcnt); -} - -static inline void l2cap_chan_put(struct l2cap_chan *c) -{ - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); - - if (atomic_dec_and_test(&c->refcnt)) - kfree(c); -} +void l2cap_chan_hold(struct l2cap_chan *c); +void l2cap_chan_put(struct l2cap_chan *c); static inline void l2cap_chan_lock(struct l2cap_chan *chan) { @@ -771,7 +759,6 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); struct l2cap_chan *l2cap_chan_create(void); void l2cap_chan_close(struct l2cap_chan *chan, int reason); -void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst, u8 dst_type); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index ca356a734920..50993a531d45 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -108,8 +108,8 @@ struct smp_cmd_security_req { #define SMP_CONFIRM_FAILED 0x04 #define SMP_PAIRING_NOTSUPP 0x05 #define SMP_ENC_KEY_SIZE 0x06 -#define SMP_CMD_NOTSUPP 0x07 -#define SMP_UNSPECIFIED 0x08 +#define SMP_CMD_NOTSUPP 0x07 +#define SMP_UNSPECIFIED 0x08 #define SMP_REPEATED_ATTEMPTS 0x09 #define SMP_MIN_ENC_KEY_SIZE 7 @@ -123,8 +123,8 @@ struct smp_chan { struct l2cap_conn *conn; u8 preq[7]; /* SMP Pairing Request */ u8 prsp[7]; /* SMP Pairing Response */ - u8 prnd[16]; /* SMP Pairing Random (local) */ - u8 rrnd[16]; /* SMP Pairing Random (remote) */ + u8 prnd[16]; /* SMP Pairing Random (local) */ + u8 rrnd[16]; /* SMP Pairing Random (remote) */ u8 pcnf[16]; /* SMP Pairing Confirm */ u8 tk[16]; /* SMP Temporary Key */ u8 enc_key_size; diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 4ff0bf3ba9a5..0760d1fed6f0 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -316,7 +316,7 @@ send_rsp: static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, struct a2mp_cmd *hdr) { - BT_DBG("ident %d code %d", hdr->ident, hdr->code); + BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code); skb_pull(skb, le16_to_cpu(hdr->len)); return 0; @@ -325,17 +325,19 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, /* Handle A2MP signalling */ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { - struct a2mp_cmd *hdr = (void *) skb->data; + struct a2mp_cmd *hdr; struct amp_mgr *mgr = chan->data; int err = 0; amp_mgr_get(mgr); while (skb->len >= sizeof(*hdr)) { - struct a2mp_cmd *hdr = (void *) skb->data; - u16 len = le16_to_cpu(hdr->len); + u16 len; - BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len); + hdr = (void *) skb->data; + len = le16_to_cpu(hdr->len); + + BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); skb_pull(skb, sizeof(*hdr)); @@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) if (err) { struct a2mp_cmd_rej rej; + rej.reason = __constant_cpu_to_le16(0); + hdr = (void *) skb->data; BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); @@ -412,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) static void a2mp_chan_close_cb(struct l2cap_chan *chan) { - l2cap_chan_destroy(chan); + l2cap_chan_put(chan); } static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index f7db5792ec64..58f9762b339a 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -28,6 +28,7 @@ #include <asm/ioctls.h> #include <net/bluetooth/bluetooth.h> +#include <linux/proc_fs.h> #define VERSION "2.16" @@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) } EXPORT_SYMBOL(bt_sock_wait_state); +#ifdef CONFIG_PROC_FS +struct bt_seq_state { + struct bt_sock_list *l; +}; + +static void *bt_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(seq->private->l->lock) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + read_lock(&l->lock); + return seq_hlist_start_head(&l->head, *pos); +} + +static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + return seq_hlist_next(v, &l->head, pos); +} + +static void bt_seq_stop(struct seq_file *seq, void *v) + __releases(seq->private->l->lock) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + read_unlock(&l->lock); +} + +static int bt_seq_show(struct seq_file *seq, void *v) +{ + struct sock *sk; + struct bt_sock *bt; + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + bdaddr_t src_baswapped, dst_baswapped; + + if (v == SEQ_START_TOKEN) { + seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); + + if (l->custom_seq_show) { + seq_putc(seq, ' '); + l->custom_seq_show(seq, v); + } + + seq_putc(seq, '\n'); + } else { + sk = sk_entry(v); + bt = bt_sk(sk); + baswap(&src_baswapped, &bt->src); + baswap(&dst_baswapped, &bt->dst); + + seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", + sk, + atomic_read(&sk->sk_refcnt), + sk_rmem_alloc_get(sk), + sk_wmem_alloc_get(sk), + sock_i_uid(sk), + sock_i_ino(sk), + &src_baswapped, + &dst_baswapped, + bt->parent? sock_i_ino(bt->parent): 0LU); + + if (l->custom_seq_show) { + seq_putc(seq, ' '); + l->custom_seq_show(seq, v); + } + + seq_putc(seq, '\n'); + } + return 0; +} + +static struct seq_operations bt_seq_ops = { + .start = bt_seq_start, + .next = bt_seq_next, + .stop = bt_seq_stop, + .show = bt_seq_show, +}; + +static int bt_seq_open(struct inode *inode, struct file *file) +{ + struct bt_sock_list *sk_list; + struct bt_seq_state *s; + + sk_list = PDE(inode)->data; + s = __seq_open_private(file, &bt_seq_ops, + sizeof(struct bt_seq_state)); + if (s == NULL) + return -ENOMEM; + + s->l = sk_list; + return 0; +} + +int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)) +{ + struct proc_dir_entry * pde; + + sk_list->custom_seq_show = seq_show; + + sk_list->fops.owner = module; + sk_list->fops.open = bt_seq_open; + sk_list->fops.read = seq_read; + sk_list->fops.llseek = seq_lseek; + sk_list->fops.release = seq_release_private; + + pde = proc_net_fops_create(net, name, 0, &sk_list->fops); + if (pde == NULL) + return -ENOMEM; + + pde->data = sk_list; + + return 0; +} + +void bt_procfs_cleanup(struct net *net, const char *name) +{ + proc_net_remove(net, name); +} +#else +int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)) +{ + return 0; +} + +void bt_procfs_cleanup(struct net *net, const char *name) +{ +} +#endif +EXPORT_SYMBOL(bt_procfs_init); +EXPORT_SYMBOL(bt_procfs_cleanup); + static struct net_proto_family bt_sock_family_ops = { .owner = THIS_MODULE, .family = PF_BLUETOOTH, diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5e5f5b410e0b..5b6cc0bf4dec 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -29,6 +29,10 @@ #include "bnep.h" +static struct bt_sock_list bnep_sk_list = { + .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock) +}; + static int bnep_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&bnep_sk_list, sk); + sock_orphan(sk); sock_put(sk); return 0; @@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&bnep_sk_list, sk); return 0; } @@ -222,19 +229,30 @@ int __init bnep_sock_init(void) return err; err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register BNEP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create BNEP proc file"); + bt_sock_unregister(BTPROTO_BNEP); + goto error; + } + + BT_INFO("BNEP socket layer initialized"); return 0; error: - BT_ERR("Can't register BNEP socket"); proto_unregister(&bnep_proto); return err; } void __exit bnep_sock_cleanup(void) { + bt_procfs_cleanup(&init_net, "bnep"); if (bt_sock_unregister(BTPROTO_BNEP) < 0) BT_ERR("Can't unregister BNEP socket"); diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 311668d14571..d5cacef52748 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -42,6 +42,10 @@ #include "cmtp.h" +static struct bt_sock_list cmtp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock) +}; + static int cmtp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&cmtp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&cmtp_sk_list, sk); + return 0; } @@ -232,19 +240,30 @@ int cmtp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register CMTP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create CMTP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("CMTP socket layer initialized"); return 0; error: - BT_ERR("Can't register CMTP socket"); proto_unregister(&cmtp_proto); return err; } void cmtp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "cmtp"); if (bt_sock_unregister(BTPROTO_CMTP) < 0) BT_ERR("Can't unregister CMTP socket"); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4de5db18d5a..fa974a19d365 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev) hci_dev_hold(hdev); set_bit(HCI_UP, &hdev->flags); hci_notify(hdev, HCI_DEV_UP); - if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { + if (!test_bit(HCI_SETUP, &hdev->dev_flags) && + mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 1); hci_dev_unlock(hdev); @@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) * and no tasks are scheduled. */ hdev->close(hdev); - if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { + if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && + mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 0); hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f9..32e21ad36a68 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[3] & LMP_RSSI_INQ) events[4] |= 0x02; /* Inquiry Result with RSSI */ - if (hdev->features[5] & LMP_SNIFF_SUBR) + if (lmp_sniffsubr_capable(hdev)) events[5] |= 0x20; /* Sniff Subrating */ if (hdev->features[5] & LMP_PAUSE_ENC) @@ -522,13 +522,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[6] & LMP_EXT_INQ) events[5] |= 0x40; /* Extended Inquiry Result */ - if (hdev->features[6] & LMP_NO_FLUSH) + if (lmp_no_flush_capable(hdev)) events[7] |= 0x01; /* Enhanced Flush Complete */ if (hdev->features[7] & LMP_LSTO) events[6] |= 0x80; /* Link Supervision Timeout Changed */ - if (hdev->features[6] & LMP_SIMPLE_PAIR) { + if (lmp_ssp_capable(hdev)) { events[6] |= 0x01; /* IO Capability Request */ events[6] |= 0x02; /* IO Capability Response */ events[6] |= 0x04; /* User Confirmation Request */ @@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) * Features Notification */ } - if (hdev->features[4] & LMP_LE) + if (lmp_le_capable(hdev)) events[7] |= 0x20; /* LE Meta-Event */ hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); @@ -623,11 +623,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev) struct hci_cp_write_def_link_policy cp; u16 link_policy = 0; - if (hdev->features[0] & LMP_RSWITCH) + if (lmp_rswitch_capable(hdev)) link_policy |= HCI_LP_RSWITCH; if (hdev->features[0] & LMP_HOLD) link_policy |= HCI_LP_HOLD; - if (hdev->features[0] & LMP_SNIFF) + if (lmp_sniff_capable(hdev)) link_policy |= HCI_LP_SNIFF; if (hdev->features[1] & LMP_PARK) link_policy |= HCI_LP_PARK; @@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, hdev->esco_type |= (ESCO_HV3); } - if (hdev->features[3] & LMP_ESCO) + if (lmp_esco_capable(hdev)) hdev->esco_type |= (ESCO_EV3); if (hdev->features[4] & LMP_EV4) @@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, break; } - if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) + if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) hci_set_le_support(hdev); done: @@ -1614,43 +1614,30 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) { - struct hci_cp_le_create_conn *cp; struct hci_conn *conn; BT_DBG("%s status 0x%2.2x", hdev->name, status); - cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); - if (!cp) - return; + if (status) { + hci_dev_lock(hdev); - hci_dev_lock(hdev); + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (!conn) { + hci_dev_unlock(hdev); + return; + } - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); + BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), + conn); - BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), - conn); + conn->state = BT_CLOSED; + mgmt_connect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, status); + hci_proto_connect_cfm(conn, status); + hci_conn_del(conn); - if (status) { - if (conn && conn->state == BT_CONNECT) { - conn->state = BT_CLOSED; - mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, - conn->dst_type, status); - hci_proto_connect_cfm(conn, status); - hci_conn_del(conn); - } - } else { - if (!conn) { - conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); - if (conn) { - conn->dst_type = cp->peer_addr_type; - conn->out = true; - } else { - BT_ERR("No memory for new connection"); - } - } + hci_dev_unlock(hdev); } - - hci_dev_unlock(hdev); } static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) @@ -3252,12 +3239,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, BT_DBG("%s", hdev->name); - hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); - - hci_dev_unlock(hdev); } static void hci_simple_pair_complete_evt(struct hci_dev *hdev, @@ -3350,11 +3333,23 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (ev->status) { - conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (!conn) + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (!conn) { + conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); + if (!conn) { + BT_ERR("No memory for new connection"); goto unlock; + } + conn->dst_type = ev->bdaddr_type; + + if (ev->role == LE_CONN_ROLE_MASTER) { + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + } + } + + if (ev->status) { mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); hci_proto_connect_cfm(conn, ev->status); @@ -3363,18 +3358,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) goto unlock; } - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); - if (!conn) { - conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); - if (!conn) { - BT_ERR("No memory for new connection"); - hci_dev_unlock(hdev); - return; - } - - conn->dst_type = ev->bdaddr_type; - } - if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) mgmt_device_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type, 0, NULL, 0, NULL); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d79..7c3d6c7c6ddb 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1100,21 +1100,30 @@ int __init hci_sock_init(void) return err; err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("HCI socket registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HCI proc file"); + bt_sock_unregister(BTPROTO_HCI); + goto error; + } BT_INFO("HCI socket layer initialized"); return 0; error: - BT_ERR("HCI socket registration failed"); proto_unregister(&hci_sk_proto); return err; } void hci_sock_cleanup(void) { + bt_procfs_cleanup(&init_net, "hci"); if (bt_sock_unregister(BTPROTO_HCI) < 0) BT_ERR("HCI socket unregistration failed"); diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a36..eca3889371c4 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -25,6 +25,10 @@ #include "hidp.h" +static struct bt_sock_list hidp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) +}; + static int hidp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&hidp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&hidp_sk_list, sk); + return 0; } @@ -271,8 +279,19 @@ int __init hidp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register HIDP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HIDP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("HIDP socket layer initialized"); return 0; @@ -284,6 +303,7 @@ error: void __exit hidp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "hidp"); if (bt_sock_unregister(BTPROTO_HIDP) < 0) BT_ERR("Can't unregister HIDP socket"); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bfb..9f8b29ef5b68 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -416,13 +416,30 @@ struct l2cap_chan *l2cap_chan_create(void) return chan; } -void l2cap_chan_destroy(struct l2cap_chan *chan) +static void l2cap_chan_destroy(struct l2cap_chan *chan) { + BT_DBG("chan %p", chan); + write_lock(&chan_list_lock); list_del(&chan->global_l); write_unlock(&chan_list_lock); - l2cap_chan_put(chan); + kfree(chan); +} + +void l2cap_chan_hold(struct l2cap_chan *c) +{ + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + + atomic_inc(&c->refcnt); +} + +void l2cap_chan_put(struct l2cap_chan *c) +{ + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + + if (atomic_dec_and_test(&c->refcnt)) + l2cap_chan_destroy(c); } void l2cap_chan_set_defaults(struct l2cap_chan *chan) @@ -5329,7 +5346,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) return exact ? lm1 : lm2; } -int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) +void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) { struct l2cap_conn *conn; @@ -5342,7 +5359,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) } else l2cap_conn_del(hcon, bt_to_errno(status)); - return 0; } int l2cap_disconn_ind(struct hci_conn *hcon) @@ -5356,12 +5372,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon) return conn->disc_reason; } -int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) +void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); l2cap_conn_del(hcon, bt_to_errno(reason)); - return 0; } static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) @@ -5404,6 +5419,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, state_to_string(chan->state)); + if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { + l2cap_chan_unlock(chan); + continue; + } + if (chan->scid == L2CAP_CID_LE_DATA) { if (!status && encrypt) { chan->sec_level = hcon->sec_level; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427e..13f6a9816feb 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -34,6 +34,10 @@ #include <net/bluetooth/l2cap.h> #include <net/bluetooth/smp.h> +static struct bt_sock_list l2cap_sk_list = { + .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) +}; + static const struct proto_ops l2cap_sock_ops; static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); @@ -823,7 +827,7 @@ static void l2cap_sock_kill(struct sock *sk) /* Kill poor orphan */ - l2cap_chan_destroy(l2cap_pi(sk)->chan); + l2cap_chan_put(l2cap_pi(sk)->chan); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); } @@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&l2cap_sk_list, sk); + err = l2cap_sock_shutdown(sock, 2); sock_orphan(sk); @@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, return -ENOMEM; l2cap_sock_init(sk, NULL); + bt_sock_link(&l2cap_sk_list, sk); return 0; } @@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void) return err; err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("L2CAP socket registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create L2CAP proc file"); + bt_sock_unregister(BTPROTO_L2CAP); + goto error; + } BT_INFO("L2CAP socket layer initialized"); return 0; error: - BT_ERR("L2CAP socket registration failed"); proto_unregister(&l2cap_proto); return err; } void l2cap_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "l2cap"); if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad6613d17ca6..a3329cbd3e4d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = { MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ }; +bool mgmt_valid_hdev(struct hci_dev *hdev) +{ + return hdev->dev_type == HCI_BREDR; +} + static u8 mgmt_status(u8 hci_status) { if (hci_status < ARRAY_SIZE(mgmt_status_table)) @@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, u16 data_len) { struct mgmt_rp_read_index_list *rp; - struct list_head *p; struct hci_dev *d; size_t rp_len; u16 count; @@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, read_lock(&hci_dev_list_lock); count = 0; - list_for_each(p, &hci_dev_list) { + list_for_each_entry(d, &hci_dev_list, list) { + if (!mgmt_valid_hdev(d)) + continue; + count++; } @@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (test_bit(HCI_SETUP, &d->dev_flags)) continue; + if (!mgmt_valid_hdev(d)) + continue; + rp->index[i++] = cpu_to_le16(d->id); BT_DBG("Added hci%u", d->id); } @@ -370,10 +380,10 @@ static u32 get_supported_settings(struct hci_dev *hdev) settings |= MGMT_SETTING_DISCOVERABLE; settings |= MGMT_SETTING_PAIRABLE; - if (hdev->features[6] & LMP_SIMPLE_PAIR) + if (lmp_ssp_capable(hdev)) settings |= MGMT_SETTING_SSP; - if (!(hdev->features[4] & LMP_NO_BREDR)) { + if (lmp_bredr_capable(hdev)) { settings |= MGMT_SETTING_BREDR; settings |= MGMT_SETTING_LINK_SECURITY; } @@ -381,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) if (enable_hs) settings |= MGMT_SETTING_HS; - if (hdev->features[4] & LMP_LE) + if (lmp_le_capable(hdev)) settings |= MGMT_SETTING_LE; return settings; @@ -403,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) settings |= MGMT_SETTING_PAIRABLE; - if (!(hdev->features[4] & LMP_NO_BREDR)) + if (lmp_bredr_capable(hdev)) settings |= MGMT_SETTING_BREDR; if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) @@ -1111,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + if (!lmp_ssp_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, MGMT_STATUS_NOT_SUPPORTED); goto failed; @@ -1195,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - if (!(hdev->features[4] & LMP_LE)) { + if (!lmp_le_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, MGMT_STATUS_NOT_SUPPORTED); goto unlock; @@ -2191,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, goto unlock; } - if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + if (!lmp_ssp_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, MGMT_STATUS_NOT_SUPPORTED); goto unlock; @@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data) int mgmt_index_added(struct hci_dev *hdev) { + if (!mgmt_valid_hdev(hdev)) + return -ENOTSUPP; + return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); } @@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev) { u8 status = MGMT_STATUS_INVALID_INDEX; + if (!mgmt_valid_hdev(hdev)) + return -ENOTSUPP; + mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c05..260821a2d6e7 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void) return err; err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("RFCOMM socket layer registration failed"); + goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create RFCOMM proc file"); + bt_sock_unregister(BTPROTO_RFCOMM); goto error; + } if (bt_debugfs) { rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, @@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void) return 0; error: - BT_ERR("RFCOMM socket layer registration failed"); proto_unregister(&rfcomm_proto); return err; } void __exit rfcomm_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "rfcomm"); + debugfs_remove(rfcomm_sock_debugfs); if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff7..caa109df6452 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) return lm; } -int sco_connect_cfm(struct hci_conn *hcon, __u8 status) +void sco_connect_cfm(struct hci_conn *hcon, __u8 status) { BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); if (!status) { @@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status) sco_conn_ready(conn); } else sco_conn_del(hcon, bt_to_errno(status)); - - return 0; } -int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) +void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); sco_conn_del(hcon, bt_to_errno(reason)); - return 0; } int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) @@ -1026,6 +1023,13 @@ int __init sco_init(void) goto error; } + err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create SCO proc file"); + bt_sock_unregister(BTPROTO_SCO); + goto error; + } + if (bt_debugfs) { sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, NULL, &sco_debugfs_fops); @@ -1044,6 +1048,8 @@ error: void __exit sco_exit(void) { + bt_procfs_cleanup(&init_net, "sco"); + debugfs_remove(sco_debugfs); if (bt_sock_unregister(BTPROTO_SCO) < 0) |