Commit 7bcfeead authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2015-10-08

Here's another set of Bluetooth & 802.15.4 patches for the 4.4 kernel.

802.15.4:
 - Many improvements & fixes to the mrf24j40 driver
 - Fixes and cleanups to nl802154, mac802154 & ieee802154 code

Bluetooth:
 - New chipset support in btmrvl driver
 - Fixes & cleanups to btbcm, btmrvl, bpa10x & btintel drivers
 - Support for vendor specific diagnostic data through common API
 - Cleanups to the 6lowpan code
 - New events & message types for monitor channel

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8fae307c f640ee98
* MRF24J40 IEEE 802.15.4 *
Required properties:
- compatible: should be "microchip,mrf24j40", "microchip,mrf24j40ma",
or "microchip,mrf24j40mc" depends on your transceiver
board
- spi-max-frequency: maximal bus speed, should be set something under or equal
10000000
- reg: the chipselect index
- interrupts: the interrupt generated by the device.
Example:
mrf24j40ma@0 {
compatible = "microchip,mrf24j40ma";
spi-max-frequency = <8500000>;
reg = <0>;
interrupts = <19 8>;
interrupt-parent = <&gpio3>;
};
...@@ -6978,6 +6978,7 @@ M: Alan Ott <alan@signal11.us> ...@@ -6978,6 +6978,7 @@ M: Alan Ott <alan@signal11.us>
L: linux-wpan@vger.kernel.org L: linux-wpan@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ieee802154/mrf24j40.c F: drivers/net/ieee802154/mrf24j40.c
F: Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt
MSI LAPTOP SUPPORT MSI LAPTOP SUPPORT
M: "Lee, Chun-Yi" <jlee@suse.com> M: "Lee, Chun-Yi" <jlee@suse.com>
......
...@@ -4,6 +4,7 @@ menu "Bluetooth device drivers" ...@@ -4,6 +4,7 @@ menu "Bluetooth device drivers"
config BT_INTEL config BT_INTEL
tristate tristate
select REGMAP
config BT_BCM config BT_BCM
tristate tristate
...@@ -183,6 +184,7 @@ config BT_HCIBCM203X ...@@ -183,6 +184,7 @@ config BT_HCIBCM203X
config BT_HCIBPA10X config BT_HCIBPA10X
tristate "HCI BPA10x USB driver" tristate "HCI BPA10x USB driver"
depends on USB depends on USB
select BT_HCIUART_H4
help help
Bluetooth HCI BPA10x USB driver. Bluetooth HCI BPA10x USB driver.
This driver provides support for the Digianswer BPA 100/105 Bluetooth This driver provides support for the Digianswer BPA 100/105 Bluetooth
...@@ -275,7 +277,7 @@ config BT_MRVL ...@@ -275,7 +277,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897. Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8997.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -289,7 +291,7 @@ config BT_MRVL_SDIO ...@@ -289,7 +291,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897 devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8997
chipsets are supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
......
...@@ -422,17 +422,12 @@ static int bfusb_open(struct hci_dev *hdev) ...@@ -422,17 +422,12 @@ static int bfusb_open(struct hci_dev *hdev)
BT_DBG("hdev %p bfusb %p", hdev, data); BT_DBG("hdev %p bfusb %p", hdev, data);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
write_lock_irqsave(&data->lock, flags); write_lock_irqsave(&data->lock, flags);
err = bfusb_rx_submit(data, NULL); err = bfusb_rx_submit(data, NULL);
if (!err) { if (!err) {
for (i = 1; i < BFUSB_MAX_BULK_RX; i++) for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
bfusb_rx_submit(data, NULL); bfusb_rx_submit(data, NULL);
} else {
clear_bit(HCI_RUNNING, &hdev->flags);
} }
write_unlock_irqrestore(&data->lock, flags); write_unlock_irqrestore(&data->lock, flags);
...@@ -458,9 +453,6 @@ static int bfusb_close(struct hci_dev *hdev) ...@@ -458,9 +453,6 @@ static int bfusb_close(struct hci_dev *hdev)
BT_DBG("hdev %p bfusb %p", hdev, data); BT_DBG("hdev %p bfusb %p", hdev, data);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
write_lock_irqsave(&data->lock, flags); write_lock_irqsave(&data->lock, flags);
write_unlock_irqrestore(&data->lock, flags); write_unlock_irqrestore(&data->lock, flags);
...@@ -479,9 +471,6 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -479,9 +471,6 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++; hdev->stat.cmd_tx++;
......
...@@ -390,7 +390,7 @@ static void bluecard_receive(struct bluecard_info *info, ...@@ -390,7 +390,7 @@ static void bluecard_receive(struct bluecard_info *info,
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
/* Allocate packet */ /* Allocate packet */
if (info->rx_skb == NULL) { if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0; info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
...@@ -628,9 +628,6 @@ static int bluecard_hci_open(struct hci_dev *hdev) ...@@ -628,9 +628,6 @@ static int bluecard_hci_open(struct hci_dev *hdev)
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
if (test_and_set_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
unsigned int iobase = info->p_dev->resource[0]->start; unsigned int iobase = info->p_dev->resource[0]->start;
...@@ -646,9 +643,6 @@ static int bluecard_hci_close(struct hci_dev *hdev) ...@@ -646,9 +643,6 @@ static int bluecard_hci_close(struct hci_dev *hdev)
{ {
struct bluecard_info *info = hci_get_drvdata(hdev); struct bluecard_info *info = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
bluecard_hci_flush(hdev); bluecard_hci_flush(hdev);
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
......
...@@ -35,7 +35,9 @@ ...@@ -35,7 +35,9 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#define VERSION "0.10" #include "hci_uart.h"
#define VERSION "0.11"
static const struct usb_device_id bpa10x_table[] = { static const struct usb_device_id bpa10x_table[] = {
/* Tektronix BPA 100/105 (Digianswer) */ /* Tektronix BPA 100/105 (Digianswer) */
...@@ -56,112 +58,6 @@ struct bpa10x_data { ...@@ -56,112 +58,6 @@ struct bpa10x_data {
struct sk_buff *rx_skb[2]; struct sk_buff *rx_skb[2];
}; };
#define HCI_VENDOR_HDR_SIZE 5
struct hci_vendor_hdr {
__u8 type;
__le16 snum;
__le16 dlen;
} __packed;
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
{
struct bpa10x_data *data = hci_get_drvdata(hdev);
BT_DBG("%s queue %d buffer %p count %d", hdev->name,
queue, buf, count);
if (queue < 0 || queue > 1)
return -EILSEQ;
hdev->stat.byte_rx += count;
while (count) {
struct sk_buff *skb = data->rx_skb[queue];
struct { __u8 type; int expect; } *scb;
int type, len = 0;
if (!skb) {
/* Start of the frame */
type = *((__u8 *) buf);
count--; buf++;
switch (type) {
case HCI_EVENT_PKT:
if (count >= HCI_EVENT_HDR_SIZE) {
struct hci_event_hdr *h = buf;
len = HCI_EVENT_HDR_SIZE + h->plen;
} else
return -EILSEQ;
break;
case HCI_ACLDATA_PKT:
if (count >= HCI_ACL_HDR_SIZE) {
struct hci_acl_hdr *h = buf;
len = HCI_ACL_HDR_SIZE +
__le16_to_cpu(h->dlen);
} else
return -EILSEQ;
break;
case HCI_SCODATA_PKT:
if (count >= HCI_SCO_HDR_SIZE) {
struct hci_sco_hdr *h = buf;
len = HCI_SCO_HDR_SIZE + h->dlen;
} else
return -EILSEQ;
break;
case HCI_VENDOR_PKT:
if (count >= HCI_VENDOR_HDR_SIZE) {
struct hci_vendor_hdr *h = buf;
len = HCI_VENDOR_HDR_SIZE +
__le16_to_cpu(h->dlen);
} else
return -EILSEQ;
break;
}
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
BT_ERR("%s no memory for packet", hdev->name);
return -ENOMEM;
}
data->rx_skb[queue] = skb;
scb = (void *) skb->cb;
scb->type = type;
scb->expect = len;
} else {
/* Continuation */
scb = (void *) skb->cb;
len = scb->expect;
}
len = min(len, count);
memcpy(skb_put(skb, len), buf, len);
scb->expect -= len;
if (scb->expect == 0) {
/* Complete frame */
data->rx_skb[queue] = NULL;
bt_cb(skb)->pkt_type = scb->type;
hci_recv_frame(hdev, skb);
}
count -= len; buf += len;
}
return 0;
}
static void bpa10x_tx_complete(struct urb *urb) static void bpa10x_tx_complete(struct urb *urb)
{ {
struct sk_buff *skb = urb->context; struct sk_buff *skb = urb->context;
...@@ -184,6 +80,22 @@ static void bpa10x_tx_complete(struct urb *urb) ...@@ -184,6 +80,22 @@ static void bpa10x_tx_complete(struct urb *urb)
kfree_skb(skb); kfree_skb(skb);
} }
#define HCI_VENDOR_HDR_SIZE 5
#define HCI_RECV_VENDOR \
.type = HCI_VENDOR_PKT, \
.hlen = HCI_VENDOR_HDR_SIZE, \
.loff = 3, \
.lsize = 2, \
.maxlen = HCI_MAX_FRAME_SIZE
static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ HCI_RECV_VENDOR, .recv = hci_recv_diag },
};
static void bpa10x_rx_complete(struct urb *urb) static void bpa10x_rx_complete(struct urb *urb)
{ {
struct hci_dev *hdev = urb->context; struct hci_dev *hdev = urb->context;
...@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb) ...@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb)
return; return;
if (urb->status == 0) { if (urb->status == 0) {
if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe), bool idx = usb_pipebulk(urb->pipe);
data->rx_skb[idx] = h4_recv_buf(hdev, data->rx_skb[idx],
urb->transfer_buffer, urb->transfer_buffer,
urb->actual_length) < 0) { urb->actual_length,
bpa10x_recv_pkts,
ARRAY_SIZE(bpa10x_recv_pkts));
if (IS_ERR(data->rx_skb[idx])) {
BT_ERR("%s corrupted event packet", hdev->name); BT_ERR("%s corrupted event packet", hdev->name);
hdev->stat.err_rx++; hdev->stat.err_rx++;
data->rx_skb[idx] = NULL;
} }
} }
...@@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev) ...@@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
err = bpa10x_submit_intr_urb(hdev); err = bpa10x_submit_intr_urb(hdev);
if (err < 0) if (err < 0)
goto error; goto error;
...@@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev) ...@@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev)
error: error:
usb_kill_anchored_urbs(&data->rx_anchor); usb_kill_anchored_urbs(&data->rx_anchor);
clear_bit(HCI_RUNNING, &hdev->flags);
return err; return err;
} }
...@@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev) ...@@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
usb_kill_anchored_urbs(&data->rx_anchor); usb_kill_anchored_urbs(&data->rx_anchor);
return 0; return 0;
...@@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev) ...@@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev)
return 0; return 0;
} }
static int bpa10x_setup(struct hci_dev *hdev)
{
const u8 req[] = { 0x07 };
struct sk_buff *skb;
BT_DBG("%s", hdev->name);
/* Read revision string */
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
return 0;
}
static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct bpa10x_data *data = hci_get_drvdata(hdev); struct bpa10x_data *data = hci_get_drvdata(hdev);
...@@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
skb->dev = (void *) hdev; skb->dev = (void *) hdev;
urb = usb_alloc_urb(0, GFP_ATOMIC); urb = usb_alloc_urb(0, GFP_ATOMIC);
...@@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0; return 0;
} }
static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
{
const u8 req[] = { 0x00, enable };
struct sk_buff *skb;
BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -ENETDOWN;
/* Enable sniffer operation */
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
kfree_skb(skb);
return 0;
}
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id) static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
{ {
struct bpa10x_data *data; struct bpa10x_data *data;
...@@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * ...@@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
hdev->open = bpa10x_open; hdev->open = bpa10x_open;
hdev->close = bpa10x_close; hdev->close = bpa10x_close;
hdev->flush = bpa10x_flush; hdev->flush = bpa10x_flush;
hdev->setup = bpa10x_setup;
hdev->send = bpa10x_send_frame; hdev->send = bpa10x_send_frame;
hdev->set_diag = bpa10x_set_diag;
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
......
...@@ -233,7 +233,7 @@ static void bt3c_receive(struct bt3c_info *info) ...@@ -233,7 +233,7 @@ static void bt3c_receive(struct bt3c_info *info)
info->hdev->stat.byte_rx++; info->hdev->stat.byte_rx++;
/* Allocate packet */ /* Allocate packet */
if (info->rx_skb == NULL) { if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0; info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
...@@ -270,7 +270,6 @@ static void bt3c_receive(struct bt3c_info *info) ...@@ -270,7 +270,6 @@ static void bt3c_receive(struct bt3c_info *info)
/* Unknown packet */ /* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type); BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++; info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
kfree_skb(info->rx_skb); kfree_skb(info->rx_skb);
info->rx_skb = NULL; info->rx_skb = NULL;
...@@ -395,17 +394,12 @@ static int bt3c_hci_flush(struct hci_dev *hdev) ...@@ -395,17 +394,12 @@ static int bt3c_hci_flush(struct hci_dev *hdev)
static int bt3c_hci_open(struct hci_dev *hdev) static int bt3c_hci_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &(hdev->flags));
return 0; return 0;
} }
static int bt3c_hci_close(struct hci_dev *hdev) static int bt3c_hci_close(struct hci_dev *hdev)
{ {
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
bt3c_hci_flush(hdev); bt3c_hci_flush(hdev);
return 0; return 0;
......
...@@ -181,6 +181,27 @@ static int btbcm_reset(struct hci_dev *hdev) ...@@ -181,6 +181,27 @@ static int btbcm_reset(struct hci_dev *hdev)
return 0; return 0;
} }
static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev)
{
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Reading local name failed (%ld)",
hdev->name, PTR_ERR(skb));
return skb;
}
if (skb->len != sizeof(struct hci_rp_read_local_name)) {
BT_ERR("%s: BCM: Local name length mismatch", hdev->name);
kfree_skb(skb);
return ERR_PTR(-EIO);
}
return skb;
}
static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev) static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -393,6 +414,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev) ...@@ -393,6 +414,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
kfree_skb(skb); kfree_skb(skb);
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
switch ((rev & 0xf000) >> 12) { switch ((rev & 0xf000) >> 12) {
case 0: case 0:
case 3: case 3:
...@@ -464,6 +493,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev) ...@@ -464,6 +493,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
hw_name ? : "BCM", (subver & 0x7000) >> 13, hw_name ? : "BCM", (subver & 0x7000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
btbcm_check_bdaddr(hdev); btbcm_check_bdaddr(hdev);
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
...@@ -475,12 +512,25 @@ EXPORT_SYMBOL_GPL(btbcm_setup_patchram); ...@@ -475,12 +512,25 @@ EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
int btbcm_setup_apple(struct hci_dev *hdev) int btbcm_setup_apple(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err;
/* Reset */
err = btbcm_reset(hdev);
if (err)
return err;
/* Read Verbose Config Version Info */ /* Read Verbose Config Version Info */
skb = btbcm_read_verbose_config(hdev); skb = btbcm_read_verbose_config(hdev);
if (!IS_ERR(skb)) { if (!IS_ERR(skb)) {
BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name,
get_unaligned_le16(skb->data + 5)); skb->data[1], get_unaligned_le16(skb->data + 5));
kfree_skb(skb);
}
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (!IS_ERR(skb)) {
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb); kfree_skb(skb);
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/regmap.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -215,6 +216,201 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) ...@@ -215,6 +216,201 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)
} }
EXPORT_SYMBOL_GPL(btintel_load_ddc_config); EXPORT_SYMBOL_GPL(btintel_load_ddc_config);
/* ------- REGMAP IBT SUPPORT ------- */
#define IBT_REG_MODE_8BIT 0x00
#define IBT_REG_MODE_16BIT 0x01
#define IBT_REG_MODE_32BIT 0x02
struct regmap_ibt_context {
struct hci_dev *hdev;
__u16 op_write;
__u16 op_read;
};
struct ibt_cp_reg_access {
__le32 addr;
__u8 mode;
__u8 len;
__u8 data[0];
} __packed;
struct ibt_rp_reg_access {
__u8 status;
__le32 addr;
__u8 data[0];
} __packed;
static int regmap_ibt_read(void *context, const void *addr, size_t reg_size,
void *val, size_t val_size)
{
struct regmap_ibt_context *ctx = context;
struct ibt_cp_reg_access cp;
struct ibt_rp_reg_access *rp;
struct sk_buff *skb;
int err = 0;
if (reg_size != sizeof(__le32))
return -EINVAL;
switch (val_size) {
case 1:
cp.mode = IBT_REG_MODE_8BIT;
break;
case 2:
cp.mode = IBT_REG_MODE_16BIT;
break;
case 4:
cp.mode = IBT_REG_MODE_32BIT;
break;
default:
return -EINVAL;
}
/* regmap provides a little-endian formatted addr */
cp.addr = *(__le32 *)addr;
cp.len = val_size;
bt_dev_dbg(ctx->hdev, "Register (0x%x) read", le32_to_cpu(cp.addr));
skb = hci_cmd_sync(ctx->hdev, ctx->op_read, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error (%d)",
le32_to_cpu(cp.addr), err);
return err;
}
if (skb->len != sizeof(*rp) + val_size) {
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad len",
le32_to_cpu(cp.addr));
err = -EINVAL;
goto done;
}
rp = (struct ibt_rp_reg_access *)skb->data;
if (rp->addr != cp.addr) {
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad addr",
le32_to_cpu(rp->addr));
err = -EINVAL;
goto done;
}
memcpy(val, rp->data, val_size);
done:
kfree_skb(skb);
return err;
}
static int regmap_ibt_gather_write(void *context,
const void *addr, size_t reg_size,
const void *val, size_t val_size)
{
struct regmap_ibt_context *ctx = context;
struct ibt_cp_reg_access *cp;
struct sk_buff *skb;
int plen = sizeof(*cp) + val_size;
u8 mode;
int err = 0;
if (reg_size != sizeof(__le32))
return -EINVAL;
switch (val_size) {
case 1:
mode = IBT_REG_MODE_8BIT;
break;
case 2:
mode = IBT_REG_MODE_16BIT;
break;
case 4:
mode = IBT_REG_MODE_32BIT;
break;
default:
return -EINVAL;
}
cp = kmalloc(plen, GFP_KERNEL);
if (!cp)
return -ENOMEM;
/* regmap provides a little-endian formatted addr/value */
cp->addr = *(__le32 *)addr;
cp->mode = mode;
cp->len = val_size;
memcpy(&cp->data, val, val_size);
bt_dev_dbg(ctx->hdev, "Register (0x%x) write", le32_to_cpu(cp->addr));
skb = hci_cmd_sync(ctx->hdev, ctx->op_write, plen, cp, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) write error (%d)",
le32_to_cpu(cp->addr), err);
goto done;
}
kfree_skb(skb);
done:
kfree(cp);
return err;
}
static int regmap_ibt_write(void *context, const void *data, size_t count)
{
/* data contains register+value, since we only support 32bit addr,
* minimum data size is 4 bytes.
*/
if (WARN_ONCE(count < 4, "Invalid register access"))
return -EINVAL;
return regmap_ibt_gather_write(context, data, 4, data + 4, count - 4);
}
static void regmap_ibt_free_context(void *context)
{
kfree(context);
}
static struct regmap_bus regmap_ibt = {
.read = regmap_ibt_read,
.write = regmap_ibt_write,
.gather_write = regmap_ibt_gather_write,
.free_context = regmap_ibt_free_context,
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
};
/* Config is the same for all register regions */
static const struct regmap_config regmap_ibt_cfg = {
.name = "btintel_regmap",
.reg_bits = 32,
.val_bits = 32,
};
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write)
{
struct regmap_ibt_context *ctx;
bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read,
opcode_write);
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
ctx->op_read = opcode_read;
ctx->op_write = opcode_write;
ctx->hdev = hdev;
return regmap_init(&hdev->dev, &regmap_ibt, ctx, &regmap_ibt_cfg);
}
EXPORT_SYMBOL_GPL(btintel_regmap_init);
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
......
...@@ -80,6 +80,9 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, ...@@ -80,6 +80,9 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param); const void *param);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name); int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write);
#else #else
static inline int btintel_check_bdaddr(struct hci_dev *hdev) static inline int btintel_check_bdaddr(struct hci_dev *hdev)
...@@ -113,4 +116,10 @@ static inline int btintel_load_ddc_config(struct hci_dev *hdev, ...@@ -113,4 +116,10 @@ static inline int btintel_load_ddc_config(struct hci_dev *hdev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
u16 opcode_read,
u16 opcode_write)
{
return ERR_PTR(-EINVAL);
}
#endif #endif
...@@ -184,7 +184,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, ...@@ -184,7 +184,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
} }
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC); skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
if (skb == NULL) { if (!skb) {
BT_ERR("No free skb"); BT_ERR("No free skb");
return -ENOMEM; return -ENOMEM;
} }
...@@ -436,13 +436,6 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -436,13 +436,6 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
skb->data, skb->len);
return -EBUSY;
}
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++; hdev->stat.cmd_tx++;
...@@ -477,9 +470,6 @@ static int btmrvl_close(struct hci_dev *hdev) ...@@ -477,9 +470,6 @@ static int btmrvl_close(struct hci_dev *hdev)
{ {
struct btmrvl_private *priv = hci_get_drvdata(hdev); struct btmrvl_private *priv = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
skb_queue_purge(&priv->adapter->tx_queue); skb_queue_purge(&priv->adapter->tx_queue);
return 0; return 0;
...@@ -487,8 +477,6 @@ static int btmrvl_close(struct hci_dev *hdev) ...@@ -487,8 +477,6 @@ static int btmrvl_close(struct hci_dev *hdev)
static int btmrvl_open(struct hci_dev *hdev) static int btmrvl_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &hdev->flags);
return 0; return 0;
} }
......
...@@ -146,6 +146,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = { ...@@ -146,6 +146,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
.fw_dump_end = 0xea, .fw_dump_end = 0xea,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
.cfg = 0x00,
.host_int_mask = 0x08,
.host_intstatus = 0x0c,
.card_status = 0x5c,
.sq_read_base_addr_a0 = 0xf8,
.sq_read_base_addr_a1 = 0xf9,
.card_revision = 0xc8,
.card_fw_status0 = 0xe8,
.card_fw_status1 = 0xe9,
.card_rx_len = 0xea,
.card_rx_unit = 0xeb,
.io_port_0 = 0xe4,
.io_port_1 = 0xe5,
.io_port_2 = 0xe6,
.int_read_to_clear = true,
.host_int_rsr = 0x04,
.card_misc_cfg = 0xD8,
.fw_dump_ctrl = 0xf0,
.fw_dump_start = 0xf1,
.fw_dump_end = 0xf8,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin", .helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin", .firmware = "mrvl/sd8688.bin",
...@@ -191,25 +214,37 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { ...@@ -191,25 +214,37 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.supports_fw_dump = true, .supports_fw_dump = true,
}; };
static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
.helper = NULL,
.firmware = "mrvl/sd8997_uapsta.bin",
.reg = &btmrvl_reg_8997,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
.supports_fw_dump = true,
};
static const struct sdio_device_id btmrvl_sdio_ids[] = { static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8688 Bluetooth device */ /* Marvell SD8688 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
.driver_data = (unsigned long) &btmrvl_sdio_sd8688 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
/* Marvell SD8787 Bluetooth device */ /* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
/* Marvell SD8787 Bluetooth AMP device */ /* Marvell SD8787 Bluetooth AMP device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
/* Marvell SD8797 Bluetooth device */ /* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
/* Marvell SD8887 Bluetooth device */ /* Marvell SD8887 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
.driver_data = (unsigned long)&btmrvl_sdio_sd8887 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
/* Marvell SD8897 Bluetooth device */ /* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
.driver_data = (unsigned long) &btmrvl_sdio_sd8897 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
/* Marvell SD8997 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
.driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -619,7 +654,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) ...@@ -619,7 +654,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
/* Allocate buffer */ /* Allocate buffer */
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
if (skb == NULL) { if (!skb) {
BT_ERR("No free skb"); BT_ERR("No free skb");
ret = -ENOMEM; ret = -ENOMEM;
goto exit; goto exit;
...@@ -1278,6 +1313,12 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv) ...@@ -1278,6 +1313,12 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
if (memory_size == 0) { if (memory_size == 0) {
BT_INFO("Firmware dump finished!"); BT_INFO("Firmware dump finished!");
sdio_writeb(card->func, FW_DUMP_READ_DONE,
card->reg->fw_dump_ctrl, &ret);
if (ret) {
BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
goto done;
}
break; break;
} }
...@@ -1616,3 +1657,4 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); ...@@ -1616,3 +1657,4 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");
...@@ -194,21 +194,15 @@ static int btsdio_open(struct hci_dev *hdev) ...@@ -194,21 +194,15 @@ static int btsdio_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
sdio_claim_host(data->func); sdio_claim_host(data->func);
err = sdio_enable_func(data->func); err = sdio_enable_func(data->func);
if (err < 0) { if (err < 0)
clear_bit(HCI_RUNNING, &hdev->flags);
goto release; goto release;
}
err = sdio_claim_irq(data->func, btsdio_interrupt); err = sdio_claim_irq(data->func, btsdio_interrupt);
if (err < 0) { if (err < 0) {
sdio_disable_func(data->func); sdio_disable_func(data->func);
clear_bit(HCI_RUNNING, &hdev->flags);
goto release; goto release;
} }
...@@ -229,9 +223,6 @@ static int btsdio_close(struct hci_dev *hdev) ...@@ -229,9 +223,6 @@ static int btsdio_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
sdio_claim_host(data->func); sdio_claim_host(data->func);
sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL); sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL);
...@@ -261,9 +252,6 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -261,9 +252,6 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++; hdev->stat.cmd_tx++;
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/io.h> #include <linux/io.h>
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h> #include <pcmcia/ciscode.h>
...@@ -188,7 +188,7 @@ static void btuart_receive(struct btuart_info *info) ...@@ -188,7 +188,7 @@ static void btuart_receive(struct btuart_info *info)
info->hdev->stat.byte_rx++; info->hdev->stat.byte_rx++;
/* Allocate packet */ /* Allocate packet */
if (info->rx_skb == NULL) { if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0; info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
...@@ -223,7 +223,6 @@ static void btuart_receive(struct btuart_info *info) ...@@ -223,7 +223,6 @@ static void btuart_receive(struct btuart_info *info)
/* Unknown packet */ /* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type); BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++; info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
kfree_skb(info->rx_skb); kfree_skb(info->rx_skb);
info->rx_skb = NULL; info->rx_skb = NULL;
...@@ -409,17 +408,12 @@ static int btuart_hci_flush(struct hci_dev *hdev) ...@@ -409,17 +408,12 @@ static int btuart_hci_flush(struct hci_dev *hdev)
static int btuart_hci_open(struct hci_dev *hdev) static int btuart_hci_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &(hdev->flags));
return 0; return 0;
} }
static int btuart_hci_close(struct hci_dev *hdev) static int btuart_hci_close(struct hci_dev *hdev)
{ {
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
btuart_hci_flush(hdev); btuart_hci_flush(hdev);
return 0; return 0;
......
...@@ -940,9 +940,6 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -940,9 +940,6 @@ static int btusb_open(struct hci_dev *hdev)
data->intf->needs_remote_wakeup = 1; data->intf->needs_remote_wakeup = 1;
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
goto done;
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
goto done; goto done;
...@@ -965,7 +962,6 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -965,7 +962,6 @@ static int btusb_open(struct hci_dev *hdev)
failed: failed:
clear_bit(BTUSB_INTR_RUNNING, &data->flags); clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
usb_autopm_put_interface(data->intf); usb_autopm_put_interface(data->intf);
return err; return err;
} }
...@@ -984,9 +980,6 @@ static int btusb_close(struct hci_dev *hdev) ...@@ -984,9 +980,6 @@ static int btusb_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
cancel_work_sync(&data->work); cancel_work_sync(&data->work);
cancel_work_sync(&data->waker); cancel_work_sync(&data->waker);
...@@ -1156,9 +1149,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1156,9 +1149,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
urb = alloc_ctrl_urb(hdev, skb); urb = alloc_ctrl_urb(hdev, skb);
...@@ -1843,9 +1833,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1843,9 +1833,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
......
...@@ -155,9 +155,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -155,9 +155,6 @@ static int ti_st_open(struct hci_dev *hdev)
BT_DBG("%s %p", hdev->name, hdev); BT_DBG("%s %p", hdev->name, hdev);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
/* provide contexts for callbacks from ST */ /* provide contexts for callbacks from ST */
hst = hci_get_drvdata(hdev); hst = hci_get_drvdata(hdev);
...@@ -181,7 +178,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -181,7 +178,6 @@ static int ti_st_open(struct hci_dev *hdev)
goto done; goto done;
if (err != -EINPROGRESS) { if (err != -EINPROGRESS) {
clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("st_register failed %d", err); BT_ERR("st_register failed %d", err);
return err; return err;
} }
...@@ -195,7 +191,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -195,7 +191,6 @@ static int ti_st_open(struct hci_dev *hdev)
(&hst->wait_reg_completion, (&hst->wait_reg_completion,
msecs_to_jiffies(BT_REGISTER_TIMEOUT)); msecs_to_jiffies(BT_REGISTER_TIMEOUT));
if (!timeleft) { if (!timeleft) {
clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("Timeout(%d sec),didn't get reg " BT_ERR("Timeout(%d sec),didn't get reg "
"completion signal from ST", "completion signal from ST",
BT_REGISTER_TIMEOUT / 1000); BT_REGISTER_TIMEOUT / 1000);
...@@ -205,7 +200,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -205,7 +200,6 @@ static int ti_st_open(struct hci_dev *hdev)
/* Is ST registration callback /* Is ST registration callback
* called with ERROR status? */ * called with ERROR status? */
if (hst->reg_status != 0) { if (hst->reg_status != 0) {
clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("ST registration completed with invalid " BT_ERR("ST registration completed with invalid "
"status %d", hst->reg_status); "status %d", hst->reg_status);
return -EAGAIN; return -EAGAIN;
...@@ -215,7 +209,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -215,7 +209,6 @@ static int ti_st_open(struct hci_dev *hdev)
hst->st_write = ti_st_proto[i].write; hst->st_write = ti_st_proto[i].write;
if (!hst->st_write) { if (!hst->st_write) {
BT_ERR("undefined ST write function"); BT_ERR("undefined ST write function");
clear_bit(HCI_RUNNING, &hdev->flags);
for (i = 0; i < MAX_BT_CHNL_IDS; i++) { for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
/* Undo registration with ST */ /* Undo registration with ST */
err = st_unregister(&ti_st_proto[i]); err = st_unregister(&ti_st_proto[i]);
...@@ -236,9 +229,6 @@ static int ti_st_close(struct hci_dev *hdev) ...@@ -236,9 +229,6 @@ static int ti_st_close(struct hci_dev *hdev)
int err, i; int err, i;
struct ti_st *hst = hci_get_drvdata(hdev); struct ti_st *hst = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) { for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {
err = st_unregister(&ti_st_proto[i]); err = st_unregister(&ti_st_proto[i]);
if (err) if (err)
...@@ -256,9 +246,6 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -256,9 +246,6 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct ti_st *hst; struct ti_st *hst;
long len; long len;
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
hst = hci_get_drvdata(hdev); hst = hci_get_drvdata(hdev);
/* Prepend skb with frame type */ /* Prepend skb with frame type */
......
...@@ -357,8 +357,6 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) ...@@ -357,8 +357,6 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
static int dtl1_hci_open(struct hci_dev *hdev) static int dtl1_hci_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &(hdev->flags));
return 0; return 0;
} }
...@@ -376,9 +374,6 @@ static int dtl1_hci_flush(struct hci_dev *hdev) ...@@ -376,9 +374,6 @@ static int dtl1_hci_flush(struct hci_dev *hdev)
static int dtl1_hci_close(struct hci_dev *hdev) static int dtl1_hci_close(struct hci_dev *hdev)
{ {
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
dtl1_hci_flush(hdev); dtl1_hci_flush(hdev);
return 0; return 0;
......
This diff is collapsed.
...@@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, ...@@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
return skb; return skb;
} }
EXPORT_SYMBOL_GPL(h4_recv_buf);
...@@ -128,7 +128,7 @@ static void h5_timed_event(unsigned long arg) ...@@ -128,7 +128,7 @@ static void h5_timed_event(unsigned long arg)
{ {
const unsigned char sync_req[] = { 0x01, 0x7e }; const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
struct hci_uart *hu = (struct hci_uart *) arg; struct hci_uart *hu = (struct hci_uart *)arg;
struct h5 *h5 = hu->priv; struct h5 *h5 = hu->priv;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags; unsigned long flags;
...@@ -210,7 +210,7 @@ static int h5_open(struct hci_uart *hu) ...@@ -210,7 +210,7 @@ static int h5_open(struct hci_uart *hu)
init_timer(&h5->timer); init_timer(&h5->timer);
h5->timer.function = h5_timed_event; h5->timer.function = h5_timed_event;
h5->timer.data = (unsigned long) hu; h5->timer.data = (unsigned long)hu;
h5->tx_win = H5_TX_WIN_MAX; h5->tx_win = H5_TX_WIN_MAX;
...@@ -453,7 +453,7 @@ static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c) ...@@ -453,7 +453,7 @@ static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c)
return -ENOMEM; return -ENOMEM;
} }
h5->rx_skb->dev = (void *) hu->hdev; h5->rx_skb->dev = (void *)hu->hdev;
return 0; return 0;
} }
...@@ -696,7 +696,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) ...@@ -696,7 +696,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
} }
skb = skb_dequeue(&h5->unrel); skb = skb_dequeue(&h5->unrel);
if (skb != NULL) { if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len); skb->data, skb->len);
if (nskb) { if (nskb) {
...@@ -714,7 +714,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) ...@@ -714,7 +714,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
goto unlock; goto unlock;
skb = skb_dequeue(&h5->rel); skb = skb_dequeue(&h5->rel);
if (skb != NULL) { if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len); skb->data, skb->len);
if (nskb) { if (nskb) {
......
...@@ -1165,22 +1165,6 @@ static const struct acpi_device_id intel_acpi_match[] = { ...@@ -1165,22 +1165,6 @@ static const struct acpi_device_id intel_acpi_match[] = {
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, intel_acpi_match); MODULE_DEVICE_TABLE(acpi, intel_acpi_match);
static int intel_acpi_probe(struct intel_device *idev)
{
const struct acpi_device_id *id;
id = acpi_match_device(intel_acpi_match, &idev->pdev->dev);
if (!id)
return -ENODEV;
return 0;
}
#else
static int intel_acpi_probe(struct intel_device *idev)
{
return -ENODEV;
}
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -1248,14 +1232,6 @@ static int intel_probe(struct platform_device *pdev) ...@@ -1248,14 +1232,6 @@ static int intel_probe(struct platform_device *pdev)
idev->pdev = pdev; idev->pdev = pdev;
if (ACPI_HANDLE(&pdev->dev)) {
int err = intel_acpi_probe(idev);
if (err)
return err;
} else {
return -ENODEV;
}
idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset", idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(idev->reset)) { if (IS_ERR(idev->reset)) {
......
...@@ -208,9 +208,6 @@ static int hci_uart_open(struct hci_dev *hdev) ...@@ -208,9 +208,6 @@ static int hci_uart_open(struct hci_dev *hdev)
BT_DBG("%s %p", hdev->name, hdev); BT_DBG("%s %p", hdev->name, hdev);
/* Nothing to do for UART driver */ /* Nothing to do for UART driver */
set_bit(HCI_RUNNING, &hdev->flags);
return 0; return 0;
} }
...@@ -241,9 +238,6 @@ static int hci_uart_close(struct hci_dev *hdev) ...@@ -241,9 +238,6 @@ static int hci_uart_close(struct hci_dev *hdev)
{ {
BT_DBG("hdev %p", hdev); BT_DBG("hdev %p", hdev);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
hci_uart_flush(hdev); hci_uart_flush(hdev);
hdev->flush = NULL; hdev->flush = NULL;
return 0; return 0;
...@@ -254,9 +248,6 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -254,9 +248,6 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_uart *hu = hci_get_drvdata(hdev);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
hu->proto->enqueue(hu, skb); hu->proto->enqueue(hu, skb);
...@@ -470,8 +461,6 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -470,8 +461,6 @@ static int hci_uart_tty_open(struct tty_struct *tty)
INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->init_ready, hci_uart_init_work);
INIT_WORK(&hu->write_work, hci_uart_write_work); INIT_WORK(&hu->write_work, hci_uart_write_work);
spin_lock_init(&hu->rx_lock);
/* Flush any pending characters in the driver and line discipline. */ /* Flush any pending characters in the driver and line discipline. */
/* FIXME: why is this needed. Note don't use ldisc_ref here as the /* FIXME: why is this needed. Note don't use ldisc_ref here as the
...@@ -569,14 +558,14 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, ...@@ -569,14 +558,14 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
return; return;
spin_lock(&hu->rx_lock); /* It does not need a lock here as it is already protected by a mutex in
* tty caller
*/
hu->proto->recv(hu, data, count); hu->proto->recv(hu, data, count);
if (hu->hdev) if (hu->hdev)
hu->hdev->stat.byte_rx += count; hu->hdev->stat.byte_rx += count;
spin_unlock(&hu->rx_lock);
tty_unthrottle(tty); tty_unthrottle(tty);
} }
......
...@@ -347,7 +347,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg) ...@@ -347,7 +347,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
struct hci_uart *hu = (struct hci_uart *)arg; struct hci_uart *hu = (struct hci_uart *)arg;
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
unsigned long flags, retrans_delay; unsigned long flags, retrans_delay;
unsigned long retransmit = 0; bool retransmit = false;
BT_DBG("hu %p wake retransmit timeout in %d state", BT_DBG("hu %p wake retransmit timeout in %d state",
hu, qca->tx_ibs_state); hu, qca->tx_ibs_state);
...@@ -358,7 +358,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg) ...@@ -358,7 +358,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
switch (qca->tx_ibs_state) { switch (qca->tx_ibs_state) {
case HCI_IBS_TX_WAKING: case HCI_IBS_TX_WAKING:
/* No WAKE_ACK, retransmit WAKE */ /* No WAKE_ACK, retransmit WAKE */
retransmit = 1; retransmit = true;
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) { if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
BT_ERR("Failed to acknowledge device wake up"); BT_ERR("Failed to acknowledge device wake up");
break; break;
......
...@@ -85,7 +85,6 @@ struct hci_uart { ...@@ -85,7 +85,6 @@ struct hci_uart {
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
unsigned long tx_state; unsigned long tx_state;
spinlock_t rx_lock;
unsigned int init_speed; unsigned int init_speed;
unsigned int oper_speed; unsigned int oper_speed;
......
...@@ -55,8 +55,6 @@ struct vhci_data { ...@@ -55,8 +55,6 @@ struct vhci_data {
static int vhci_open_dev(struct hci_dev *hdev) static int vhci_open_dev(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &hdev->flags);
return 0; return 0;
} }
...@@ -64,9 +62,6 @@ static int vhci_close_dev(struct hci_dev *hdev) ...@@ -64,9 +62,6 @@ static int vhci_close_dev(struct hci_dev *hdev)
{ {
struct vhci_data *data = hci_get_drvdata(hdev); struct vhci_data *data = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
skb_queue_purge(&data->readq); skb_queue_purge(&data->readq);
return 0; return 0;
...@@ -85,9 +80,6 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -85,9 +80,6 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct vhci_data *data = hci_get_drvdata(hdev); struct vhci_data *data = hci_get_drvdata(hdev);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&data->readq, skb); skb_queue_tail(&data->readq, skb);
......
...@@ -43,6 +43,7 @@ config IEEE802154_MRF24J40 ...@@ -43,6 +43,7 @@ config IEEE802154_MRF24J40
tristate "Microchip MRF24J40 transceiver driver" tristate "Microchip MRF24J40 transceiver driver"
depends on IEEE802154_DRIVERS && MAC802154 depends on IEEE802154_DRIVERS && MAC802154
depends on SPI depends on SPI
select REGMAP_SPI
---help--- ---help---
Say Y here to enable the MRF24J20 SPI 802.15.4 wireless Say Y here to enable the MRF24J20 SPI 802.15.4 wireless
controller. controller.
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,12 +25,22 @@ ...@@ -25,12 +25,22 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/random.h> #include <linux/random.h>
#include <asm/byteorder.h>
#define IEEE802154_MTU 127 #define IEEE802154_MTU 127
#define IEEE802154_ACK_PSDU_LEN 5 #define IEEE802154_ACK_PSDU_LEN 5
#define IEEE802154_MIN_PSDU_LEN 9 #define IEEE802154_MIN_PSDU_LEN 9
#define IEEE802154_FCS_LEN 2 #define IEEE802154_FCS_LEN 2
#define IEEE802154_MAX_AUTH_TAG_LEN 16
/* General MAC frame format:
* 2 bytes: Frame Control
* 1 byte: Sequence Number
* 20 bytes: Addressing fields
* 14 bytes: Auxiliary Security Header
*/
#define IEEE802154_MAX_HEADER_LEN (2 + 1 + 20 + 14)
#define IEEE802154_MIN_HEADER_LEN (IEEE802154_ACK_PSDU_LEN - \
IEEE802154_FCS_LEN)
#define IEEE802154_PAN_ID_BROADCAST 0xffff #define IEEE802154_PAN_ID_BROADCAST 0xffff
#define IEEE802154_ADDR_SHORT_BROADCAST 0xffff #define IEEE802154_ADDR_SHORT_BROADCAST 0xffff
...@@ -207,6 +217,7 @@ enum { ...@@ -207,6 +217,7 @@ enum {
/* frame control handling */ /* frame control handling */
#define IEEE802154_FCTL_FTYPE 0x0003 #define IEEE802154_FCTL_FTYPE 0x0003
#define IEEE802154_FCTL_ACKREQ 0x0020
#define IEEE802154_FCTL_INTRA_PAN 0x0040 #define IEEE802154_FCTL_INTRA_PAN 0x0040
#define IEEE802154_FTYPE_DATA 0x0001 #define IEEE802154_FTYPE_DATA 0x0001
...@@ -221,6 +232,15 @@ static inline int ieee802154_is_data(__le16 fc) ...@@ -221,6 +232,15 @@ static inline int ieee802154_is_data(__le16 fc)
cpu_to_le16(IEEE802154_FTYPE_DATA); cpu_to_le16(IEEE802154_FTYPE_DATA);
} }
/**
* ieee802154_is_ackreq - check if acknowledgment request bit is set
* @fc: frame control bytes in little-endian byteorder
*/
static inline bool ieee802154_is_ackreq(__le16 fc)
{
return fc & cpu_to_le16(IEEE802154_FCTL_ACKREQ);
}
/** /**
* ieee802154_is_intra_pan - check if intra pan id communication * ieee802154_is_intra_pan - check if intra pan id communication
* @fc: frame control bytes in little-endian byteorder * @fc: frame control bytes in little-endian byteorder
......
...@@ -61,6 +61,16 @@ ...@@ -61,6 +61,16 @@
#define UIP_PROTO_UDP 17 /* ipv6 next header value for UDP */ #define UIP_PROTO_UDP 17 /* ipv6 next header value for UDP */
#define UIP_FRAGH_LEN 8 /* ipv6 fragment header size */ #define UIP_FRAGH_LEN 8 /* ipv6 fragment header size */
#define EUI64_ADDR_LEN 8
#define LOWPAN_NHC_MAX_ID_LEN 1
/* Max IPHC Header len without IPv6 hdr specific inline data.
* Useful for getting the "extra" bytes we need at worst case compression.
*
* LOWPAN_IPHC + CID + LOWPAN_NHC_MAX_ID_LEN
*/
#define LOWPAN_IPHC_MAX_HEADER_LEN (2 + 1 + LOWPAN_NHC_MAX_ID_LEN)
/* /*
* ipv6 address based on mac * ipv6 address based on mac
* second bit-flip (Universe/Local) is done according RFC2464 * second bit-flip (Universe/Local) is done according RFC2464
......
...@@ -122,11 +122,14 @@ struct bt_voice { ...@@ -122,11 +122,14 @@ struct bt_voice {
__printf(1, 2) __printf(1, 2)
void bt_info(const char *fmt, ...); void bt_info(const char *fmt, ...);
__printf(1, 2) __printf(1, 2)
void bt_warn(const char *fmt, ...);
__printf(1, 2)
void bt_err(const char *fmt, ...); void bt_err(const char *fmt, ...);
__printf(1, 2) __printf(1, 2)
void bt_err_ratelimited(const char *fmt, ...); void bt_err_ratelimited(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__) #define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
#define BT_WARN(fmt, ...) bt_warn(fmt "\n", ##__VA_ARGS__)
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__) #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__) #define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
...@@ -134,6 +137,8 @@ void bt_err_ratelimited(const char *fmt, ...); ...@@ -134,6 +137,8 @@ void bt_err_ratelimited(const char *fmt, ...);
#define bt_dev_info(hdev, fmt, ...) \ #define bt_dev_info(hdev, fmt, ...) \
BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__) BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_warn(hdev, fmt, ...) \
BT_WARN("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_err(hdev, fmt, ...) \ #define bt_dev_err(hdev, fmt, ...) \
BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__) BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_dbg(hdev, fmt, ...) \ #define bt_dev_dbg(hdev, fmt, ...) \
......
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#define HCI_DEV_DOWN 4 #define HCI_DEV_DOWN 4
#define HCI_DEV_SUSPEND 5 #define HCI_DEV_SUSPEND 5
#define HCI_DEV_RESUME 6 #define HCI_DEV_RESUME 6
#define HCI_DEV_OPEN 7
#define HCI_DEV_CLOSE 8
/* HCI notify events */ /* HCI notify events */
#define HCI_NOTIFY_CONN_ADD 1 #define HCI_NOTIFY_CONN_ADD 1
...@@ -238,6 +240,7 @@ enum { ...@@ -238,6 +240,7 @@ enum {
HCI_LE_SCAN_INTERRUPTED, HCI_LE_SCAN_INTERRUPTED,
HCI_DUT_MODE, HCI_DUT_MODE,
HCI_VENDOR_DIAG,
HCI_FORCE_BREDR_SMP, HCI_FORCE_BREDR_SMP,
HCI_FORCE_STATIC_ADDR, HCI_FORCE_STATIC_ADDR,
...@@ -260,6 +263,7 @@ enum { ...@@ -260,6 +263,7 @@ enum {
#define HCI_ACLDATA_PKT 0x02 #define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03 #define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04 #define HCI_EVENT_PKT 0x04
#define HCI_DIAG_PKT 0xf0
#define HCI_VENDOR_PKT 0xff #define HCI_VENDOR_PKT 0xff
/* HCI packet types */ /* HCI packet types */
......
...@@ -398,6 +398,7 @@ struct hci_dev { ...@@ -398,6 +398,7 @@ struct hci_dev {
int (*send)(struct hci_dev *hdev, struct sk_buff *skb); int (*send)(struct hci_dev *hdev, struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt); void (*notify)(struct hci_dev *hdev, unsigned int evt);
void (*hw_error)(struct hci_dev *hdev, u8 code); void (*hw_error)(struct hci_dev *hdev, u8 code);
int (*set_diag)(struct hci_dev *hdev, bool enable);
int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr); int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
}; };
...@@ -1066,6 +1067,7 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance); ...@@ -1066,6 +1067,7 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb);
void hci_init_sysfs(struct hci_dev *hdev); void hci_init_sysfs(struct hci_dev *hdev);
void hci_conn_init_sysfs(struct hci_conn *conn); void hci_conn_init_sysfs(struct hci_conn *conn);
...@@ -1349,6 +1351,9 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); ...@@ -1349,6 +1351,9 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
struct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u32 timeout);
/* ----- HCI Sockets ----- */ /* ----- HCI Sockets ----- */
void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
......
...@@ -39,6 +39,10 @@ struct hci_mon_hdr { ...@@ -39,6 +39,10 @@ struct hci_mon_hdr {
#define HCI_MON_ACL_RX_PKT 5 #define HCI_MON_ACL_RX_PKT 5
#define HCI_MON_SCO_TX_PKT 6 #define HCI_MON_SCO_TX_PKT 6
#define HCI_MON_SCO_RX_PKT 7 #define HCI_MON_SCO_RX_PKT 7
#define HCI_MON_OPEN_INDEX 8
#define HCI_MON_CLOSE_INDEX 9
#define HCI_MON_INDEX_INFO 10
#define HCI_MON_VENDOR_DIAG 11
struct hci_mon_new_index { struct hci_mon_new_index {
__u8 type; __u8 type;
...@@ -48,4 +52,10 @@ struct hci_mon_new_index { ...@@ -48,4 +52,10 @@ struct hci_mon_new_index {
} __packed; } __packed;
#define HCI_MON_NEW_INDEX_SIZE 16 #define HCI_MON_NEW_INDEX_SIZE 16
struct hci_mon_index_info {
bdaddr_t bdaddr;
__le16 manufacturer;
} __packed;
#define HCI_MON_INDEX_INFO_SIZE 8
#endif /* __HCI_MON_H */ #endif /* __HCI_MON_H */
...@@ -27,6 +27,16 @@ ...@@ -27,6 +27,16 @@
struct wpan_phy; struct wpan_phy;
struct wpan_phy_cca; struct wpan_phy_cca;
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
struct ieee802154_llsec_device_key;
struct ieee802154_llsec_seclevel;
struct ieee802154_llsec_params;
struct ieee802154_llsec_device;
struct ieee802154_llsec_table;
struct ieee802154_llsec_key_id;
struct ieee802154_llsec_key;
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
struct cfg802154_ops { struct cfg802154_ops {
struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
const char *name, const char *name,
...@@ -65,6 +75,51 @@ struct cfg802154_ops { ...@@ -65,6 +75,51 @@ struct cfg802154_ops {
struct wpan_dev *wpan_dev, bool mode); struct wpan_dev *wpan_dev, bool mode);
int (*set_ackreq_default)(struct wpan_phy *wpan_phy, int (*set_ackreq_default)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, bool ackreq); struct wpan_dev *wpan_dev, bool ackreq);
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
void (*get_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
struct ieee802154_llsec_table **table);
void (*lock_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev);
void (*unlock_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev);
/* TODO remove locking/get table callbacks, this is part of the
* nl802154 interface and should be accessible from ieee802154 layer.
*/
int (*get_llsec_params)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
struct ieee802154_llsec_params *params);
int (*set_llsec_params)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_params *params,
int changed);
int (*add_llsec_key)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_key_id *id,
const struct ieee802154_llsec_key *key);
int (*del_llsec_key)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_key_id *id);
int (*add_seclevel)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_seclevel *sl);
int (*del_seclevel)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_seclevel *sl);
int (*add_device)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_device *dev);
int (*del_device)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, __le64 extended_addr);
int (*add_devkey)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
__le64 extended_addr,
const struct ieee802154_llsec_device_key *key);
int (*del_devkey)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
__le64 extended_addr,
const struct ieee802154_llsec_device_key *key);
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
}; };
static inline bool static inline bool
...@@ -167,6 +222,102 @@ struct wpan_phy { ...@@ -167,6 +222,102 @@ struct wpan_phy {
char priv[0] __aligned(NETDEV_ALIGN); char priv[0] __aligned(NETDEV_ALIGN);
}; };
struct ieee802154_addr {
u8 mode;
__le16 pan_id;
union {
__le16 short_addr;
__le64 extended_addr;
};
};
struct ieee802154_llsec_key_id {
u8 mode;
u8 id;
union {
struct ieee802154_addr device_addr;
__le32 short_source;
__le64 extended_source;
};
};
#define IEEE802154_LLSEC_KEY_SIZE 16
struct ieee802154_llsec_key {
u8 frame_types;
u32 cmd_frame_ids;
/* TODO replace with NL802154_KEY_SIZE */
u8 key[IEEE802154_LLSEC_KEY_SIZE];
};
struct ieee802154_llsec_key_entry {
struct list_head list;
struct ieee802154_llsec_key_id id;
struct ieee802154_llsec_key *key;
};
struct ieee802154_llsec_params {
bool enabled;
__be32 frame_counter;
u8 out_level;
struct ieee802154_llsec_key_id out_key;
__le64 default_key_source;
__le16 pan_id;
__le64 hwaddr;
__le64 coord_hwaddr;
__le16 coord_shortaddr;
};
struct ieee802154_llsec_table {
struct list_head keys;
struct list_head devices;
struct list_head security_levels;
};
struct ieee802154_llsec_seclevel {
struct list_head list;
u8 frame_type;
u8 cmd_frame_id;
bool device_override;
u32 sec_levels;
};
struct ieee802154_llsec_device {
struct list_head list;
__le16 pan_id;
__le16 short_addr;
__le64 hwaddr;
u32 frame_counter;
bool seclevel_exempt;
u8 key_mode;
struct list_head keys;
};
struct ieee802154_llsec_device_key {
struct list_head list;
struct ieee802154_llsec_key_id key_id;
u32 frame_counter;
};
struct wpan_dev_header_ops {
/* TODO create callback currently assumes ieee802154_mac_cb inside
* skb->cb. This should be changed to give these information as
* parameter.
*/
int (*create)(struct sk_buff *skb, struct net_device *dev,
const struct ieee802154_addr *daddr,
const struct ieee802154_addr *saddr,
unsigned int len);
};
struct wpan_dev { struct wpan_dev {
struct wpan_phy *wpan_phy; struct wpan_phy *wpan_phy;
int iftype; int iftype;
...@@ -175,6 +326,8 @@ struct wpan_dev { ...@@ -175,6 +326,8 @@ struct wpan_dev {
struct list_head list; struct list_head list;
struct net_device *netdev; struct net_device *netdev;
const struct wpan_dev_header_ops *header_ops;
/* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */ /* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */
struct net_device *lowpan_dev; struct net_device *lowpan_dev;
...@@ -205,6 +358,17 @@ struct wpan_dev { ...@@ -205,6 +358,17 @@ struct wpan_dev {
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
static inline int
wpan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
const struct ieee802154_addr *daddr,
const struct ieee802154_addr *saddr,
unsigned int len)
{
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
return wpan_dev->header_ops->create(skb, dev, daddr, saddr, len);
}
struct wpan_phy * struct wpan_phy *
wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size); wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size);
static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev) static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
......
...@@ -50,15 +50,6 @@ struct ieee802154_sechdr { ...@@ -50,15 +50,6 @@ struct ieee802154_sechdr {
}; };
}; };
struct ieee802154_addr {
u8 mode;
__le16 pan_id;
union {
__le16 short_addr;
__le64 extended_addr;
};
};
struct ieee802154_hdr_fc { struct ieee802154_hdr_fc {
#if defined(__LITTLE_ENDIAN_BITFIELD) #if defined(__LITTLE_ENDIAN_BITFIELD)
u16 type:3, u16 type:3,
...@@ -99,7 +90,7 @@ struct ieee802154_hdr { ...@@ -99,7 +90,7 @@ struct ieee802154_hdr {
* hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
* version, if SECEN is set. * version, if SECEN is set.
*/ */
int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr); int ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr);
/* pulls the entire 802.15.4 header off of the skb, including the security /* pulls the entire 802.15.4 header off of the skb, including the security
* header, and performs pan id decompression * header, and performs pan id decompression
...@@ -243,38 +234,6 @@ static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb) ...@@ -243,38 +234,6 @@ static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb)
return mac_cb(skb); return mac_cb(skb);
} }
#define IEEE802154_LLSEC_KEY_SIZE 16
struct ieee802154_llsec_key_id {
u8 mode;
u8 id;
union {
struct ieee802154_addr device_addr;
__le32 short_source;
__le64 extended_source;
};
};
struct ieee802154_llsec_key {
u8 frame_types;
u32 cmd_frame_ids;
u8 key[IEEE802154_LLSEC_KEY_SIZE];
};
struct ieee802154_llsec_key_entry {
struct list_head list;
struct ieee802154_llsec_key_id id;
struct ieee802154_llsec_key *key;
};
struct ieee802154_llsec_device_key {
struct list_head list;
struct ieee802154_llsec_key_id key_id;
u32 frame_counter;
};
enum { enum {
IEEE802154_LLSEC_DEVKEY_IGNORE, IEEE802154_LLSEC_DEVKEY_IGNORE,
IEEE802154_LLSEC_DEVKEY_RESTRICT, IEEE802154_LLSEC_DEVKEY_RESTRICT,
...@@ -283,49 +242,6 @@ enum { ...@@ -283,49 +242,6 @@ enum {
__IEEE802154_LLSEC_DEVKEY_MAX, __IEEE802154_LLSEC_DEVKEY_MAX,
}; };
struct ieee802154_llsec_device {
struct list_head list;
__le16 pan_id;
__le16 short_addr;
__le64 hwaddr;
u32 frame_counter;
bool seclevel_exempt;
u8 key_mode;
struct list_head keys;
};
struct ieee802154_llsec_seclevel {
struct list_head list;
u8 frame_type;
u8 cmd_frame_id;
bool device_override;
u32 sec_levels;
};
struct ieee802154_llsec_params {
bool enabled;
__be32 frame_counter;
u8 out_level;
struct ieee802154_llsec_key_id out_key;
__le64 default_key_source;
__le16 pan_id;
__le64 hwaddr;
__le64 coord_hwaddr;
__le16 coord_shortaddr;
};
struct ieee802154_llsec_table {
struct list_head keys;
struct list_head devices;
struct list_head security_levels;
};
#define IEEE802154_MAC_SCAN_ED 0 #define IEEE802154_MAC_SCAN_ED 0
#define IEEE802154_MAC_SCAN_ACTIVE 1 #define IEEE802154_MAC_SCAN_ACTIVE 1
#define IEEE802154_MAC_SCAN_PASSIVE 2 #define IEEE802154_MAC_SCAN_PASSIVE 2
......
...@@ -23,14 +23,6 @@ ...@@ -23,14 +23,6 @@
#include <net/cfg802154.h> #include <net/cfg802154.h>
/* General MAC frame format:
* 2 bytes: Frame Control
* 1 byte: Sequence Number
* 20 bytes: Addressing fields
* 14 bytes: Auxiliary Security Header
*/
#define MAC802154_FRAME_HARD_HEADER_LEN (2 + 1 + 20 + 14)
/** /**
* enum ieee802154_hw_addr_filt_flags - hardware address filtering flags * enum ieee802154_hw_addr_filt_flags - hardware address filtering flags
* *
...@@ -256,7 +248,7 @@ struct ieee802154_ops { ...@@ -256,7 +248,7 @@ struct ieee802154_ops {
static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb) static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb)
{ {
/* return some invalid fc on failure */ /* return some invalid fc on failure */
if (unlikely(skb->mac_len < 2)) { if (unlikely(skb->len < 2)) {
WARN_ON(1); WARN_ON(1);
return cpu_to_le16(0); return cpu_to_le16(0);
} }
......
...@@ -1003,6 +1003,15 @@ static inline __be32 nla_get_be32(const struct nlattr *nla) ...@@ -1003,6 +1003,15 @@ static inline __be32 nla_get_be32(const struct nlattr *nla)
return *(__be32 *) nla_data(nla); return *(__be32 *) nla_data(nla);
} }
/**
* nla_get_le32 - return payload of __le32 attribute
* @nla: __le32 netlink attribute
*/
static inline __le32 nla_get_le32(const struct nlattr *nla)
{
return *(__le32 *) nla_data(nla);
}
/** /**
* nla_get_u16 - return payload of u16 attribute * nla_get_u16 - return payload of u16 attribute
* @nla: u16 netlink attribute * @nla: u16 netlink attribute
...@@ -1065,6 +1074,15 @@ static inline __be64 nla_get_be64(const struct nlattr *nla) ...@@ -1065,6 +1074,15 @@ static inline __be64 nla_get_be64(const struct nlattr *nla)
return tmp; return tmp;
} }
/**
* nla_get_le64 - return payload of __le64 attribute
* @nla: __le64 netlink attribute
*/
static inline __le64 nla_get_le64(const struct nlattr *nla)
{
return *(__le64 *) nla_data(nla);
}
/** /**
* nla_get_s32 - return payload of s32 attribute * nla_get_s32 - return payload of s32 attribute
* @nla: s32 netlink attribute * @nla: s32 netlink attribute
......
...@@ -56,6 +56,22 @@ enum nl802154_commands { ...@@ -56,6 +56,22 @@ enum nl802154_commands {
/* add new commands above here */ /* add new commands above here */
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
NL802154_CMD_SET_SEC_PARAMS,
NL802154_CMD_GET_SEC_KEY, /* can dump */
NL802154_CMD_NEW_SEC_KEY,
NL802154_CMD_DEL_SEC_KEY,
NL802154_CMD_GET_SEC_DEV, /* can dump */
NL802154_CMD_NEW_SEC_DEV,
NL802154_CMD_DEL_SEC_DEV,
NL802154_CMD_GET_SEC_DEVKEY, /* can dump */
NL802154_CMD_NEW_SEC_DEVKEY,
NL802154_CMD_DEL_SEC_DEVKEY,
NL802154_CMD_GET_SEC_LEVEL, /* can dump */
NL802154_CMD_NEW_SEC_LEVEL,
NL802154_CMD_DEL_SEC_LEVEL,
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
/* used to define NL802154_CMD_MAX below */ /* used to define NL802154_CMD_MAX below */
__NL802154_CMD_AFTER_LAST, __NL802154_CMD_AFTER_LAST,
NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1 NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1
...@@ -110,6 +126,18 @@ enum nl802154_attrs { ...@@ -110,6 +126,18 @@ enum nl802154_attrs {
/* add attributes here, update the policy in nl802154.c */ /* add attributes here, update the policy in nl802154.c */
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
NL802154_ATTR_SEC_ENABLED,
NL802154_ATTR_SEC_OUT_LEVEL,
NL802154_ATTR_SEC_OUT_KEY_ID,
NL802154_ATTR_SEC_FRAME_COUNTER,
NL802154_ATTR_SEC_LEVEL,
NL802154_ATTR_SEC_DEVICE,
NL802154_ATTR_SEC_DEVKEY,
NL802154_ATTR_SEC_KEY,
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
__NL802154_ATTR_AFTER_LAST, __NL802154_ATTR_AFTER_LAST,
NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1
}; };
...@@ -247,4 +275,167 @@ enum nl802154_supported_bool_states { ...@@ -247,4 +275,167 @@ enum nl802154_supported_bool_states {
NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1 NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1
}; };
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
enum nl802154_dev_addr_modes {
NL802154_DEV_ADDR_NONE,
__NL802154_DEV_ADDR_INVALID,
NL802154_DEV_ADDR_SHORT,
NL802154_DEV_ADDR_EXTENDED,
/* keep last */
__NL802154_DEV_ADDR_AFTER_LAST,
NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1
};
enum nl802154_dev_addr_attrs {
NL802154_DEV_ADDR_ATTR_UNSPEC,
NL802154_DEV_ADDR_ATTR_PAN_ID,
NL802154_DEV_ADDR_ATTR_MODE,
NL802154_DEV_ADDR_ATTR_SHORT,
NL802154_DEV_ADDR_ATTR_EXTENDED,
/* keep last */
__NL802154_DEV_ADDR_ATTR_AFTER_LAST,
NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1
};
enum nl802154_key_id_modes {
NL802154_KEY_ID_MODE_IMPLICIT,
NL802154_KEY_ID_MODE_INDEX,
NL802154_KEY_ID_MODE_INDEX_SHORT,
NL802154_KEY_ID_MODE_INDEX_EXTENDED,
/* keep last */
__NL802154_KEY_ID_MODE_AFTER_LAST,
NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1
};
enum nl802154_key_id_attrs {
NL802154_KEY_ID_ATTR_UNSPEC,
NL802154_KEY_ID_ATTR_MODE,
NL802154_KEY_ID_ATTR_INDEX,
NL802154_KEY_ID_ATTR_IMPLICIT,
NL802154_KEY_ID_ATTR_SOURCE_SHORT,
NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
/* keep last */
__NL802154_KEY_ID_ATTR_AFTER_LAST,
NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1
};
enum nl802154_seclevels {
NL802154_SECLEVEL_NONE,
NL802154_SECLEVEL_MIC32,
NL802154_SECLEVEL_MIC64,
NL802154_SECLEVEL_MIC128,
NL802154_SECLEVEL_ENC,
NL802154_SECLEVEL_ENC_MIC32,
NL802154_SECLEVEL_ENC_MIC64,
NL802154_SECLEVEL_ENC_MIC128,
/* keep last */
__NL802154_SECLEVEL_AFTER_LAST,
NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1
};
enum nl802154_frames {
NL802154_FRAME_BEACON,
NL802154_FRAME_DATA,
NL802154_FRAME_ACK,
NL802154_FRAME_CMD,
/* keep last */
__NL802154_FRAME_AFTER_LAST,
NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1
};
enum nl802154_cmd_frames {
__NL802154_CMD_FRAME_INVALID,
NL802154_CMD_FRAME_ASSOC_REQUEST,
NL802154_CMD_FRAME_ASSOC_RESPONSE,
NL802154_CMD_FRAME_DISASSOC_NOTIFY,
NL802154_CMD_FRAME_DATA_REQUEST,
NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY,
NL802154_CMD_FRAME_ORPHAN_NOTIFY,
NL802154_CMD_FRAME_BEACON_REQUEST,
NL802154_CMD_FRAME_COORD_REALIGNMENT,
NL802154_CMD_FRAME_GTS_REQUEST,
/* keep last */
__NL802154_CMD_FRAME_AFTER_LAST,
NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1
};
enum nl802154_seclevel_attrs {
NL802154_SECLEVEL_ATTR_UNSPEC,
NL802154_SECLEVEL_ATTR_LEVELS,
NL802154_SECLEVEL_ATTR_FRAME,
NL802154_SECLEVEL_ATTR_CMD_FRAME,
NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
/* keep last */
__NL802154_SECLEVEL_ATTR_AFTER_LAST,
NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1
};
/* TODO what is this? couldn't find in mib */
enum {
NL802154_DEVKEY_IGNORE,
NL802154_DEVKEY_RESTRICT,
NL802154_DEVKEY_RECORD,
/* keep last */
__NL802154_DEVKEY_AFTER_LAST,
NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1
};
enum nl802154_dev {
NL802154_DEV_ATTR_UNSPEC,
NL802154_DEV_ATTR_FRAME_COUNTER,
NL802154_DEV_ATTR_PAN_ID,
NL802154_DEV_ATTR_SHORT_ADDR,
NL802154_DEV_ATTR_EXTENDED_ADDR,
NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
NL802154_DEV_ATTR_KEY_MODE,
/* keep last */
__NL802154_DEV_ATTR_AFTER_LAST,
NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1
};
enum nl802154_devkey {
NL802154_DEVKEY_ATTR_UNSPEC,
NL802154_DEVKEY_ATTR_FRAME_COUNTER,
NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
NL802154_DEVKEY_ATTR_ID,
/* keep last */
__NL802154_DEVKEY_ATTR_AFTER_LAST,
NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1
};
enum nl802154_key {
NL802154_KEY_ATTR_UNSPEC,
NL802154_KEY_ATTR_ID,
NL802154_KEY_ATTR_USAGE_FRAMES,
NL802154_KEY_ATTR_USAGE_CMDS,
NL802154_KEY_ATTR_BYTES,
/* keep last */
__NL802154_KEY_ATTR_AFTER_LAST,
NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1
};
#define NL802154_KEY_SIZE 16
#define NL802154_CMD_FRAME_NR_IDS 256
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
#endif /* __NL802154_H */ #endif /* __NL802154_H */
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype) void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype)
{ {
dev->addr_len = EUI64_ADDR_LEN;
dev->type = ARPHRD_6LOWPAN;
dev->mtu = IPV6_MIN_MTU;
dev->priv_flags |= IFF_NO_QUEUE;
lowpan_priv(dev)->lltype = lltype; lowpan_priv(dev)->lltype = lltype;
} }
EXPORT_SYMBOL(lowpan_netdev_setup); EXPORT_SYMBOL(lowpan_netdev_setup);
......
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#include <net/6lowpan.h> #include <net/6lowpan.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#define LOWPAN_NHC_MAX_ID_LEN 1
/** /**
* LOWPAN_NHC - helper macro to generate nh id fields and lowpan_nhc struct * LOWPAN_NHC - helper macro to generate nh id fields and lowpan_nhc struct
* *
......
...@@ -35,7 +35,6 @@ static struct dentry *lowpan_enable_debugfs; ...@@ -35,7 +35,6 @@ static struct dentry *lowpan_enable_debugfs;
static struct dentry *lowpan_control_debugfs; static struct dentry *lowpan_control_debugfs;
#define IFACE_NAME_TEMPLATE "bt%d" #define IFACE_NAME_TEMPLATE "bt%d"
#define EUI64_ADDR_LEN 8
struct skb_cb { struct skb_cb {
struct in6_addr addr; struct in6_addr addr;
...@@ -674,13 +673,8 @@ static struct header_ops header_ops = { ...@@ -674,13 +673,8 @@ static struct header_ops header_ops = {
static void netdev_setup(struct net_device *dev) static void netdev_setup(struct net_device *dev)
{ {
dev->addr_len = EUI64_ADDR_LEN;
dev->type = ARPHRD_6LOWPAN;
dev->hard_header_len = 0; dev->hard_header_len = 0;
dev->needed_tailroom = 0; dev->needed_tailroom = 0;
dev->mtu = IPV6_MIN_MTU;
dev->tx_queue_len = 0;
dev->flags = IFF_RUNNING | IFF_POINTOPOINT | dev->flags = IFF_RUNNING | IFF_POINTOPOINT |
IFF_MULTICAST; IFF_MULTICAST;
dev->watchdog_timeo = 0; dev->watchdog_timeo = 0;
...@@ -775,24 +769,7 @@ static struct l2cap_chan *chan_create(void) ...@@ -775,24 +769,7 @@ static struct l2cap_chan *chan_create(void)
chan->chan_type = L2CAP_CHAN_CONN_ORIENTED; chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
chan->mode = L2CAP_MODE_LE_FLOWCTL; chan->mode = L2CAP_MODE_LE_FLOWCTL;
chan->omtu = 65535; chan->imtu = 1280;
chan->imtu = chan->omtu;
return chan;
}
static struct l2cap_chan *chan_open(struct l2cap_chan *pchan)
{
struct l2cap_chan *chan;
chan = chan_create();
if (!chan)
return NULL;
chan->remote_mps = chan->omtu;
chan->mps = chan->omtu;
chan->state = BT_CONNECTED;
return chan; return chan;
} }
...@@ -919,7 +896,10 @@ static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan) ...@@ -919,7 +896,10 @@ static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)
{ {
struct l2cap_chan *chan; struct l2cap_chan *chan;
chan = chan_open(pchan); chan = chan_create();
if (!chan)
return NULL;
chan->ops = pchan->ops; chan->ops = pchan->ops;
BT_DBG("chan %p pchan %p", chan, pchan); BT_DBG("chan %p pchan %p", chan, pchan);
...@@ -1065,34 +1045,23 @@ static inline __u8 bdaddr_type(__u8 type) ...@@ -1065,34 +1045,23 @@ static inline __u8 bdaddr_type(__u8 type)
return BDADDR_LE_RANDOM; return BDADDR_LE_RANDOM;
} }
static struct l2cap_chan *chan_get(void)
{
struct l2cap_chan *pchan;
pchan = chan_create();
if (!pchan)
return NULL;
pchan->ops = &bt_6lowpan_chan_ops;
return pchan;
}
static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type) static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type)
{ {
struct l2cap_chan *pchan; struct l2cap_chan *chan;
int err; int err;
pchan = chan_get(); chan = chan_create();
if (!pchan) if (!chan)
return -EINVAL; return -EINVAL;
err = l2cap_chan_connect(pchan, cpu_to_le16(L2CAP_PSM_IPSP), 0, chan->ops = &bt_6lowpan_chan_ops;
err = l2cap_chan_connect(chan, cpu_to_le16(L2CAP_PSM_IPSP), 0,
addr, dst_type); addr, dst_type);
BT_DBG("chan %p err %d", pchan, err); BT_DBG("chan %p err %d", chan, err);
if (err < 0) if (err < 0)
l2cap_chan_put(pchan); l2cap_chan_put(chan);
return err; return err;
} }
...@@ -1117,31 +1086,32 @@ static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type) ...@@ -1117,31 +1086,32 @@ static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type)
static struct l2cap_chan *bt_6lowpan_listen(void) static struct l2cap_chan *bt_6lowpan_listen(void)
{ {
bdaddr_t *addr = BDADDR_ANY; bdaddr_t *addr = BDADDR_ANY;
struct l2cap_chan *pchan; struct l2cap_chan *chan;
int err; int err;
if (!enable_6lowpan) if (!enable_6lowpan)
return NULL; return NULL;
pchan = chan_get(); chan = chan_create();
if (!pchan) if (!chan)
return NULL; return NULL;
pchan->state = BT_LISTEN; chan->ops = &bt_6lowpan_chan_ops;
pchan->src_type = BDADDR_LE_PUBLIC; chan->state = BT_LISTEN;
chan->src_type = BDADDR_LE_PUBLIC;
atomic_set(&pchan->nesting, L2CAP_NESTING_PARENT); atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
BT_DBG("chan %p src type %d", pchan, pchan->src_type); BT_DBG("chan %p src type %d", chan, chan->src_type);
err = l2cap_add_psm(pchan, addr, cpu_to_le16(L2CAP_PSM_IPSP)); err = l2cap_add_psm(chan, addr, cpu_to_le16(L2CAP_PSM_IPSP));
if (err) { if (err) {
l2cap_chan_put(pchan); l2cap_chan_put(chan);
BT_ERR("psm cannot be added err %d", err); BT_ERR("psm cannot be added err %d", err);
return NULL; return NULL;
} }
return pchan; return chan;
} }
static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
......
...@@ -134,6 +134,66 @@ static const struct file_operations dut_mode_fops = { ...@@ -134,6 +134,66 @@ static const struct file_operations dut_mode_fops = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
static ssize_t vendor_diag_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[3];
buf[0] = hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t vendor_diag_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable;
int err;
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (strtobool(buf, &enable))
return -EINVAL;
hci_req_lock(hdev);
err = hdev->set_diag(hdev, enable);
hci_req_unlock(hdev);
if (err < 0)
return err;
if (enable)
hci_dev_set_flag(hdev, HCI_VENDOR_DIAG);
else
hci_dev_clear_flag(hdev, HCI_VENDOR_DIAG);
return count;
}
static const struct file_operations vendor_diag_fops = {
.open = simple_open,
.read = vendor_diag_read,
.write = vendor_diag_write,
.llseek = default_llseek,
};
static void hci_debugfs_create_basic(struct hci_dev *hdev)
{
debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
&dut_mode_fops);
if (hdev->set_diag)
debugfs_create_file("vendor_diag", 0644, hdev->debugfs, hdev,
&vendor_diag_fops);
}
/* ---- HCI requests ---- */ /* ---- HCI requests ---- */
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
...@@ -850,13 +910,8 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -850,13 +910,8 @@ static int __hci_init(struct hci_dev *hdev)
if (err < 0) if (err < 0)
return err; return err;
/* The Device Under Test (DUT) mode is special and available for if (hci_dev_test_flag(hdev, HCI_SETUP))
* all controller types. So just create it early on. hci_debugfs_create_basic(hdev);
*/
if (hci_dev_test_flag(hdev, HCI_SETUP)) {
debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
&dut_mode_fops);
}
err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT); err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
if (err < 0) if (err < 0)
...@@ -933,6 +988,9 @@ static int __hci_unconf_init(struct hci_dev *hdev) ...@@ -933,6 +988,9 @@ static int __hci_unconf_init(struct hci_dev *hdev)
if (err < 0) if (err < 0)
return err; return err;
if (hci_dev_test_flag(hdev, HCI_SETUP))
hci_debugfs_create_basic(hdev);
return 0; return 0;
} }
...@@ -1385,6 +1443,9 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1385,6 +1443,9 @@ static int hci_dev_do_open(struct hci_dev *hdev)
goto done; goto done;
} }
set_bit(HCI_RUNNING, &hdev->flags);
hci_notify(hdev, HCI_DEV_OPEN);
atomic_set(&hdev->cmd_cnt, 1); atomic_set(&hdev->cmd_cnt, 1);
set_bit(HCI_INIT, &hdev->flags); set_bit(HCI_INIT, &hdev->flags);
...@@ -1466,6 +1527,9 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1466,6 +1527,9 @@ static int hci_dev_do_open(struct hci_dev *hdev)
hdev->sent_cmd = NULL; hdev->sent_cmd = NULL;
} }
clear_bit(HCI_RUNNING, &hdev->flags);
hci_notify(hdev, HCI_DEV_CLOSE);
hdev->close(hdev); hdev->close(hdev);
hdev->flags &= BIT(HCI_RAW); hdev->flags &= BIT(HCI_RAW);
} }
...@@ -1551,6 +1615,8 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) ...@@ -1551,6 +1615,8 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
int hci_dev_do_close(struct hci_dev *hdev) int hci_dev_do_close(struct hci_dev *hdev)
{ {
bool auto_off;
BT_DBG("%s %p", hdev->name, hdev); BT_DBG("%s %p", hdev->name, hdev);
if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
...@@ -1606,10 +1672,10 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1606,10 +1672,10 @@ int hci_dev_do_close(struct hci_dev *hdev)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
if (!hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) { auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF);
if (hdev->dev_type == HCI_BREDR)
if (!auto_off && hdev->dev_type == HCI_BREDR)
mgmt_powered(hdev, 0); mgmt_powered(hdev, 0);
}
hci_inquiry_cache_flush(hdev); hci_inquiry_cache_flush(hdev);
hci_pend_le_actions_clear(hdev); hci_pend_le_actions_clear(hdev);
...@@ -1626,9 +1692,8 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1626,9 +1692,8 @@ int hci_dev_do_close(struct hci_dev *hdev)
/* Reset device */ /* Reset device */
skb_queue_purge(&hdev->cmd_q); skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1); atomic_set(&hdev->cmd_cnt, 1);
if (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) && if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) &&
!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
set_bit(HCI_INIT, &hdev->flags); set_bit(HCI_INIT, &hdev->flags);
__hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT);
clear_bit(HCI_INIT, &hdev->flags); clear_bit(HCI_INIT, &hdev->flags);
...@@ -1649,6 +1714,9 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1649,6 +1714,9 @@ int hci_dev_do_close(struct hci_dev *hdev)
hdev->sent_cmd = NULL; hdev->sent_cmd = NULL;
} }
clear_bit(HCI_RUNNING, &hdev->flags);
hci_notify(hdev, HCI_DEV_CLOSE);
/* After this point our queues are empty /* After this point our queues are empty
* and no tasks are scheduled. */ * and no tasks are scheduled. */
hdev->close(hdev); hdev->close(hdev);
...@@ -3471,6 +3539,13 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3471,6 +3539,13 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
return -ENXIO; return -ENXIO;
} }
if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT &&
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
kfree_skb(skb);
return -EINVAL;
}
/* Incoming skb */ /* Incoming skb */
bt_cb(skb)->incoming = 1; bt_cb(skb)->incoming = 1;
...@@ -3484,6 +3559,21 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3484,6 +3559,21 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
} }
EXPORT_SYMBOL(hci_recv_frame); EXPORT_SYMBOL(hci_recv_frame);
/* Receive diagnostic message from HCI drivers */
int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb)
{
/* Time stamp */
__net_timestamp(skb);
/* Mark as diagnostic packet and send to monitor */
bt_cb(skb)->pkt_type = HCI_DIAG_PKT;
hci_send_to_monitor(hdev, skb);
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL(hci_recv_diag);
/* ---- Interface to upper protocols ---- */ /* ---- Interface to upper protocols ---- */
int hci_register_cb(struct hci_cb *cb) int hci_register_cb(struct hci_cb *cb)
...@@ -3530,6 +3620,11 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3530,6 +3620,11 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
/* Get rid of skb owner, prior to sending to the driver. */ /* Get rid of skb owner, prior to sending to the driver. */
skb_orphan(skb); skb_orphan(skb);
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
kfree_skb(skb);
return;
}
err = hdev->send(hdev, skb); err = hdev->send(hdev, skb);
if (err < 0) { if (err < 0) {
BT_ERR("%s sending frame failed (%d)", hdev->name, err); BT_ERR("%s sending frame failed (%d)", hdev->name, err);
...@@ -3580,6 +3675,25 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) ...@@ -3580,6 +3675,25 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE; return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
} }
/* Send HCI command and wait for command commplete event */
struct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u32 timeout)
{
struct sk_buff *skb;
if (!test_bit(HCI_UP, &hdev->flags))
return ERR_PTR(-ENETDOWN);
bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen);
hci_req_lock(hdev);
skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout);
hci_req_unlock(hdev);
return skb;
}
EXPORT_SYMBOL(hci_cmd_sync);
/* Send ACL data */ /* Send ACL data */
static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
{ {
......
...@@ -279,6 +279,9 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -279,6 +279,9 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
else else
opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT);
break; break;
case HCI_DIAG_PKT:
opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG);
break;
default: default:
return; return;
} }
...@@ -303,6 +306,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) ...@@ -303,6 +306,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
{ {
struct hci_mon_hdr *hdr; struct hci_mon_hdr *hdr;
struct hci_mon_new_index *ni; struct hci_mon_new_index *ni;
struct hci_mon_index_info *ii;
struct sk_buff *skb; struct sk_buff *skb;
__le16 opcode; __le16 opcode;
...@@ -312,7 +316,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) ...@@ -312,7 +316,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
if (!skb) if (!skb)
return NULL; return NULL;
ni = (void *) skb_put(skb, HCI_MON_NEW_INDEX_SIZE); ni = (void *)skb_put(skb, HCI_MON_NEW_INDEX_SIZE);
ni->type = hdev->dev_type; ni->type = hdev->dev_type;
ni->bus = hdev->bus; ni->bus = hdev->bus;
bacpy(&ni->bdaddr, &hdev->bdaddr); bacpy(&ni->bdaddr, &hdev->bdaddr);
...@@ -329,6 +333,34 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) ...@@ -329,6 +333,34 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
opcode = cpu_to_le16(HCI_MON_DEL_INDEX); opcode = cpu_to_le16(HCI_MON_DEL_INDEX);
break; break;
case HCI_DEV_UP:
skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC);
if (!skb)
return NULL;
ii = (void *)skb_put(skb, HCI_MON_INDEX_INFO_SIZE);
bacpy(&ii->bdaddr, &hdev->bdaddr);
ii->manufacturer = cpu_to_le16(hdev->manufacturer);
opcode = cpu_to_le16(HCI_MON_INDEX_INFO);
break;
case HCI_DEV_OPEN:
skb = bt_skb_alloc(0, GFP_ATOMIC);
if (!skb)
return NULL;
opcode = cpu_to_le16(HCI_MON_OPEN_INDEX);
break;
case HCI_DEV_CLOSE:
skb = bt_skb_alloc(0, GFP_ATOMIC);
if (!skb)
return NULL;
opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX);
break;
default: default:
return NULL; return NULL;
} }
...@@ -358,6 +390,26 @@ static void send_monitor_replay(struct sock *sk) ...@@ -358,6 +390,26 @@ static void send_monitor_replay(struct sock *sk)
if (sock_queue_rcv_skb(sk, skb)) if (sock_queue_rcv_skb(sk, skb))
kfree_skb(skb); kfree_skb(skb);
if (!test_bit(HCI_RUNNING, &hdev->flags))
continue;
skb = create_monitor_event(hdev, HCI_DEV_OPEN);
if (!skb)
continue;
if (sock_queue_rcv_skb(sk, skb))
kfree_skb(skb);
if (!test_bit(HCI_UP, &hdev->flags))
continue;
skb = create_monitor_event(hdev, HCI_DEV_UP);
if (!skb)
continue;
if (sock_queue_rcv_skb(sk, skb))
kfree_skb(skb);
} }
read_unlock(&hci_dev_list_lock); read_unlock(&hci_dev_list_lock);
...@@ -392,14 +444,12 @@ static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) ...@@ -392,14 +444,12 @@ static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
void hci_sock_dev_event(struct hci_dev *hdev, int event) void hci_sock_dev_event(struct hci_dev *hdev, int event)
{ {
struct hci_ev_si_device ev;
BT_DBG("hdev %s event %d", hdev->name, event); BT_DBG("hdev %s event %d", hdev->name, event);
/* Send event to monitor */
if (atomic_read(&monitor_promisc)) { if (atomic_read(&monitor_promisc)) {
struct sk_buff *skb; struct sk_buff *skb;
/* Send event to monitor */
skb = create_monitor_event(hdev, event); skb = create_monitor_event(hdev, event);
if (skb) { if (skb) {
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
...@@ -408,10 +458,14 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) ...@@ -408,10 +458,14 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
} }
} }
if (event <= HCI_DEV_DOWN) {
struct hci_ev_si_device ev;
/* Send event to sockets */ /* Send event to sockets */
ev.event = event; ev.event = event;
ev.dev_id = hdev->id; ev.dev_id = hdev->id;
hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
}
if (event == HCI_DEV_UNREG) { if (event == HCI_DEV_UNREG) {
struct sock *sk; struct sock *sk;
......
...@@ -151,6 +151,22 @@ void bt_info(const char *format, ...) ...@@ -151,6 +151,22 @@ void bt_info(const char *format, ...)
} }
EXPORT_SYMBOL(bt_info); EXPORT_SYMBOL(bt_info);
void bt_warn(const char *format, ...)
{
struct va_format vaf;
va_list args;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
pr_warn("%pV", &vaf);
va_end(args);
}
EXPORT_SYMBOL(bt_warn);
void bt_err(const char *format, ...) void bt_err(const char *format, ...)
{ {
struct va_format vaf; struct va_format vaf;
......
...@@ -101,14 +101,9 @@ static const struct net_device_ops lowpan_netdev_ops = { ...@@ -101,14 +101,9 @@ static const struct net_device_ops lowpan_netdev_ops = {
static void lowpan_setup(struct net_device *ldev) static void lowpan_setup(struct net_device *ldev)
{ {
ldev->addr_len = IEEE802154_ADDR_LEN;
memset(ldev->broadcast, 0xff, IEEE802154_ADDR_LEN); memset(ldev->broadcast, 0xff, IEEE802154_ADDR_LEN);
ldev->type = ARPHRD_6LOWPAN; /* We need an ipv6hdr as minimum len when calling xmit */
/* Frame Control + Sequence Number + Address fields + Security Header */ ldev->hard_header_len = sizeof(struct ipv6hdr);
ldev->hard_header_len = 2 + 1 + 20 + 14;
ldev->needed_tailroom = 2; /* FCS */
ldev->mtu = IPV6_MIN_MTU;
ldev->priv_flags |= IFF_NO_QUEUE;
ldev->flags = IFF_BROADCAST | IFF_MULTICAST; ldev->flags = IFF_BROADCAST | IFF_MULTICAST;
ldev->netdev_ops = &lowpan_netdev_ops; ldev->netdev_ops = &lowpan_netdev_ops;
...@@ -156,6 +151,15 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev, ...@@ -156,6 +151,15 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
lowpan_dev_info(ldev)->wdev = wdev; lowpan_dev_info(ldev)->wdev = wdev;
/* Set the lowpan hardware address to the wpan hardware address. */ /* Set the lowpan hardware address to the wpan hardware address. */
memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN); memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN);
/* We need headroom for possible wpan_dev_hard_header call and tailroom
* for encryption/fcs handling. The lowpan interface will replace
* the IPv6 header with 6LoWPAN header. At worst case the 6LoWPAN
* header has LOWPAN_IPHC_MAX_HEADER_LEN more bytes than the IPv6
* header.
*/
ldev->needed_headroom = LOWPAN_IPHC_MAX_HEADER_LEN +
wdev->needed_headroom;
ldev->needed_tailroom = wdev->needed_tailroom;
lowpan_netdev_setup(ldev, LOWPAN_LLTYPE_IEEE802154); lowpan_netdev_setup(ldev, LOWPAN_LLTYPE_IEEE802154);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
static int lowpan_give_skb_to_device(struct sk_buff *skb) static int lowpan_give_skb_to_device(struct sk_buff *skb)
{ {
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->dev->stats.rx_packets++;
skb->dev->stats.rx_bytes += skb->len;
return netif_rx(skb); return netif_rx(skb);
} }
......
This diff is collapsed.
...@@ -12,6 +12,11 @@ menuconfig IEEE802154 ...@@ -12,6 +12,11 @@ menuconfig IEEE802154
if IEEE802154 if IEEE802154
config IEEE802154_NL802154_EXPERIMENTAL
bool "IEEE 802.15.4 experimental netlink support"
---help---
Adds experimental netlink support for nl802154.
config IEEE802154_SOCKET config IEEE802154_SOCKET
tristate "IEEE 802.15.4 socket interface" tristate "IEEE 802.15.4 socket interface"
default y default y
......
This diff is collapsed.
...@@ -42,5 +42,6 @@ extern int cfg802154_rdev_list_generation; ...@@ -42,5 +42,6 @@ extern int cfg802154_rdev_list_generation;
void cfg802154_dev_free(struct cfg802154_registered_device *rdev); void cfg802154_dev_free(struct cfg802154_registered_device *rdev);
struct cfg802154_registered_device * struct cfg802154_registered_device *
cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx); cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx);
struct wpan_phy *wpan_phy_idx_to_wpan_phy(int wpan_phy_idx);
#endif /* __IEEE802154_CORE_H */ #endif /* __IEEE802154_CORE_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -401,6 +401,7 @@ int mac802154_llsec_dev_del(struct mac802154_llsec *sec, __le64 device_addr) ...@@ -401,6 +401,7 @@ int mac802154_llsec_dev_del(struct mac802154_llsec *sec, __le64 device_addr)
hash_del_rcu(&pos->bucket_s); hash_del_rcu(&pos->bucket_s);
hash_del_rcu(&pos->bucket_hw); hash_del_rcu(&pos->bucket_hw);
list_del_rcu(&pos->dev.list);
call_rcu(&pos->rcu, llsec_dev_free_rcu); call_rcu(&pos->rcu, llsec_dev_free_rcu);
return 0; return 0;
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment