Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 25 Aug 2014 19:58:02 +0000 (15:58 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 25 Aug 2014 19:58:02 +0000 (15:58 -0400)
22 files changed:
MAINTAINERS
drivers/bluetooth/ath3k.c
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/btusb.c
drivers/bluetooth/dtl1_cs.c
drivers/bluetooth/hci_h5.c
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
net/bluetooth/6lowpan.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/bluetooth/smp.h
net/ieee802154/6lowpan_rtnl.c
net/mac802154/rx.c
net/mac802154/tx.c
net/mac802154/wpan.c

index f01f54f277504ac373fdfd5d9a788509c1ae0ae1..b0a9003a133411738cdb54f16a4512c2da6fec37 100644 (file)
@@ -152,8 +152,8 @@ F:  drivers/scsi/53c700*
 
 6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
 M:     Alexander Aring <alex.aring@gmail.com>
-L:     linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
 L:     linux-bluetooth@vger.kernel.org
+L:     linux-wpan@vger.kernel.org
 S:     Maintained
 F:     net/6lowpan/
 F:     include/net/6lowpan.h
@@ -4580,13 +4580,14 @@ F:      drivers/idle/i7300_idle.c
 
 IEEE 802.15.4 SUBSYSTEM
 M:     Alexander Aring <alex.aring@gmail.com>
-L:     linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
-W:     http://apps.sourceforge.net/trac/linux-zigbee
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
+L:     linux-wpan@vger.kernel.org
+W:     https://github.com/linux-wpan
+T:     git git://github.com/linux-wpan/linux-wpan-next.git
 S:     Maintained
 F:     net/ieee802154/
 F:     net/mac802154/
 F:     drivers/net/ieee802154/
+F:     Documentation/networking/ieee802154.txt
 
 IGUANAWORKS USB IR TRANSCEIVER
 M:     Sean Young <sean@mess.org>
index a0d7355ef1275e865ad09d6e3503c953111cf4fd..d85ced27ebd58f5a40b1881032daced2aedf82b0 100644 (file)
@@ -88,6 +88,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x04CA, 0x300b) },
        { USB_DEVICE(0x0930, 0x0219) },
        { USB_DEVICE(0x0930, 0x0220) },
+       { USB_DEVICE(0x0930, 0x0227) },
        { USB_DEVICE(0x0b05, 0x17d0) },
        { USB_DEVICE(0x0CF3, 0x0036) },
        { USB_DEVICE(0x0CF3, 0x3004) },
@@ -138,6 +139,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
index dfa5043e68bacc9de66f6ce12c565fb8f410f4b1..35e63aaa6f803e423a39e532adeff717b7279cb3 100644 (file)
@@ -61,7 +61,7 @@ MODULE_LICENSE("GPL");
 /* ======================== Local structures ======================== */
 
 
-typedef struct bluecard_info_t {
+struct bluecard_info {
        struct pcmcia_device *p_dev;
 
        struct hci_dev *hdev;
@@ -78,7 +78,7 @@ typedef struct bluecard_info_t {
 
        unsigned char ctrl_reg;
        unsigned long hw_state;         /* Status of the hardware and LED control */
-} bluecard_info_t;
+};
 
 
 static int bluecard_config(struct pcmcia_device *link);
@@ -157,7 +157,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
 
 static void bluecard_activity_led_timeout(u_long arg)
 {
-       bluecard_info_t *info = (bluecard_info_t *)arg;
+       struct bluecard_info *info = (struct bluecard_info *)arg;
        unsigned int iobase = info->p_dev->resource[0]->start;
 
        if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
@@ -173,7 +173,7 @@ static void bluecard_activity_led_timeout(u_long arg)
 }
 
 
-static void bluecard_enable_activity_led(bluecard_info_t *info)
+static void bluecard_enable_activity_led(struct bluecard_info *info)
 {
        unsigned int iobase = info->p_dev->resource[0]->start;
 
@@ -215,7 +215,7 @@ static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, i
 }
 
 
-static void bluecard_write_wakeup(bluecard_info_t *info)
+static void bluecard_write_wakeup(struct bluecard_info *info)
 {
        if (!info) {
                BT_ERR("Unknown device");
@@ -368,7 +368,8 @@ static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, in
 }
 
 
-static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
+static void bluecard_receive(struct bluecard_info *info,
+                            unsigned int offset)
 {
        unsigned int iobase;
        unsigned char buf[31];
@@ -497,7 +498,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
 
 static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
 {
-       bluecard_info_t *info = dev_inst;
+       struct bluecard_info *info = dev_inst;
        unsigned int iobase;
        unsigned char reg;
 
@@ -562,7 +563,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
 
 static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
 {
-       bluecard_info_t *info = hci_get_drvdata(hdev);
+       struct bluecard_info *info = hci_get_drvdata(hdev);
        struct sk_buff *skb;
 
        /* Ericsson baud rate command */
@@ -611,7 +612,7 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
 
 static int bluecard_hci_flush(struct hci_dev *hdev)
 {
-       bluecard_info_t *info = hci_get_drvdata(hdev);
+       struct bluecard_info *info = hci_get_drvdata(hdev);
 
        /* Drop TX queue */
        skb_queue_purge(&(info->txq));
@@ -622,7 +623,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
 
 static int bluecard_hci_open(struct hci_dev *hdev)
 {
-       bluecard_info_t *info = hci_get_drvdata(hdev);
+       struct bluecard_info *info = hci_get_drvdata(hdev);
 
        if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
                bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -643,7 +644,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
 
 static int bluecard_hci_close(struct hci_dev *hdev)
 {
-       bluecard_info_t *info = hci_get_drvdata(hdev);
+       struct bluecard_info *info = hci_get_drvdata(hdev);
 
        if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
                return 0;
@@ -663,7 +664,7 @@ static int bluecard_hci_close(struct hci_dev *hdev)
 
 static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
-       bluecard_info_t *info = hci_get_drvdata(hdev);
+       struct bluecard_info *info = hci_get_drvdata(hdev);
 
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
@@ -691,7 +692,7 @@ static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 /* ======================== Card services HCI interaction ======================== */
 
 
-static int bluecard_open(bluecard_info_t *info)
+static int bluecard_open(struct bluecard_info *info)
 {
        unsigned int iobase = info->p_dev->resource[0]->start;
        struct hci_dev *hdev;
@@ -806,7 +807,7 @@ static int bluecard_open(bluecard_info_t *info)
 }
 
 
-static int bluecard_close(bluecard_info_t *info)
+static int bluecard_close(struct bluecard_info *info)
 {
        unsigned int iobase = info->p_dev->resource[0]->start;
        struct hci_dev *hdev = info->hdev;
@@ -833,7 +834,7 @@ static int bluecard_close(bluecard_info_t *info)
 
 static int bluecard_probe(struct pcmcia_device *link)
 {
-       bluecard_info_t *info;
+       struct bluecard_info *info;
 
        /* Create new info device */
        info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
@@ -857,7 +858,7 @@ static void bluecard_detach(struct pcmcia_device *link)
 
 static int bluecard_config(struct pcmcia_device *link)
 {
-       bluecard_info_t *info = link->priv;
+       struct bluecard_info *info = link->priv;
        int i, n;
 
        link->config_index = 0x20;
@@ -897,7 +898,7 @@ failed:
 
 static void bluecard_release(struct pcmcia_device *link)
 {
-       bluecard_info_t *info = link->priv;
+       struct bluecard_info *info = link->priv;
 
        bluecard_close(info);
 
index 1d82721cf9c67e05653f00f6ae93e20d482c9ff4..4f7e8d400bc01a178bcbfcf499340b40545fb54f 100644 (file)
@@ -67,7 +67,7 @@ MODULE_FIRMWARE("BT3CPCC.bin");
 /* ======================== Local structures ======================== */
 
 
-typedef struct bt3c_info_t {
+struct bt3c_info {
        struct pcmcia_device *p_dev;
 
        struct hci_dev *hdev;
@@ -80,7 +80,7 @@ typedef struct bt3c_info_t {
        unsigned long rx_state;
        unsigned long rx_count;
        struct sk_buff *rx_skb;
-} bt3c_info_t;
+};
 
 
 static int bt3c_config(struct pcmcia_device *link);
@@ -175,7 +175,7 @@ static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
 }
 
 
-static void bt3c_write_wakeup(bt3c_info_t *info)
+static void bt3c_write_wakeup(struct bt3c_info *info)
 {
        if (!info) {
                BT_ERR("Unknown device");
@@ -214,7 +214,7 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
 }
 
 
-static void bt3c_receive(bt3c_info_t *info)
+static void bt3c_receive(struct bt3c_info *info)
 {
        unsigned int iobase;
        int size = 0, avail;
@@ -336,7 +336,7 @@ static void bt3c_receive(bt3c_info_t *info)
 
 static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
 {
-       bt3c_info_t *info = dev_inst;
+       struct bt3c_info *info = dev_inst;
        unsigned int iobase;
        int iir;
        irqreturn_t r = IRQ_NONE;
@@ -388,7 +388,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
 
 static int bt3c_hci_flush(struct hci_dev *hdev)
 {
-       bt3c_info_t *info = hci_get_drvdata(hdev);
+       struct bt3c_info *info = hci_get_drvdata(hdev);
 
        /* Drop TX queue */
        skb_queue_purge(&(info->txq));
@@ -418,7 +418,7 @@ static int bt3c_hci_close(struct hci_dev *hdev)
 
 static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
-       bt3c_info_t *info = hci_get_drvdata(hdev);
+       struct bt3c_info *info = hci_get_drvdata(hdev);
        unsigned long flags;
 
        switch (bt_cb(skb)->pkt_type) {
@@ -451,7 +451,8 @@ static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 /* ======================== Card services HCI interaction ======================== */
 
 
-static int bt3c_load_firmware(bt3c_info_t *info, const unsigned char *firmware,
+static int bt3c_load_firmware(struct bt3c_info *info,
+                             const unsigned char *firmware,
                              int count)
 {
        char *ptr = (char *) firmware;
@@ -536,7 +537,7 @@ error:
 }
 
 
-static int bt3c_open(bt3c_info_t *info)
+static int bt3c_open(struct bt3c_info *info)
 {
        const struct firmware *firmware;
        struct hci_dev *hdev;
@@ -603,7 +604,7 @@ error:
 }
 
 
-static int bt3c_close(bt3c_info_t *info)
+static int bt3c_close(struct bt3c_info *info)
 {
        struct hci_dev *hdev = info->hdev;
 
@@ -620,7 +621,7 @@ static int bt3c_close(bt3c_info_t *info)
 
 static int bt3c_probe(struct pcmcia_device *link)
 {
-       bt3c_info_t *info;
+       struct bt3c_info *info;
 
        /* Create new info device */
        info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
@@ -683,7 +684,7 @@ static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
 
 static int bt3c_config(struct pcmcia_device *link)
 {
-       bt3c_info_t *info = link->priv;
+       struct bt3c_info *info = link->priv;
        int i;
        unsigned long try;
 
@@ -724,7 +725,7 @@ failed:
 
 static void bt3c_release(struct pcmcia_device *link)
 {
-       bt3c_info_t *info = link->priv;
+       struct bt3c_info *info = link->priv;
 
        bt3c_close(info);
 
index fb948f02eda5b1747a7ca7604133daf88a719ef1..abb4d2106db464198c328af1069342bd36d64d80 100644 (file)
@@ -62,7 +62,7 @@ MODULE_LICENSE("GPL");
 /* ======================== Local structures ======================== */
 
 
-typedef struct btuart_info_t {
+struct btuart_info {
        struct pcmcia_device *p_dev;
 
        struct hci_dev *hdev;
@@ -75,7 +75,7 @@ typedef struct btuart_info_t {
        unsigned long rx_state;
        unsigned long rx_count;
        struct sk_buff *rx_skb;
-} btuart_info_t;
+};
 
 
 static int btuart_config(struct pcmcia_device *link);
@@ -127,7 +127,7 @@ static int btuart_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
 }
 
 
-static void btuart_write_wakeup(btuart_info_t *info)
+static void btuart_write_wakeup(struct btuart_info *info)
 {
        if (!info) {
                BT_ERR("Unknown device");
@@ -172,7 +172,7 @@ static void btuart_write_wakeup(btuart_info_t *info)
 }
 
 
-static void btuart_receive(btuart_info_t *info)
+static void btuart_receive(struct btuart_info *info)
 {
        unsigned int iobase;
        int boguscount = 0;
@@ -286,7 +286,7 @@ static void btuart_receive(btuart_info_t *info)
 
 static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
 {
-       btuart_info_t *info = dev_inst;
+       struct btuart_info *info = dev_inst;
        unsigned int iobase;
        int boguscount = 0;
        int iir, lsr;
@@ -340,7 +340,8 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
 }
 
 
-static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
+static void btuart_change_speed(struct btuart_info *info,
+                               unsigned int speed)
 {
        unsigned long flags;
        unsigned int iobase;
@@ -397,7 +398,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
 
 static int btuart_hci_flush(struct hci_dev *hdev)
 {
-       btuart_info_t *info = hci_get_drvdata(hdev);
+       struct btuart_info *info = hci_get_drvdata(hdev);
 
        /* Drop TX queue */
        skb_queue_purge(&(info->txq));
@@ -427,7 +428,7 @@ static int btuart_hci_close(struct hci_dev *hdev)
 
 static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
-       btuart_info_t *info = hci_get_drvdata(hdev);
+       struct btuart_info *info = hci_get_drvdata(hdev);
 
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
@@ -455,7 +456,7 @@ static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 /* ======================== Card services HCI interaction ======================== */
 
 
-static int btuart_open(btuart_info_t *info)
+static int btuart_open(struct btuart_info *info)
 {
        unsigned long flags;
        unsigned int iobase = info->p_dev->resource[0]->start;
@@ -521,7 +522,7 @@ static int btuart_open(btuart_info_t *info)
 }
 
 
-static int btuart_close(btuart_info_t *info)
+static int btuart_close(struct btuart_info *info)
 {
        unsigned long flags;
        unsigned int iobase = info->p_dev->resource[0]->start;
@@ -550,7 +551,7 @@ static int btuart_close(btuart_info_t *info)
 
 static int btuart_probe(struct pcmcia_device *link)
 {
-       btuart_info_t *info;
+       struct btuart_info *info;
 
        /* Create new info device */
        info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
@@ -613,7 +614,7 @@ static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
 
 static int btuart_config(struct pcmcia_device *link)
 {
-       btuart_info_t *info = link->priv;
+       struct btuart_info *info = link->priv;
        int i;
        int try;
 
@@ -654,7 +655,7 @@ failed:
 
 static void btuart_release(struct pcmcia_device *link)
 {
-       btuart_info_t *info = link->priv;
+       struct btuart_info *info = link->priv;
 
        btuart_close(info);
 
index 292c38e8aa1760c000cdcce9ee6d223e9f819559..0527b29c3954be02db3693b4d338d0cbe59d7960 100644 (file)
@@ -165,6 +165,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
index 2bd8fad172064af8f2211536fe8903e363ef33f1..78e10f0c65b28dc38d30336514b92614bc7e449c 100644 (file)
@@ -62,7 +62,7 @@ MODULE_LICENSE("GPL");
 /* ======================== Local structures ======================== */
 
 
-typedef struct dtl1_info_t {
+struct dtl1_info {
        struct pcmcia_device *p_dev;
 
        struct hci_dev *hdev;
@@ -78,7 +78,7 @@ typedef struct dtl1_info_t {
        unsigned long rx_state;
        unsigned long rx_count;
        struct sk_buff *rx_skb;
-} dtl1_info_t;
+};
 
 
 static int dtl1_config(struct pcmcia_device *link);
@@ -94,11 +94,11 @@ static int dtl1_config(struct pcmcia_device *link);
 #define RECV_WAIT_DATA  1
 
 
-typedef struct {
+struct nsh {
        u8 type;
        u8 zero;
        u16 len;
-} __packed nsh_t;      /* Nokia Specific Header */
+} __packed;    /* Nokia Specific Header */
 
 #define NSHL  4                                /* Nokia Specific Header Length */
 
@@ -126,7 +126,7 @@ static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
 }
 
 
-static void dtl1_write_wakeup(dtl1_info_t *info)
+static void dtl1_write_wakeup(struct dtl1_info *info)
 {
        if (!info) {
                BT_ERR("Unknown device");
@@ -176,7 +176,7 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
 }
 
 
-static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb)
+static void dtl1_control(struct dtl1_info *info, struct sk_buff *skb)
 {
        u8 flowmask = *(u8 *)skb->data;
        int i;
@@ -199,10 +199,10 @@ static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb)
 }
 
 
-static void dtl1_receive(dtl1_info_t *info)
+static void dtl1_receive(struct dtl1_info *info)
 {
        unsigned int iobase;
-       nsh_t *nsh;
+       struct nsh *nsh;
        int boguscount = 0;
 
        if (!info) {
@@ -227,7 +227,7 @@ static void dtl1_receive(dtl1_info_t *info)
                }
 
                *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
-               nsh = (nsh_t *)info->rx_skb->data;
+               nsh = (struct nsh *)info->rx_skb->data;
 
                info->rx_count--;
 
@@ -287,7 +287,7 @@ static void dtl1_receive(dtl1_info_t *info)
 
 static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
 {
-       dtl1_info_t *info = dev_inst;
+       struct dtl1_info *info = dev_inst;
        unsigned int iobase;
        unsigned char msr;
        int boguscount = 0;
@@ -365,7 +365,7 @@ static int dtl1_hci_open(struct hci_dev *hdev)
 
 static int dtl1_hci_flush(struct hci_dev *hdev)
 {
-       dtl1_info_t *info = hci_get_drvdata(hdev);
+       struct dtl1_info *info = hci_get_drvdata(hdev);
 
        /* Drop TX queue */
        skb_queue_purge(&(info->txq));
@@ -387,9 +387,9 @@ static int dtl1_hci_close(struct hci_dev *hdev)
 
 static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
-       dtl1_info_t *info = hci_get_drvdata(hdev);
+       struct dtl1_info *info = hci_get_drvdata(hdev);
        struct sk_buff *s;
-       nsh_t nsh;
+       struct nsh nsh;
 
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
@@ -436,7 +436,7 @@ static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 /* ======================== Card services HCI interaction ======================== */
 
 
-static int dtl1_open(dtl1_info_t *info)
+static int dtl1_open(struct dtl1_info *info)
 {
        unsigned long flags;
        unsigned int iobase = info->p_dev->resource[0]->start;
@@ -505,7 +505,7 @@ static int dtl1_open(dtl1_info_t *info)
 }
 
 
-static int dtl1_close(dtl1_info_t *info)
+static int dtl1_close(struct dtl1_info *info)
 {
        unsigned long flags;
        unsigned int iobase = info->p_dev->resource[0]->start;
@@ -534,7 +534,7 @@ static int dtl1_close(dtl1_info_t *info)
 
 static int dtl1_probe(struct pcmcia_device *link)
 {
-       dtl1_info_t *info;
+       struct dtl1_info *info;
 
        /* Create new info device */
        info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
@@ -552,7 +552,7 @@ static int dtl1_probe(struct pcmcia_device *link)
 
 static void dtl1_detach(struct pcmcia_device *link)
 {
-       dtl1_info_t *info = link->priv;
+       struct dtl1_info *info = link->priv;
 
        dtl1_close(info);
        pcmcia_disable_device(link);
@@ -571,7 +571,7 @@ static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 
 static int dtl1_config(struct pcmcia_device *link)
 {
-       dtl1_info_t *info = link->priv;
+       struct dtl1_info *info = link->priv;
        int ret;
 
        /* Look for a generic full-sized window */
index caacb422995dd4a69e18585275f32904a17bf708..a22838669b4ed227d447925ea45337f5efd9f72d 100644 (file)
@@ -237,7 +237,7 @@ static void h5_pkt_cull(struct h5 *h5)
                        break;
 
                to_remove--;
-               seq = (seq - 1) % 8;
+               seq = (seq - 1) & 0x07;
        }
 
        if (seq != h5->rx_ack)
index b5d5af3aa469961af36b30b0aea2da1d4e959bac..5f0b77b71b45b79f6f2abed9219769eeefb4e4f3 100644 (file)
@@ -302,7 +302,7 @@ struct hci_dev {
        __u32                   req_status;
        __u32                   req_result;
 
-       struct crypto_blkcipher *tfm_aes;
+       void                    *smp_data;
 
        struct discovery_state  discovery;
        struct hci_conn_hash    conn_hash;
@@ -968,6 +968,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_host_le_capable(dev)   (!!((dev)->features[1][0] & LMP_HOST_LE))
 #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
 
+#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
+                               !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+
 /* ----- HCI protocols ----- */
 #define HCI_PROTO_DEFER             0x01
 
@@ -1256,6 +1259,8 @@ bool hci_req_pending(struct hci_dev *hdev);
 void hci_req_add_le_scan_disable(struct hci_request *req);
 void hci_req_add_le_passive_scan(struct hci_request *req);
 
+void hci_update_page_scan(struct hci_dev *hdev, struct hci_request *req);
+
 struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
                               const void *param, u32 timeout);
 struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
@@ -1351,6 +1356,7 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
                      u8 addr_type, s8 rssi, u8 *name, u8 name_len);
 void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
+bool mgmt_powering_down(struct hci_dev *hdev);
 void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent);
 void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
 void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
index 8df15ad0d43fadc17f82aed2cb2b9115ff6a425f..cedda399f9c0e7fb98ca62a1612e65f35e9a68b4 100644 (file)
@@ -625,6 +625,9 @@ struct l2cap_conn {
 
        struct delayed_work     info_timer;
 
+       int                     disconn_err;
+       struct work_struct      disconn_work;
+
        struct sk_buff          *rx_skb;
        __u32                   rx_len;
        __u8                    tx_ident;
@@ -635,8 +638,7 @@ struct l2cap_conn {
 
        __u8                    disc_reason;
 
-       struct delayed_work     security_timer;
-       struct smp_chan         *smp_chan;
+       struct l2cap_chan       *smp;
 
        struct list_head        chan_l;
        struct mutex            chan_lock;
@@ -708,6 +710,7 @@ enum {
        FLAG_EFS_ENABLE,
        FLAG_DEFER_SETUP,
        FLAG_LE_CONN_REQ_SENT,
+       FLAG_PENDING_SECURITY,
 };
 
 enum {
@@ -837,18 +840,43 @@ static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan
        return NULL;
 }
 
+static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
+{
+       return -ENOSYS;
+}
+
+static inline struct sk_buff *l2cap_chan_no_alloc_skb(struct l2cap_chan *chan,
+                                                     unsigned long hdr_len,
+                                                     unsigned long len, int nb)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
 static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err)
 {
 }
 
+static inline void l2cap_chan_no_close(struct l2cap_chan *chan)
+{
+}
+
 static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_state_change(struct l2cap_chan *chan,
+                                             int state, int err)
+{
+}
+
 static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_suspend(struct l2cap_chan *chan)
+{
+}
+
 static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
 {
 }
@@ -918,6 +946,7 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
                       u8 status);
 void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
 
+void l2cap_conn_shutdown(struct l2cap_conn *conn, int err);
 void l2cap_conn_get(struct l2cap_conn *conn);
 void l2cap_conn_put(struct l2cap_conn *conn);
 
index 206b65ccd5b8bd318e554e452966fae1c582112f..35ebe79c87b0ca5df9a76ad0ea7761c433cf1fe0 100644 (file)
@@ -772,16 +772,16 @@ static inline void chan_ready_cb(struct l2cap_chan *chan)
        ifup(dev->netdev);
 }
 
-static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *chan)
+static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)
 {
-       struct l2cap_chan *pchan;
+       struct l2cap_chan *chan;
 
-       pchan = chan_open(chan);
-       pchan->ops = chan->ops;
+       chan = chan_open(pchan);
+       chan->ops = pchan->ops;
 
        BT_DBG("chan %p pchan %p", chan, pchan);
 
-       return pchan;
+       return chan;
 }
 
 static void delete_netdev(struct work_struct *work)
index c32d361c0cf766478f80fb9ed8a4884f53451122..abeb5e47311e47bd85439d1842349e135bbb3abb 100644 (file)
@@ -1898,6 +1898,8 @@ static int __hci_init(struct hci_dev *hdev)
                debugfs_create_u16("discov_interleaved_timeout", 0644,
                                   hdev->debugfs,
                                   &hdev->discov_interleaved_timeout);
+
+               smp_register(hdev);
        }
 
        return 0;
@@ -3233,7 +3235,7 @@ struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
        }
 
        list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
-               if (smp_irk_matches(hdev->tfm_aes, irk->val, rpa)) {
+               if (smp_irk_matches(hdev, irk->val, rpa)) {
                        bacpy(&irk->rpa, rpa);
                        return irk;
                }
@@ -3882,7 +3884,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
                    !bacmp(&hdev->random_addr, &hdev->rpa))
                        return 0;
 
-               err = smp_generate_rpa(hdev->tfm_aes, hdev->irk, &hdev->rpa);
+               err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
                if (err < 0) {
                        BT_ERR("%s failed to generate new RPA", hdev->name);
                        return err;
@@ -4090,18 +4092,9 @@ int hci_register_dev(struct hci_dev *hdev)
 
        dev_set_name(&hdev->dev, "%s", hdev->name);
 
-       hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0,
-                                              CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hdev->tfm_aes)) {
-               BT_ERR("Unable to create crypto context");
-               error = PTR_ERR(hdev->tfm_aes);
-               hdev->tfm_aes = NULL;
-               goto err_wqueue;
-       }
-
        error = device_add(&hdev->dev);
        if (error < 0)
-               goto err_tfm;
+               goto err_wqueue;
 
        hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
                                    RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops,
@@ -4143,8 +4136,6 @@ int hci_register_dev(struct hci_dev *hdev)
 
        return id;
 
-err_tfm:
-       crypto_free_blkcipher(hdev->tfm_aes);
 err_wqueue:
        destroy_workqueue(hdev->workqueue);
        destroy_workqueue(hdev->req_workqueue);
@@ -4196,8 +4187,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
                rfkill_destroy(hdev->rfkill);
        }
 
-       if (hdev->tfm_aes)
-               crypto_free_blkcipher(hdev->tfm_aes);
+       smp_unregister(hdev);
 
        device_del(&hdev->dev);
 
@@ -5680,3 +5670,52 @@ void hci_update_background_scan(struct hci_dev *hdev)
        if (err)
                BT_ERR("Failed to run HCI request: err %d", err);
 }
+
+static bool disconnected_whitelist_entries(struct hci_dev *hdev)
+{
+       struct bdaddr_list *b;
+
+       list_for_each_entry(b, &hdev->whitelist, list) {
+               struct hci_conn *conn;
+
+               conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &b->bdaddr);
+               if (!conn)
+                       return true;
+
+               if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
+                       return true;
+       }
+
+       return false;
+}
+
+void hci_update_page_scan(struct hci_dev *hdev, struct hci_request *req)
+{
+       u8 scan;
+
+       if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
+               return;
+
+       if (!hdev_is_powered(hdev))
+               return;
+
+       if (mgmt_powering_down(hdev))
+               return;
+
+       if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
+           disconnected_whitelist_entries(hdev))
+               scan = SCAN_PAGE;
+       else
+               scan = SCAN_DISABLED;
+
+       if (test_bit(HCI_PSCAN, &hdev->flags) == !!(scan & SCAN_PAGE))
+               return;
+
+       if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
+               scan |= SCAN_INQUIRY;
+
+       if (req)
+               hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+       else
+               hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+}
index be35598984d9b9b3120cd178f67f0418858b2774..da7ab6b9bb691383d977e039b39e94f8714507d4 100644 (file)
@@ -2071,6 +2071,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        cp.handle = ev->handle;
                        hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
                                     sizeof(cp), &cp);
+
+                       hci_update_page_scan(hdev, NULL);
                }
 
                /* Set packet type for incoming connection */
@@ -2247,9 +2249,12 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
                                reason, mgmt_connected);
 
-       if (conn->type == ACL_LINK &&
-           test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
-               hci_remove_link_key(hdev, &conn->dst);
+       if (conn->type == ACL_LINK) {
+               if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
+                       hci_remove_link_key(hdev, &conn->dst);
+
+               hci_update_page_scan(hdev, NULL);
+       }
 
        params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
        if (params) {
index 46547b920f88edf7e6df5b6c5d10ae30daa47d67..4a90438d99dff0c8c660e1ce66c8f7ad9a67dc58 100644 (file)
@@ -210,6 +210,10 @@ int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
 {
        write_lock(&chan_list_lock);
 
+       /* Override the defaults (which are for conn-oriented) */
+       chan->omtu = L2CAP_DEFAULT_MTU;
+       chan->chan_type = L2CAP_CHAN_FIXED;
+
        chan->scid = scid;
 
        write_unlock(&chan_list_lock);
@@ -562,6 +566,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 
        BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
 
+       chan->ops->teardown(chan, err);
+
        if (conn) {
                struct amp_mgr *mgr = conn->hcon->amp_mgr;
                /* Delete from channel list */
@@ -585,8 +591,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
                amp_disconnect_logical_link(hs_hchan);
        }
 
-       chan->ops->teardown(chan, err);
-
        if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
                return;
 
@@ -1082,6 +1086,9 @@ static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
 
 static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
 {
+       if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
+               return true;
+
        return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
 }
 
@@ -1417,71 +1424,18 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
        mutex_unlock(&conn->chan_lock);
 }
 
-/* Find socket with cid and source/destination bdaddr.
- * Returns closest match, locked.
- */
-static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
-                                                   bdaddr_t *src,
-                                                   bdaddr_t *dst)
-{
-       struct l2cap_chan *c, *c1 = NULL;
-
-       read_lock(&chan_list_lock);
-
-       list_for_each_entry(c, &chan_list, global_l) {
-               if (state && c->state != state)
-                       continue;
-
-               if (c->scid == cid) {
-                       int src_match, dst_match;
-                       int src_any, dst_any;
-
-                       /* Exact match. */
-                       src_match = !bacmp(&c->src, src);
-                       dst_match = !bacmp(&c->dst, dst);
-                       if (src_match && dst_match) {
-                               read_unlock(&chan_list_lock);
-                               return c;
-                       }
-
-                       /* Closest match */
-                       src_any = !bacmp(&c->src, BDADDR_ANY);
-                       dst_any = !bacmp(&c->dst, BDADDR_ANY);
-                       if ((src_match && dst_any) || (src_any && dst_match) ||
-                           (src_any && dst_any))
-                               c1 = c;
-               }
-       }
-
-       read_unlock(&chan_list_lock);
-
-       return c1;
-}
-
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
        struct hci_conn *hcon = conn->hcon;
        struct hci_dev *hdev = hcon->hdev;
-       struct l2cap_chan *chan, *pchan;
-       u8 dst_type;
 
-       BT_DBG("");
+       BT_DBG("%s conn %p", hdev->name, conn);
 
-       /* Check if we have socket listening on cid */
-       pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
-                                         &hcon->src, &hcon->dst);
-       if (!pchan)
-               return;
-
-       /* Client ATT sockets should override the server one */
-       if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
-               return;
-
-       dst_type = bdaddr_type(hcon, hcon->dst_type);
-
-       /* If device is blocked, do not create a channel for it */
-       if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
-               return;
+       /* For outgoing pairing which doesn't necessarily have an
+        * associated socket (e.g. mgmt_pair_device).
+        */
+       if (hcon->out)
+               smp_conn_security(hcon, hcon->pending_sec_level);
 
        /* For LE slave connections, make sure the connection interval
         * is in the range of the minium and maximum interval that has
@@ -1501,22 +1455,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
                l2cap_send_cmd(conn, l2cap_get_ident(conn),
                               L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
        }
-
-       l2cap_chan_lock(pchan);
-
-       chan = pchan->ops->new_connection(pchan);
-       if (!chan)
-               goto clean;
-
-       bacpy(&chan->src, &hcon->src);
-       bacpy(&chan->dst, &hcon->dst);
-       chan->src_type = bdaddr_type(hcon, hcon->src_type);
-       chan->dst_type = dst_type;
-
-       __l2cap_chan_add(conn, chan);
-
-clean:
-       l2cap_chan_unlock(pchan);
 }
 
 static void l2cap_conn_ready(struct l2cap_conn *conn)
@@ -1526,17 +1464,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 
        BT_DBG("conn %p", conn);
 
-       /* For outgoing pairing which doesn't necessarily have an
-        * associated socket (e.g. mgmt_pair_device).
-        */
-       if (hcon->out && hcon->type == LE_LINK)
-               smp_conn_security(hcon, hcon->pending_sec_level);
-
        mutex_lock(&conn->chan_lock);
 
-       if (hcon->type == LE_LINK)
-               l2cap_le_conn_ready(conn);
-
        list_for_each_entry(chan, &conn->chan_l, list) {
 
                l2cap_chan_lock(chan);
@@ -1560,6 +1489,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 
        mutex_unlock(&conn->chan_lock);
 
+       if (hcon->type == LE_LINK)
+               l2cap_le_conn_ready(conn);
+
        queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
 }
 
@@ -1695,6 +1627,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
        if (work_pending(&conn->pending_rx_work))
                cancel_work_sync(&conn->pending_rx_work);
 
+       if (work_pending(&conn->disconn_work))
+               cancel_work_sync(&conn->disconn_work);
+
        l2cap_unregister_all_users(conn);
 
        mutex_lock(&conn->chan_lock);
@@ -1719,27 +1654,29 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
                cancel_delayed_work_sync(&conn->info_timer);
 
-       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
-               cancel_delayed_work_sync(&conn->security_timer);
-               smp_chan_destroy(conn);
-       }
-
        hcon->l2cap_data = NULL;
        conn->hchan = NULL;
        l2cap_conn_put(conn);
 }
 
-static void security_timeout(struct work_struct *work)
+static void disconn_work(struct work_struct *work)
 {
        struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
-                                              security_timer.work);
+                                              disconn_work);
 
        BT_DBG("conn %p", conn);
 
-       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
-               smp_chan_destroy(conn);
-               l2cap_conn_del(conn->hcon, ETIMEDOUT);
-       }
+       l2cap_conn_del(conn->hcon, conn->disconn_err);
+}
+
+void l2cap_conn_shutdown(struct l2cap_conn *conn, int err)
+{
+       struct hci_dev *hdev = conn->hcon->hdev;
+
+       BT_DBG("conn %p err %d", conn, err);
+
+       conn->disconn_err = err;
+       queue_work(hdev->workqueue, &conn->disconn_work);
 }
 
 static void l2cap_conn_free(struct kref *ref)
@@ -1794,6 +1731,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                        src_match = !bacmp(&c->src, src);
                        dst_match = !bacmp(&c->dst, dst);
                        if (src_match && dst_match) {
+                               l2cap_chan_hold(c);
                                read_unlock(&chan_list_lock);
                                return c;
                        }
@@ -1807,6 +1745,9 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                }
        }
 
+       if (c1)
+               l2cap_chan_hold(c1);
+
        read_unlock(&chan_list_lock);
 
        return c1;
@@ -2027,10 +1968,12 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
                                           tx_skb->data + L2CAP_HDR_SIZE);
                }
 
+               /* Update FCS */
                if (chan->fcs == L2CAP_FCS_CRC16) {
-                       u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
-                       put_unaligned_le16(fcs, skb_put(tx_skb,
-                                                       L2CAP_FCS_SIZE));
+                       u16 fcs = crc16(0, (u8 *) tx_skb->data,
+                                       tx_skb->len - L2CAP_FCS_SIZE);
+                       put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
+                                               L2CAP_FCS_SIZE);
                }
 
                l2cap_do_send(chan, tx_skb);
@@ -2334,7 +2277,6 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
        } else {
                sar = L2CAP_SAR_START;
                sdu_len = len;
-               pdu_len -= L2CAP_SDULEN_SIZE;
        }
 
        while (len > 0) {
@@ -2349,10 +2291,8 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
                __skb_queue_tail(seg_queue, skb);
 
                len -= pdu_len;
-               if (sdu_len) {
+               if (sdu_len)
                        sdu_len = 0;
-                       pdu_len += L2CAP_SDULEN_SIZE;
-               }
 
                if (len <= pdu_len) {
                        sar = L2CAP_SAR_END;
@@ -3884,6 +3824,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 response:
        l2cap_chan_unlock(pchan);
        mutex_unlock(&conn->chan_lock);
+       l2cap_chan_put(pchan);
 
 sendresp:
        rsp.scid   = cpu_to_le16(scid);
@@ -5497,6 +5438,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 response_unlock:
        l2cap_chan_unlock(pchan);
        mutex_unlock(&conn->chan_lock);
+       l2cap_chan_put(pchan);
 
        if (result == L2CAP_CR_PEND)
                return 0;
@@ -6845,12 +6787,12 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
        struct l2cap_chan *chan;
 
        if (hcon->type != ACL_LINK)
-               goto drop;
+               goto free_skb;
 
        chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
                                        ACL_LINK);
        if (!chan)
-               goto drop;
+               goto free_skb;
 
        BT_DBG("chan %p, len %d", chan, skb->len);
 
@@ -6864,36 +6806,14 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
        bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
        bt_cb(skb)->psm = psm;
 
-       if (!chan->ops->recv(chan, skb))
-               return;
-
-drop:
-       kfree_skb(skb);
-}
-
-static void l2cap_att_channel(struct l2cap_conn *conn,
-                             struct sk_buff *skb)
-{
-       struct hci_conn *hcon = conn->hcon;
-       struct l2cap_chan *chan;
-
-       if (hcon->type != LE_LINK)
-               goto drop;
-
-       chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
-                                        &hcon->src, &hcon->dst);
-       if (!chan)
-               goto drop;
-
-       BT_DBG("chan %p, len %d", chan, skb->len);
-
-       if (chan->imtu < skb->len)
-               goto drop;
-
-       if (!chan->ops->recv(chan, skb))
+       if (!chan->ops->recv(chan, skb)) {
+               l2cap_chan_put(chan);
                return;
+       }
 
 drop:
+       l2cap_chan_put(chan);
+free_skb:
        kfree_skb(skb);
 }
 
@@ -6942,19 +6862,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
                l2cap_conless_channel(conn, psm, skb);
                break;
 
-       case L2CAP_CID_ATT:
-               l2cap_att_channel(conn, skb);
-               break;
-
        case L2CAP_CID_LE_SIGNALING:
                l2cap_le_sig_channel(conn, skb);
                break;
 
-       case L2CAP_CID_SMP:
-               if (smp_sig_channel(conn, skb))
-                       l2cap_conn_del(conn->hcon, EACCES);
-               break;
-
        default:
                l2cap_data_channel(conn, cid, skb);
                break;
@@ -7023,10 +6934,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
        INIT_LIST_HEAD(&conn->chan_l);
        INIT_LIST_HEAD(&conn->users);
 
-       if (hcon->type == LE_LINK)
-               INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
-       else
-               INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
+       INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
+
+       INIT_WORK(&conn->disconn_work, disconn_work);
 
        skb_queue_head_init(&conn->pending_rx);
        INIT_WORK(&conn->pending_rx_work, process_pending_rx);
@@ -7239,19 +7149,99 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
        return exact ? lm1 : lm2;
 }
 
+/* Find the next fixed channel in BT_LISTEN state, continue iteration
+ * from an existing channel in the list or from the beginning of the
+ * global list (by passing NULL as first parameter).
+ */
+static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
+                                                 bdaddr_t *src, u8 link_type)
+{
+       read_lock(&chan_list_lock);
+
+       if (c)
+               c = list_next_entry(c, global_l);
+       else
+               c = list_entry(chan_list.next, typeof(*c), global_l);
+
+       list_for_each_entry_from(c, &chan_list, global_l) {
+               if (c->chan_type != L2CAP_CHAN_FIXED)
+                       continue;
+               if (c->state != BT_LISTEN)
+                       continue;
+               if (bacmp(&c->src, src) && bacmp(&c->src, BDADDR_ANY))
+                       continue;
+               if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
+                       continue;
+               if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
+                       continue;
+
+               l2cap_chan_hold(c);
+               read_unlock(&chan_list_lock);
+               return c;
+       }
+
+       read_unlock(&chan_list_lock);
+
+       return NULL;
+}
+
 void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 {
+       struct hci_dev *hdev = hcon->hdev;
        struct l2cap_conn *conn;
+       struct l2cap_chan *pchan;
+       u8 dst_type;
 
        BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
 
-       if (!status) {
-               conn = l2cap_conn_add(hcon);
-               if (conn)
-                       l2cap_conn_ready(conn);
-       } else {
+       if (status) {
                l2cap_conn_del(hcon, bt_to_errno(status));
+               return;
        }
+
+       conn = l2cap_conn_add(hcon);
+       if (!conn)
+               return;
+
+       dst_type = bdaddr_type(hcon, hcon->dst_type);
+
+       /* If device is blocked, do not create channels for it */
+       if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
+               return;
+
+       /* Find fixed channels and notify them of the new connection. We
+        * use multiple individual lookups, continuing each time where
+        * we left off, because the list lock would prevent calling the
+        * potentially sleeping l2cap_chan_lock() function.
+        */
+       pchan = l2cap_global_fixed_chan(NULL, &hdev->bdaddr, hcon->type);
+       while (pchan) {
+               struct l2cap_chan *chan, *next;
+
+               /* Client fixed channels should override server ones */
+               if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
+                       goto next;
+
+               l2cap_chan_lock(pchan);
+               chan = pchan->ops->new_connection(pchan);
+               if (chan) {
+                       bacpy(&chan->src, &hcon->src);
+                       bacpy(&chan->dst, &hcon->dst);
+                       chan->src_type = bdaddr_type(hcon, hcon->src_type);
+                       chan->dst_type = dst_type;
+
+                       __l2cap_chan_add(conn, chan);
+               }
+
+               l2cap_chan_unlock(pchan);
+next:
+               next = l2cap_global_fixed_chan(pchan, &hdev->bdaddr,
+                                              hcon->type);
+               l2cap_chan_put(pchan);
+               pchan = next;
+       }
+
+       l2cap_conn_ready(conn);
 }
 
 int l2cap_disconn_ind(struct hci_conn *hcon)
@@ -7299,12 +7289,6 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
        BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
 
-       if (hcon->type == LE_LINK) {
-               if (!status && encrypt)
-                       smp_distribute_keys(conn);
-               cancel_delayed_work(&conn->security_timer);
-       }
-
        mutex_lock(&conn->chan_lock);
 
        list_for_each_entry(chan, &conn->chan_l, list) {
@@ -7318,15 +7302,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                        continue;
                }
 
-               if (chan->scid == L2CAP_CID_ATT) {
-                       if (!status && encrypt) {
-                               chan->sec_level = hcon->sec_level;
-                               l2cap_chan_ready(chan);
-                       }
-
-                       l2cap_chan_unlock(chan);
-                       continue;
-               }
+               if (!status && encrypt)
+                       chan->sec_level = hcon->sec_level;
 
                if (!__l2cap_no_conn_pending(chan)) {
                        l2cap_chan_unlock(chan);
index 1884f72083c2f7de4595e91f2cdb61f02cef99bb..ed06f88e6f10955cae33d31a3e348b25d2c647f9 100644 (file)
@@ -99,15 +99,6 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
                return -EINVAL;
 
-       if (la.l2_cid) {
-               /* When the socket gets created it defaults to
-                * CHAN_CONN_ORIENTED, so we need to overwrite the
-                * default here.
-                */
-               chan->chan_type = L2CAP_CHAN_FIXED;
-               chan->omtu = L2CAP_DEFAULT_MTU;
-       }
-
        if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
                /* We only allow ATT user space socket */
                if (la.l2_cid &&
@@ -790,6 +781,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
                if (chan->scid == L2CAP_CID_ATT) {
                        if (smp_conn_security(conn->hcon, sec.level))
                                break;
+                       set_bit(FLAG_PENDING_SECURITY, &chan->flags);
                        sk->sk_state = BT_CONFIG;
                        chan->state = BT_CONFIG;
 
@@ -1359,6 +1351,11 @@ static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
 {
        struct sock *sk = chan->data;
 
+       if (test_and_clear_bit(FLAG_PENDING_SECURITY, &chan->flags)) {
+               sk->sk_state = BT_CONNECTED;
+               chan->state = BT_CONNECTED;
+       }
+
        clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
        sk->sk_state_change(sk);
 }
index b8554d429d889f97bd735cc62aaafce1e85bae5c..c2457435a670149c2d368f1c81dae2697972da1f 100644 (file)
@@ -129,9 +129,6 @@ static const u16 mgmt_events[] = {
 
 #define CACHE_TIMEOUT  msecs_to_jiffies(2 * 1000)
 
-#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
-                               !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
-
 struct pending_cmd {
        struct list_head list;
        u16 opcode;
@@ -1536,9 +1533,11 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
 
        /* When the discoverable mode gets changed, make sure
         * that class of device has the limited discoverable
-        * bit correctly set.
+        * bit correctly set. Also update page scan based on whitelist
+        * entries.
         */
        hci_req_init(&req, hdev);
+       hci_update_page_scan(hdev, &req);
        update_class(&req);
        hci_req_run(&req, NULL);
 
@@ -1785,6 +1784,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status)
 
        if (conn_changed || discov_changed) {
                new_settings(hdev, cmd->sk);
+               hci_update_page_scan(hdev, NULL);
                if (discov_changed)
                        mgmt_update_adv_data(hdev);
                hci_update_background_scan(hdev);
@@ -1818,6 +1818,7 @@ static int set_connectable_update_settings(struct hci_dev *hdev,
                return err;
 
        if (changed) {
+               hci_update_page_scan(hdev, NULL);
                hci_update_background_scan(hdev);
                return new_settings(hdev, sk);
        }
@@ -4381,27 +4382,6 @@ unlock:
        return err;
 }
 
-static void set_bredr_scan(struct hci_request *req)
-{
-       struct hci_dev *hdev = req->hdev;
-       u8 scan = 0;
-
-       /* Ensure that fast connectable is disabled. This function will
-        * not do anything if the page scan parameters are already what
-        * they should be.
-        */
-       write_fast_connectable(req, false);
-
-       if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
-           !list_empty(&hdev->whitelist))
-               scan |= SCAN_PAGE;
-       if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
-               scan |= SCAN_INQUIRY;
-
-       if (scan)
-               hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-}
-
 static void set_bredr_complete(struct hci_dev *hdev, u8 status)
 {
        struct pending_cmd *cmd;
@@ -4507,9 +4487,8 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
        hci_req_init(&req, hdev);
 
-       if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
-           !list_empty(&hdev->whitelist))
-               set_bredr_scan(&req);
+       write_fast_connectable(&req, false);
+       hci_update_page_scan(hdev, &req);
 
        /* Since only the advertising data flags will change, there
         * is no need to update the scan response data.
@@ -5235,27 +5214,6 @@ unlock:
        return err;
 }
 
-/* Helper for Add/Remove Device commands */
-static void update_page_scan(struct hci_dev *hdev, u8 scan)
-{
-       if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
-               return;
-
-       if (!hdev_is_powered(hdev))
-               return;
-
-       /* If HCI_CONNECTABLE is set then Add/Remove Device should not
-        * make any changes to page scanning.
-        */
-       if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
-               return;
-
-       if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
-               scan |= SCAN_INQUIRY;
-
-       hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-}
-
 static void device_added(struct sock *sk, struct hci_dev *hdev,
                         bdaddr_t *bdaddr, u8 type, u8 action)
 {
@@ -5291,8 +5249,6 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
        hci_dev_lock(hdev);
 
        if (cp->addr.type == BDADDR_BREDR) {
-               bool update_scan;
-
                /* Only incoming connections action is supported for now */
                if (cp->action != 0x01) {
                        err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
@@ -5301,15 +5257,12 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
                        goto unlock;
                }
 
-               update_scan = list_empty(&hdev->whitelist);
-
                err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
                                          cp->addr.type);
                if (err)
                        goto unlock;
 
-               if (update_scan)
-                       update_page_scan(hdev, SCAN_PAGE);
+               hci_update_page_scan(hdev, NULL);
 
                goto added;
        }
@@ -5392,8 +5345,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                                goto unlock;
                        }
 
-                       if (list_empty(&hdev->whitelist))
-                               update_page_scan(hdev, SCAN_DISABLED);
+                       hci_update_page_scan(hdev, NULL);
 
                        device_removed(sk, hdev, &cp->addr.bdaddr,
                                       cp->addr.type);
@@ -5444,7 +5396,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        kfree(b);
                }
 
-               update_page_scan(hdev, SCAN_DISABLED);
+               hci_update_page_scan(hdev, NULL);
 
                list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
                        if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
@@ -5969,8 +5921,8 @@ static int powered_update_hci(struct hci_dev *hdev)
                            sizeof(link_sec), &link_sec);
 
        if (lmp_bredr_capable(hdev)) {
-               if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
-                       set_bredr_scan(&req);
+               write_fast_connectable(&req, false);
+               hci_update_page_scan(hdev, &req);
                update_class(&req);
                update_name(&req);
                update_eir(&req);
@@ -6281,25 +6233,35 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
        mgmt_pending_remove(cmd);
 }
 
+bool mgmt_powering_down(struct hci_dev *hdev)
+{
+       struct pending_cmd *cmd;
+       struct mgmt_mode *cp;
+
+       cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
+       if (!cmd)
+               return false;
+
+       cp = cmd->param;
+       if (!cp->val)
+               return true;
+
+       return false;
+}
+
 void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
                              u8 link_type, u8 addr_type, u8 reason,
                              bool mgmt_connected)
 {
        struct mgmt_ev_device_disconnected ev;
-       struct pending_cmd *power_off;
        struct sock *sk = NULL;
 
-       power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
-       if (power_off) {
-               struct mgmt_mode *cp = power_off->param;
-
-               /* The connection is still in hci_conn_hash so test for 1
-                * instead of 0 to know if this is the last one.
-                */
-               if (!cp->val && hci_conn_count(hdev) == 1) {
-                       cancel_delayed_work(&hdev->power_off);
-                       queue_work(hdev->req_workqueue, &hdev->power_off.work);
-               }
+       /* The connection is still in hci_conn_hash so test for 1
+        * instead of 0 to know if this is the last one.
+        */
+       if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
+               cancel_delayed_work(&hdev->power_off);
+               queue_work(hdev->req_workqueue, &hdev->power_off.work);
        }
 
        if (!mgmt_connected)
@@ -6359,19 +6321,13 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
                         u8 addr_type, u8 status)
 {
        struct mgmt_ev_connect_failed ev;
-       struct pending_cmd *power_off;
-
-       power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
-       if (power_off) {
-               struct mgmt_mode *cp = power_off->param;
 
-               /* The connection is still in hci_conn_hash so test for 1
-                * instead of 0 to know if this is the last one.
-                */
-               if (!cp->val && hci_conn_count(hdev) == 1) {
-                       cancel_delayed_work(&hdev->power_off);
-                       queue_work(hdev->req_workqueue, &hdev->power_off.work);
-               }
+       /* The connection is still in hci_conn_hash so test for 1
+        * instead of 0 to know if this is the last one.
+        */
+       if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
+               cancel_delayed_work(&hdev->power_off);
+               queue_work(hdev->req_workqueue, &hdev->power_off.work);
        }
 
        bacpy(&ev.addr.bdaddr, bdaddr);
index fd32943008030332bc523e12a8d2e9a560381f04..07ca4ce0943b5b3b6d976c7b2351343e20d83149 100644 (file)
@@ -44,7 +44,10 @@ enum {
 };
 
 struct smp_chan {
-       struct l2cap_conn *conn;
+       struct l2cap_conn       *conn;
+       struct delayed_work     security_timer;
+       struct work_struct      distribute_work;
+
        u8              preq[7]; /* SMP Pairing Request */
        u8              prsp[7]; /* SMP Pairing Response */
        u8              prnd[16]; /* SMP Pairing Random (local) */
@@ -139,12 +142,18 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
        return 0;
 }
 
-bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
-                    bdaddr_t *bdaddr)
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
 {
+       struct l2cap_chan *chan = hdev->smp_data;
+       struct crypto_blkcipher *tfm;
        u8 hash[3];
        int err;
 
+       if (!chan || !chan->data)
+               return false;
+
+       tfm = chan->data;
+
        BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
 
        err = smp_ah(tfm, irk, &bdaddr->b[3], hash);
@@ -154,10 +163,17 @@ bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
        return !memcmp(bdaddr->b, hash, 3);
 }
 
-int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa)
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
 {
+       struct l2cap_chan *chan = hdev->smp_data;
+       struct crypto_blkcipher *tfm;
        int err;
 
+       if (!chan || !chan->data)
+               return -EOPNOTSUPP;
+
+       tfm = chan->data;
+
        get_random_bytes(&rpa->b[3], 3);
 
        rpa->b[5] &= 0x3f;      /* Clear two most significant bits */
@@ -235,47 +251,39 @@ static int smp_s1(struct smp_chan *smp, u8 k[16], u8 r1[16], u8 r2[16],
        return err;
 }
 
-static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
-                                    u16 dlen, void *data)
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 {
-       struct sk_buff *skb;
-       struct l2cap_hdr *lh;
-       int len;
-
-       len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
-
-       if (len > conn->mtu)
-               return NULL;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp;
+       struct kvec iv[2];
+       struct msghdr msg;
 
-       skb = bt_skb_alloc(len, GFP_ATOMIC);
-       if (!skb)
-               return NULL;
+       if (!chan)
+               return;
 
-       lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-       lh->len = cpu_to_le16(sizeof(code) + dlen);
-       lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+       BT_DBG("code 0x%2.2x", code);
 
-       memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+       iv[0].iov_base = &code;
+       iv[0].iov_len = 1;
 
-       memcpy(skb_put(skb, dlen), data, dlen);
+       iv[1].iov_base = data;
+       iv[1].iov_len = len;
 
-       return skb;
-}
+       memset(&msg, 0, sizeof(msg));
 
-static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
-{
-       struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+       msg.msg_iov = (struct iovec *) &iv;
+       msg.msg_iovlen = 2;
 
-       BT_DBG("code 0x%2.2x", code);
+       l2cap_chan_send(chan, &msg, 1 + len);
 
-       if (!skb)
+       if (!chan->data)
                return;
 
-       skb->priority = HCI_PRIO_MAX;
-       hci_send_acl(conn->hchan, skb, 0);
+       smp = chan->data;
 
-       cancel_delayed_work_sync(&conn->security_timer);
-       schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
+       cancel_delayed_work_sync(&smp->security_timer);
+       if (test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
+               schedule_delayed_work(&smp->security_timer, SMP_TIMEOUT);
 }
 
 static __u8 authreq_to_seclevel(__u8 authreq)
@@ -302,7 +310,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                              struct smp_cmd_pairing *req,
                              struct smp_cmd_pairing *rsp, __u8 authreq)
 {
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
        struct hci_conn *hcon = conn->hcon;
        struct hci_dev *hdev = hcon->hdev;
        u8 local_dist = 0, remote_dist = 0;
@@ -345,7 +354,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
 
 static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
 {
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
 
        if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
            (max_key_size < SMP_MIN_ENC_KEY_SIZE))
@@ -356,9 +366,61 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
        return 0;
 }
 
+static void smp_chan_destroy(struct l2cap_conn *conn)
+{
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
+       bool complete;
+
+       BUG_ON(!smp);
+
+       cancel_delayed_work_sync(&smp->security_timer);
+       /* In case the timeout freed the SMP context */
+       if (!chan->data)
+               return;
+
+       if (work_pending(&smp->distribute_work)) {
+               cancel_work_sync(&smp->distribute_work);
+               if (!chan->data)
+                       return;
+       }
+
+       complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
+       mgmt_smp_complete(conn->hcon, complete);
+
+       kfree(smp->csrk);
+       kfree(smp->slave_csrk);
+
+       crypto_free_blkcipher(smp->tfm_aes);
+
+       /* If pairing failed clean up any keys we might have */
+       if (!complete) {
+               if (smp->ltk) {
+                       list_del(&smp->ltk->list);
+                       kfree(smp->ltk);
+               }
+
+               if (smp->slave_ltk) {
+                       list_del(&smp->slave_ltk->list);
+                       kfree(smp->slave_ltk);
+               }
+
+               if (smp->remote_irk) {
+                       list_del(&smp->remote_irk->list);
+                       kfree(smp->remote_irk);
+               }
+       }
+
+       chan->data = NULL;
+       kfree(smp);
+       hci_conn_drop(conn->hcon);
+}
+
 static void smp_failure(struct l2cap_conn *conn, u8 reason)
 {
        struct hci_conn *hcon = conn->hcon;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp;
 
        if (reason)
                smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
@@ -368,7 +430,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason)
        mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
                         HCI_ERROR_AUTH_FAILURE);
 
-       cancel_delayed_work_sync(&conn->security_timer);
+       if (!chan->data)
+               return;
+
+       smp = chan->data;
 
        if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
                smp_chan_destroy(conn);
@@ -405,7 +470,8 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
                                                u8 local_io, u8 remote_io)
 {
        struct hci_conn *hcon = conn->hcon;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
        u8 method;
        u32 passkey = 0;
        int ret = 0;
@@ -574,8 +640,201 @@ static u8 smp_random(struct smp_chan *smp)
        return 0;
 }
 
+static void smp_notify_keys(struct l2cap_conn *conn)
+{
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
+       struct hci_conn *hcon = conn->hcon;
+       struct hci_dev *hdev = hcon->hdev;
+       struct smp_cmd_pairing *req = (void *) &smp->preq[1];
+       struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1];
+       bool persistent;
+
+       if (smp->remote_irk) {
+               mgmt_new_irk(hdev, smp->remote_irk);
+               /* Now that user space can be considered to know the
+                * identity address track the connection based on it
+                * from now on.
+                */
+               bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
+               hcon->dst_type = smp->remote_irk->addr_type;
+               l2cap_conn_update_id_addr(hcon);
+
+               /* When receiving an indentity resolving key for
+                * a remote device that does not use a resolvable
+                * private address, just remove the key so that
+                * it is possible to use the controller white
+                * list for scanning.
+                *
+                * Userspace will have been told to not store
+                * this key at this point. So it is safe to
+                * just remove it.
+                */
+               if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
+                       list_del(&smp->remote_irk->list);
+                       kfree(smp->remote_irk);
+                       smp->remote_irk = NULL;
+               }
+       }
+
+       /* The LTKs and CSRKs should be persistent only if both sides
+        * had the bonding bit set in their authentication requests.
+        */
+       persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
+
+       if (smp->csrk) {
+               smp->csrk->bdaddr_type = hcon->dst_type;
+               bacpy(&smp->csrk->bdaddr, &hcon->dst);
+               mgmt_new_csrk(hdev, smp->csrk, persistent);
+       }
+
+       if (smp->slave_csrk) {
+               smp->slave_csrk->bdaddr_type = hcon->dst_type;
+               bacpy(&smp->slave_csrk->bdaddr, &hcon->dst);
+               mgmt_new_csrk(hdev, smp->slave_csrk, persistent);
+       }
+
+       if (smp->ltk) {
+               smp->ltk->bdaddr_type = hcon->dst_type;
+               bacpy(&smp->ltk->bdaddr, &hcon->dst);
+               mgmt_new_ltk(hdev, smp->ltk, persistent);
+       }
+
+       if (smp->slave_ltk) {
+               smp->slave_ltk->bdaddr_type = hcon->dst_type;
+               bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
+               mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
+       }
+}
+
+static void smp_distribute_keys(struct work_struct *work)
+{
+       struct smp_chan *smp = container_of(work, struct smp_chan,
+                                           distribute_work);
+       struct smp_cmd_pairing *req, *rsp;
+       struct l2cap_conn *conn = smp->conn;
+       struct hci_conn *hcon = conn->hcon;
+       struct hci_dev *hdev = hcon->hdev;
+       __u8 *keydist;
+
+       BT_DBG("conn %p", conn);
+
+       if (!test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
+               return;
+
+       rsp = (void *) &smp->prsp[1];
+
+       /* The responder sends its keys first */
+       if (hcon->out && (smp->remote_key_dist & 0x07))
+               return;
+
+       req = (void *) &smp->preq[1];
+
+       if (hcon->out) {
+               keydist = &rsp->init_key_dist;
+               *keydist &= req->init_key_dist;
+       } else {
+               keydist = &rsp->resp_key_dist;
+               *keydist &= req->resp_key_dist;
+       }
+
+       BT_DBG("keydist 0x%x", *keydist);
+
+       if (*keydist & SMP_DIST_ENC_KEY) {
+               struct smp_cmd_encrypt_info enc;
+               struct smp_cmd_master_ident ident;
+               struct smp_ltk *ltk;
+               u8 authenticated;
+               __le16 ediv;
+               __le64 rand;
+
+               get_random_bytes(enc.ltk, sizeof(enc.ltk));
+               get_random_bytes(&ediv, sizeof(ediv));
+               get_random_bytes(&rand, sizeof(rand));
+
+               smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
+
+               authenticated = hcon->sec_level == BT_SECURITY_HIGH;
+               ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type,
+                                 SMP_LTK_SLAVE, authenticated, enc.ltk,
+                                 smp->enc_key_size, ediv, rand);
+               smp->slave_ltk = ltk;
+
+               ident.ediv = ediv;
+               ident.rand = rand;
+
+               smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
+
+               *keydist &= ~SMP_DIST_ENC_KEY;
+       }
+
+       if (*keydist & SMP_DIST_ID_KEY) {
+               struct smp_cmd_ident_addr_info addrinfo;
+               struct smp_cmd_ident_info idinfo;
+
+               memcpy(idinfo.irk, hdev->irk, sizeof(idinfo.irk));
+
+               smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
+
+               /* The hci_conn contains the local identity address
+                * after the connection has been established.
+                *
+                * This is true even when the connection has been
+                * established using a resolvable random address.
+                */
+               bacpy(&addrinfo.bdaddr, &hcon->src);
+               addrinfo.addr_type = hcon->src_type;
+
+               smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
+                            &addrinfo);
+
+               *keydist &= ~SMP_DIST_ID_KEY;
+       }
+
+       if (*keydist & SMP_DIST_SIGN) {
+               struct smp_cmd_sign_info sign;
+               struct smp_csrk *csrk;
+
+               /* Generate a new random key */
+               get_random_bytes(sign.csrk, sizeof(sign.csrk));
+
+               csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
+               if (csrk) {
+                       csrk->master = 0x00;
+                       memcpy(csrk->val, sign.csrk, sizeof(csrk->val));
+               }
+               smp->slave_csrk = csrk;
+
+               smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
+
+               *keydist &= ~SMP_DIST_SIGN;
+       }
+
+       /* If there are still keys to be received wait for them */
+       if ((smp->remote_key_dist & 0x07))
+               return;
+
+       clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
+       set_bit(SMP_FLAG_COMPLETE, &smp->flags);
+       smp_notify_keys(conn);
+
+       smp_chan_destroy(conn);
+}
+
+static void smp_timeout(struct work_struct *work)
+{
+       struct smp_chan *smp = container_of(work, struct smp_chan,
+                                           security_timer.work);
+       struct l2cap_conn *conn = smp->conn;
+
+       BT_DBG("conn %p", conn);
+
+       l2cap_conn_shutdown(conn, ETIMEDOUT);
+}
+
 static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
 {
+       struct l2cap_chan *chan = conn->smp;
        struct smp_chan *smp;
 
        smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
@@ -593,54 +852,20 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
        }
 
        smp->conn = conn;
-       conn->smp_chan = smp;
+       chan->data = smp;
+
+       INIT_WORK(&smp->distribute_work, smp_distribute_keys);
+       INIT_DELAYED_WORK(&smp->security_timer, smp_timeout);
 
        hci_conn_hold(conn->hcon);
 
        return smp;
 }
 
-void smp_chan_destroy(struct l2cap_conn *conn)
-{
-       struct smp_chan *smp = conn->smp_chan;
-       bool complete;
-
-       BUG_ON(!smp);
-
-       complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
-       mgmt_smp_complete(conn->hcon, complete);
-
-       kfree(smp->csrk);
-       kfree(smp->slave_csrk);
-
-       crypto_free_blkcipher(smp->tfm_aes);
-
-       /* If pairing failed clean up any keys we might have */
-       if (!complete) {
-               if (smp->ltk) {
-                       list_del(&smp->ltk->list);
-                       kfree(smp->ltk);
-               }
-
-               if (smp->slave_ltk) {
-                       list_del(&smp->slave_ltk->list);
-                       kfree(smp->slave_ltk);
-               }
-
-               if (smp->remote_irk) {
-                       list_del(&smp->remote_irk->list);
-                       kfree(smp->remote_irk);
-               }
-       }
-
-       kfree(smp);
-       conn->smp_chan = NULL;
-       hci_conn_drop(conn->hcon);
-}
-
 int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
+       struct l2cap_chan *chan;
        struct smp_chan *smp;
        u32 value;
 
@@ -649,7 +874,11 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
        if (!conn || !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
                return -ENOTCONN;
 
-       smp = conn->smp_chan;
+       chan = conn->smp;
+       if (!chan)
+               return -ENOTCONN;
+
+       smp = chan->data;
 
        switch (mgmt_op) {
        case MGMT_OP_USER_PASSKEY_REPLY:
@@ -696,10 +925,12 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
        if (conn->hcon->role != HCI_ROLE_SLAVE)
                return SMP_CMD_NOTSUPP;
 
-       if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
+       if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
                smp = smp_chan_create(conn);
-       else
-               smp = conn->smp_chan;
+       } else {
+               struct l2cap_chan *chan = conn->smp;
+               smp = chan->data;
+       }
 
        if (!smp)
                return SMP_UNSPECIFIED;
@@ -753,7 +984,8 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
        u8 key_size, auth = SMP_AUTH_NONE;
        int ret;
 
@@ -814,7 +1046,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 
 static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
 
        BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
 
@@ -837,7 +1070,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 
 static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
 
        BT_DBG("conn %p", conn);
 
@@ -1010,7 +1244,8 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct smp_cmd_encrypt_info *rp = (void *) skb->data;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
 
        BT_DBG("conn %p", conn);
 
@@ -1031,7 +1266,8 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
 static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct smp_cmd_master_ident *rp = (void *) skb->data;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
        struct hci_dev *hdev = conn->hcon->hdev;
        struct hci_conn *hcon = conn->hcon;
        struct smp_ltk *ltk;
@@ -1058,7 +1294,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
                          rp->ediv, rp->rand);
        smp->ltk = ltk;
        if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
-               smp_distribute_keys(conn);
+               queue_work(hdev->workqueue, &smp->distribute_work);
        hci_dev_unlock(hdev);
 
        return 0;
@@ -1067,7 +1303,8 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
 static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct smp_cmd_ident_info *info = (void *) skb->data;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
 
        BT_DBG("");
 
@@ -1089,8 +1326,10 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
                                   struct sk_buff *skb)
 {
        struct smp_cmd_ident_addr_info *info = (void *) skb->data;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
        struct hci_conn *hcon = conn->hcon;
+       struct hci_dev *hdev = hcon->hdev;
        bdaddr_t rpa;
 
        BT_DBG("");
@@ -1133,7 +1372,7 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
                                      smp->id_addr_type, smp->irk, &rpa);
 
 distribute:
-       smp_distribute_keys(conn);
+       queue_work(hdev->workqueue, &smp->distribute_work);
 
        hci_dev_unlock(hcon->hdev);
 
@@ -1143,7 +1382,8 @@ distribute:
 static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct smp_cmd_sign_info *rp = (void *) skb->data;
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
        struct hci_dev *hdev = conn->hcon->hdev;
        struct smp_csrk *csrk;
 
@@ -1168,15 +1408,15 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
                memcpy(csrk->val, rp->csrk, sizeof(csrk->val));
        }
        smp->csrk = csrk;
-       if (!(smp->remote_key_dist & SMP_DIST_SIGN))
-               smp_distribute_keys(conn);
+       queue_work(hdev->workqueue, &smp->distribute_work);
        hci_dev_unlock(hdev);
 
        return 0;
 }
 
-int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
 {
+       struct l2cap_conn *conn = chan->conn;
        struct hci_conn *hcon = conn->hcon;
        __u8 code, reason;
        int err = 0;
@@ -1186,10 +1426,8 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
                return 0;
        }
 
-       if (skb->len < 1) {
-               kfree_skb(skb);
+       if (skb->len < 1)
                return -EILSEQ;
-       }
 
        if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
                err = -EOPNOTSUPP;
@@ -1207,10 +1445,11 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
         * returns an error).
         */
        if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
-           !conn->smp_chan) {
+           !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
                BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
-               kfree_skb(skb);
-               return -EOPNOTSUPP;
+               reason = SMP_CMD_NOTSUPP;
+               err = -EOPNOTSUPP;
+               goto done;
        }
 
        switch (code) {
@@ -1271,188 +1510,201 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 done:
        if (reason)
                smp_failure(conn, reason);
-
-       kfree_skb(skb);
+       if (!err)
+               kfree_skb(skb);
        return err;
 }
 
-static void smp_notify_keys(struct l2cap_conn *conn)
+static void smp_teardown_cb(struct l2cap_chan *chan, int err)
 {
-       struct smp_chan *smp = conn->smp_chan;
+       struct l2cap_conn *conn = chan->conn;
+
+       BT_DBG("chan %p", chan);
+
+       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
+               smp_chan_destroy(conn);
+
+       conn->smp = NULL;
+       l2cap_chan_put(chan);
+}
+
+static void smp_resume_cb(struct l2cap_chan *chan)
+{
+       struct smp_chan *smp = chan->data;
+       struct l2cap_conn *conn = chan->conn;
        struct hci_conn *hcon = conn->hcon;
        struct hci_dev *hdev = hcon->hdev;
-       struct smp_cmd_pairing *req = (void *) &smp->preq[1];
-       struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1];
-       bool persistent;
 
-       if (smp->remote_irk) {
-               mgmt_new_irk(hdev, smp->remote_irk);
-               /* Now that user space can be considered to know the
-                * identity address track the connection based on it
-                * from now on.
-                */
-               bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
-               hcon->dst_type = smp->remote_irk->addr_type;
-               l2cap_conn_update_id_addr(hcon);
+       BT_DBG("chan %p", chan);
 
-               /* When receiving an indentity resolving key for
-                * a remote device that does not use a resolvable
-                * private address, just remove the key so that
-                * it is possible to use the controller white
-                * list for scanning.
-                *
-                * Userspace will have been told to not store
-                * this key at this point. So it is safe to
-                * just remove it.
-                */
-               if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
-                       list_del(&smp->remote_irk->list);
-                       kfree(smp->remote_irk);
-                       smp->remote_irk = NULL;
-               }
-       }
+       if (!smp)
+               return;
 
-       /* The LTKs and CSRKs should be persistent only if both sides
-        * had the bonding bit set in their authentication requests.
-        */
-       persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
+       cancel_delayed_work(&smp->security_timer);
 
-       if (smp->csrk) {
-               smp->csrk->bdaddr_type = hcon->dst_type;
-               bacpy(&smp->csrk->bdaddr, &hcon->dst);
-               mgmt_new_csrk(hdev, smp->csrk, persistent);
-       }
+       if (test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
+               queue_work(hdev->workqueue, &smp->distribute_work);
+}
 
-       if (smp->slave_csrk) {
-               smp->slave_csrk->bdaddr_type = hcon->dst_type;
-               bacpy(&smp->slave_csrk->bdaddr, &hcon->dst);
-               mgmt_new_csrk(hdev, smp->slave_csrk, persistent);
-       }
+static void smp_ready_cb(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
 
-       if (smp->ltk) {
-               smp->ltk->bdaddr_type = hcon->dst_type;
-               bacpy(&smp->ltk->bdaddr, &hcon->dst);
-               mgmt_new_ltk(hdev, smp->ltk, persistent);
-       }
+       BT_DBG("chan %p", chan);
 
-       if (smp->slave_ltk) {
-               smp->slave_ltk->bdaddr_type = hcon->dst_type;
-               bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
-               mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
-       }
+       conn->smp = chan;
+       l2cap_chan_hold(chan);
 }
 
-int smp_distribute_keys(struct l2cap_conn *conn)
+static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
 {
-       struct smp_cmd_pairing *req, *rsp;
-       struct smp_chan *smp = conn->smp_chan;
-       struct hci_conn *hcon = conn->hcon;
-       struct hci_dev *hdev = hcon->hdev;
-       __u8 *keydist;
+       int err;
 
-       BT_DBG("conn %p", conn);
+       BT_DBG("chan %p", chan);
 
-       if (!test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
-               return 0;
+       err = smp_sig_channel(chan, skb);
+       if (err) {
+               struct smp_chan *smp = chan->data;
 
-       rsp = (void *) &smp->prsp[1];
+               if (smp)
+                       cancel_delayed_work_sync(&smp->security_timer);
 
-       /* The responder sends its keys first */
-       if (hcon->out && (smp->remote_key_dist & 0x07))
-               return 0;
+               l2cap_conn_shutdown(chan->conn, -err);
+       }
 
-       req = (void *) &smp->preq[1];
+       return err;
+}
 
-       if (hcon->out) {
-               keydist = &rsp->init_key_dist;
-               *keydist &= req->init_key_dist;
-       } else {
-               keydist = &rsp->resp_key_dist;
-               *keydist &= req->resp_key_dist;
-       }
+static struct sk_buff *smp_alloc_skb_cb(struct l2cap_chan *chan,
+                                       unsigned long hdr_len,
+                                       unsigned long len, int nb)
+{
+       struct sk_buff *skb;
 
-       BT_DBG("keydist 0x%x", *keydist);
+       skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
+       if (!skb)
+               return ERR_PTR(-ENOMEM);
 
-       if (*keydist & SMP_DIST_ENC_KEY) {
-               struct smp_cmd_encrypt_info enc;
-               struct smp_cmd_master_ident ident;
-               struct smp_ltk *ltk;
-               u8 authenticated;
-               __le16 ediv;
-               __le64 rand;
+       skb->priority = HCI_PRIO_MAX;
+       bt_cb(skb)->chan = chan;
 
-               get_random_bytes(enc.ltk, sizeof(enc.ltk));
-               get_random_bytes(&ediv, sizeof(ediv));
-               get_random_bytes(&rand, sizeof(rand));
+       return skb;
+}
 
-               smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
+static const struct l2cap_ops smp_chan_ops = {
+       .name                   = "Security Manager",
+       .ready                  = smp_ready_cb,
+       .recv                   = smp_recv_cb,
+       .alloc_skb              = smp_alloc_skb_cb,
+       .teardown               = smp_teardown_cb,
+       .resume                 = smp_resume_cb,
+
+       .new_connection         = l2cap_chan_no_new_connection,
+       .state_change           = l2cap_chan_no_state_change,
+       .close                  = l2cap_chan_no_close,
+       .defer                  = l2cap_chan_no_defer,
+       .suspend                = l2cap_chan_no_suspend,
+       .set_shutdown           = l2cap_chan_no_set_shutdown,
+       .get_sndtimeo           = l2cap_chan_no_get_sndtimeo,
+       .memcpy_fromiovec       = l2cap_chan_no_memcpy_fromiovec,
+};
 
-               authenticated = hcon->sec_level == BT_SECURITY_HIGH;
-               ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type,
-                                 SMP_LTK_SLAVE, authenticated, enc.ltk,
-                                 smp->enc_key_size, ediv, rand);
-               smp->slave_ltk = ltk;
+static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
+{
+       struct l2cap_chan *chan;
 
-               ident.ediv = ediv;
-               ident.rand = rand;
+       BT_DBG("pchan %p", pchan);
 
-               smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
+       chan = l2cap_chan_create();
+       if (!chan)
+               return NULL;
 
-               *keydist &= ~SMP_DIST_ENC_KEY;
-       }
+       chan->chan_type = pchan->chan_type;
+       chan->ops       = &smp_chan_ops;
+       chan->scid      = pchan->scid;
+       chan->dcid      = chan->scid;
+       chan->imtu      = pchan->imtu;
+       chan->omtu      = pchan->omtu;
+       chan->mode      = pchan->mode;
 
-       if (*keydist & SMP_DIST_ID_KEY) {
-               struct smp_cmd_ident_addr_info addrinfo;
-               struct smp_cmd_ident_info idinfo;
+       BT_DBG("created chan %p", chan);
 
-               memcpy(idinfo.irk, hdev->irk, sizeof(idinfo.irk));
+       return chan;
+}
 
-               smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
+static const struct l2cap_ops smp_root_chan_ops = {
+       .name                   = "Security Manager Root",
+       .new_connection         = smp_new_conn_cb,
+
+       /* None of these are implemented for the root channel */
+       .close                  = l2cap_chan_no_close,
+       .alloc_skb              = l2cap_chan_no_alloc_skb,
+       .recv                   = l2cap_chan_no_recv,
+       .state_change           = l2cap_chan_no_state_change,
+       .teardown               = l2cap_chan_no_teardown,
+       .ready                  = l2cap_chan_no_ready,
+       .defer                  = l2cap_chan_no_defer,
+       .suspend                = l2cap_chan_no_suspend,
+       .resume                 = l2cap_chan_no_resume,
+       .set_shutdown           = l2cap_chan_no_set_shutdown,
+       .get_sndtimeo           = l2cap_chan_no_get_sndtimeo,
+       .memcpy_fromiovec       = l2cap_chan_no_memcpy_fromiovec,
+};
 
-               /* The hci_conn contains the local identity address
-                * after the connection has been established.
-                *
-                * This is true even when the connection has been
-                * established using a resolvable random address.
-                */
-               bacpy(&addrinfo.bdaddr, &hcon->src);
-               addrinfo.addr_type = hcon->src_type;
+int smp_register(struct hci_dev *hdev)
+{
+       struct l2cap_chan *chan;
+       struct crypto_blkcipher *tfm_aes;
 
-               smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
-                            &addrinfo);
+       BT_DBG("%s", hdev->name);
 
-               *keydist &= ~SMP_DIST_ID_KEY;
+       tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(tfm_aes)) {
+               int err = PTR_ERR(tfm_aes);
+               BT_ERR("Unable to create crypto context");
+               return err;
        }
 
-       if (*keydist & SMP_DIST_SIGN) {
-               struct smp_cmd_sign_info sign;
-               struct smp_csrk *csrk;
+       chan = l2cap_chan_create();
+       if (!chan) {
+               crypto_free_blkcipher(tfm_aes);
+               return -ENOMEM;
+       }
 
-               /* Generate a new random key */
-               get_random_bytes(sign.csrk, sizeof(sign.csrk));
+       chan->data = tfm_aes;
 
-               csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
-               if (csrk) {
-                       csrk->master = 0x00;
-                       memcpy(csrk->val, sign.csrk, sizeof(csrk->val));
-               }
-               smp->slave_csrk = csrk;
+       l2cap_add_scid(chan, L2CAP_CID_SMP);
 
-               smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
+       l2cap_chan_set_defaults(chan);
 
-               *keydist &= ~SMP_DIST_SIGN;
-       }
+       bacpy(&chan->src, &hdev->bdaddr);
+       chan->src_type = BDADDR_LE_PUBLIC;
+       chan->state = BT_LISTEN;
+       chan->mode = L2CAP_MODE_BASIC;
+       chan->imtu = L2CAP_DEFAULT_MTU;
+       chan->ops = &smp_root_chan_ops;
 
-       /* If there are still keys to be received wait for them */
-       if ((smp->remote_key_dist & 0x07))
-               return 0;
+       hdev->smp_data = chan;
 
-       clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
-       cancel_delayed_work_sync(&conn->security_timer);
-       set_bit(SMP_FLAG_COMPLETE, &smp->flags);
-       smp_notify_keys(conn);
+       return 0;
+}
 
-       smp_chan_destroy(conn);
+void smp_unregister(struct hci_dev *hdev)
+{
+       struct l2cap_chan *chan = hdev->smp_data;
+       struct crypto_blkcipher *tfm_aes;
 
-       return 0;
+       if (!chan)
+               return;
+
+       BT_DBG("%s chan %p", hdev->name, chan);
+
+       tfm_aes = chan->data;
+       if (tfm_aes) {
+               chan->data = NULL;
+               crypto_free_blkcipher(tfm_aes);
+       }
+
+       hdev->smp_data = NULL;
+       l2cap_chan_put(chan);
 }
index 796f4f45f92f67e43e32d75bfb015b5175f2aba0..cf1094617c69890eb489d314cc2b7ce021305673 100644 (file)
@@ -126,14 +126,12 @@ enum {
 /* SMP Commands */
 bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
-int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
-int smp_distribute_keys(struct l2cap_conn *conn);
 int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
 
-void smp_chan_destroy(struct l2cap_conn *conn);
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
 
-bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
-                    bdaddr_t *bdaddr);
-int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa);
+int smp_register(struct hci_dev *hdev);
+void smp_unregister(struct hci_dev *hdev);
 
 #endif /* __SMP_H */
index 016b77ee88f0e2f1394c0456f67e9e01ec190d9f..509d7a625a4bf056049e3a9fb543ac3ec02f93f8 100644 (file)
@@ -77,14 +77,6 @@ lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
        return netdev_priv(dev);
 }
 
-static inline void lowpan_address_flip(u8 *src, u8 *dest)
-{
-       int i;
-
-       for (i = 0; i < IEEE802154_ADDR_LEN; i++)
-               (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i];
-}
-
 static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
                                unsigned short type, const void *_daddr,
                                const void *_saddr, unsigned int len)
index 7f820a108a9cf3461a46a57522251ea4edc51003..a14cf9ede171e7bcc2c1373931e5e7754b36bab4 100644 (file)
@@ -86,9 +86,8 @@ fail:
 static void mac802154_rx_worker(struct work_struct *work)
 {
        struct rx_work *rw = container_of(work, struct rx_work, work);
-       struct sk_buff *skb = rw->skb;
 
-       mac802154_subif_rx(rw->dev, skb, rw->lqi);
+       mac802154_subif_rx(rw->dev, rw->skb, rw->lqi);
        kfree(rw);
 }
 
@@ -101,7 +100,7 @@ ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi)
        if (!skb)
                return;
 
-       work = kzalloc(sizeof(struct rx_work), GFP_ATOMIC);
+       work = kzalloc(sizeof(*work), GFP_ATOMIC);
        if (!work)
                return;
 
index 8124353646ae64239556a0ed915f046f7e689864..fdf4c0e67259ecceacc0b06b9060405ded6f63cc 100644 (file)
@@ -89,8 +89,7 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
 
        if (!(priv->phy->channels_supported[page] & (1 << chan))) {
                WARN_ON(1);
-               kfree_skb(skb);
-               return NETDEV_TX_OK;
+               goto err_tx;
        }
 
        mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
@@ -103,12 +102,10 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
                data[1] = crc >> 8;
        }
 
-       if (skb_cow_head(skb, priv->hw.extra_tx_headroom)) {
-               kfree_skb(skb);
-               return NETDEV_TX_OK;
-       }
+       if (skb_cow_head(skb, priv->hw.extra_tx_headroom))
+               goto err_tx;
 
-       work = kzalloc(sizeof(struct xmit_work), GFP_ATOMIC);
+       work = kzalloc(sizeof(*work), GFP_ATOMIC);
        if (!work) {
                kfree_skb(skb);
                return NETDEV_TX_BUSY;
@@ -129,4 +126,8 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
        queue_work(priv->dev_workqueue, &work->work);
 
        return NETDEV_TX_OK;
+
+err_tx:
+       kfree_skb(skb);
+       return NETDEV_TX_OK;
 }
index 3c3069fd69718277fc719e82d7bf2c51bb9747db..ce1757001917a3654f732274bc24130f78e6406c 100644 (file)
@@ -472,8 +472,7 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
        rc = mac802154_llsec_decrypt(&sdata->sec, skb);
        if (rc) {
                pr_debug("decryption failed: %i\n", rc);
-               kfree_skb(skb);
-               return NET_RX_DROP;
+               goto fail;
        }
 
        sdata->dev->stats.rx_packets++;
@@ -485,9 +484,12 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
        default:
                pr_warn("ieee802154: bad frame received (type = %d)\n",
                        mac_cb(skb)->type);
-               kfree_skb(skb);
-               return NET_RX_DROP;
+               goto fail;
        }
+
+fail:
+       kfree_skb(skb);
+       return NET_RX_DROP;
 }
 
 static void mac802154_print_addr(const char *name,