Commit 5148371a 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-12-11

Here's another set of Bluetooth & 802.15.4 patches for the 4.5 kernel:

 - 6LoWPAN debugfs support
 - New 802.15.4 driver for ADF7242 MAC IEEE802154
 - Initial code for 6LoWPAN Generic Header Compression (GHC) support
 - Refactor Bluetooth LE scan & advertising behind dedicated workqueue
 - Cleanups to Bluetooth H:5 HCI driver
 - Support for Toshiba Broadcom based Bluetooth controllers
 - Use continuous scanning when establishing Bluetooth LE connections

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7e074af2 7302b9d9
* ADF7242 IEEE 802.15.4 *
Required properties:
- compatible: should be "adi,adf7242"
- spi-max-frequency: maximal bus speed (12.5 MHz)
- reg: the chipselect index
- interrupts: the interrupt generated by the device via pin IRQ1.
IRQ_TYPE_LEVEL_HIGH (4) or IRQ_TYPE_EDGE_FALLING (1)
Example:
adf7242@0 {
compatible = "adi,adf7242";
spi-max-frequency = <10000000>;
reg = <0>;
interrupts = <98 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gpio3>;
};
...@@ -371,6 +371,15 @@ ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR) ...@@ -371,6 +371,15 @@ ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR)
M: Jiri Kosina <jikos@kernel.org> M: Jiri Kosina <jikos@kernel.org>
S: Maintained S: Maintained
ADF7242 IEEE 802.15.4 RADIO DRIVER
M: Michael Hennerich <michael.hennerich@analog.com>
W: https://wiki.analog.com/ADF7242
W: http://ez.analog.com/community/linux-device-drivers
L: linux-wpan@vger.kernel.org
S: Supported
F: drivers/net/ieee802154/adf7242.c
F: Documentation/devicetree/bindings/net/ieee802154/adf7242.txt
ADM1025 HARDWARE MONITOR DRIVER ADM1025 HARDWARE MONITOR DRIVER
M: Jean Delvare <jdelvare@suse.com> M: Jean Delvare <jdelvare@suse.com>
L: lm-sensors@lm-sensors.org L: lm-sensors@lm-sensors.org
......
...@@ -73,6 +73,48 @@ int btintel_check_bdaddr(struct hci_dev *hdev) ...@@ -73,6 +73,48 @@ int btintel_check_bdaddr(struct hci_dev *hdev)
} }
EXPORT_SYMBOL_GPL(btintel_check_bdaddr); EXPORT_SYMBOL_GPL(btintel_check_bdaddr);
int btintel_enter_mfg(struct hci_dev *hdev)
{
const u8 param[] = { 0x01, 0x00 };
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Entering manufacturer mode failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_enter_mfg);
int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched)
{
u8 param[] = { 0x00, 0x00 };
struct sk_buff *skb;
/* The 2nd command parameter specifies the manufacturing exit method:
* 0x00: Just disable the manufacturing mode (0x00).
* 0x01: Disable manufacturing mode and reset with patches deactivated.
* 0x02: Disable manufacturing mode and reset with patches activated.
*/
if (reset)
param[1] |= patched ? 0x02 : 0x01;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Exiting manufacturer mode failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_exit_mfg);
int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -126,37 +168,19 @@ EXPORT_SYMBOL_GPL(btintel_set_diag); ...@@ -126,37 +168,19 @@ EXPORT_SYMBOL_GPL(btintel_set_diag);
int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable)
{ {
struct sk_buff *skb; int err, ret;
u8 param[2];
int err;
param[0] = 0x01;
param[1] = 0x00;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT); err = btintel_enter_mfg(hdev);
if (IS_ERR(skb)) { if (err)
err = PTR_ERR(skb); return err;
BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
err = btintel_set_diag(hdev, enable);
param[0] = 0x00;
param[1] = 0x00;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT); ret = btintel_set_diag(hdev, enable);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
err = btintel_exit_mfg(hdev, false, false);
if (err)
return err; return err;
return ret;
} }
EXPORT_SYMBOL_GPL(btintel_set_diag_mfg); EXPORT_SYMBOL_GPL(btintel_set_diag_mfg);
...@@ -309,39 +333,46 @@ EXPORT_SYMBOL_GPL(btintel_set_event_mask); ...@@ -309,39 +333,46 @@ EXPORT_SYMBOL_GPL(btintel_set_event_mask);
int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
{ {
struct sk_buff *skb; int err, ret;
u8 param[2];
int err;
param[0] = 0x01; err = btintel_enter_mfg(hdev);
param[1] = 0x00; if (err)
return err;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT); ret = btintel_set_event_mask(hdev, debug);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
err = btintel_set_event_mask(hdev, debug); err = btintel_exit_mfg(hdev, false, false);
if (err)
return err;
param[0] = 0x00; return ret;
param[1] = 0x00; }
EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg);
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT); int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
{
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)", PTR_ERR(skb));
hdev->name, err);
return PTR_ERR(skb); return PTR_ERR(skb);
} }
if (skb->len != sizeof(*ver)) {
bt_dev_err(hdev, "Intel version event size mismatch");
kfree_skb(skb); kfree_skb(skb);
return -EILSEQ;
}
return err; memcpy(ver, skb->data, sizeof(*ver));
kfree_skb(skb);
return 0;
} }
EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg); EXPORT_SYMBOL_GPL(btintel_read_version);
/* ------- REGMAP IBT SUPPORT ------- */ /* ------- REGMAP IBT SUPPORT ------- */
......
...@@ -72,6 +72,8 @@ struct intel_secure_send_result { ...@@ -72,6 +72,8 @@ struct intel_secure_send_result {
#if IS_ENABLED(CONFIG_BT_INTEL) #if IS_ENABLED(CONFIG_BT_INTEL)
int btintel_check_bdaddr(struct hci_dev *hdev); int btintel_check_bdaddr(struct hci_dev *hdev);
int btintel_enter_mfg(struct hci_dev *hdev);
int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched);
int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int btintel_set_diag(struct hci_dev *hdev, bool enable); int btintel_set_diag(struct hci_dev *hdev, bool enable);
int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable); int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
...@@ -83,6 +85,7 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, ...@@ -83,6 +85,7 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
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);
int btintel_set_event_mask(struct hci_dev *hdev, bool debug); int btintel_set_event_mask(struct hci_dev *hdev, bool debug);
int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug); int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug);
int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write); u16 opcode_write);
...@@ -94,6 +97,16 @@ static inline int btintel_check_bdaddr(struct hci_dev *hdev) ...@@ -94,6 +97,16 @@ static inline int btintel_check_bdaddr(struct hci_dev *hdev)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_enter_mfg(struct hci_dev *hdev)
{
return -EOPNOTSUPP;
}
static inline int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched)
{
return -EOPNOTSUPP;
}
static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -140,6 +153,12 @@ static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) ...@@ -140,6 +153,12 @@ static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_read_version(struct hci_dev *hdev,
struct intel_version *ver)
{
return -EOPNOTSUPP;
}
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev, static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
u16 opcode_read, u16 opcode_read,
u16 opcode_write) u16 opcode_write)
......
...@@ -153,6 +153,10 @@ static const struct usb_device_id btusb_table[] = { ...@@ -153,6 +153,10 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .driver_info = BTUSB_BCM_PATCHRAM },
/* Toshiba Corp - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
/* Intel Bluetooth USB Bootloader (RAM module) */ /* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a), { USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
...@@ -1642,13 +1646,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1642,13 +1646,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
struct sk_buff *skb; struct sk_buff *skb;
const struct firmware *fw; const struct firmware *fw;
const u8 *fw_ptr; const u8 *fw_ptr;
int disable_patch; int disable_patch, err;
struct intel_version *ver; struct intel_version ver;
const u8 mfg_enable[] = { 0x01, 0x00 };
const u8 mfg_disable[] = { 0x00, 0x00 };
const u8 mfg_reset_deactivate[] = { 0x00, 0x01 };
const u8 mfg_reset_activate[] = { 0x00, 0x02 };
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
...@@ -1674,35 +1673,22 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1674,35 +1673,22 @@ static int btusb_setup_intel(struct hci_dev *hdev)
* The returned information are hardware variant and revision plus * The returned information are hardware variant and revision plus
* firmware variant, revision and build number. * firmware variant, revision and build number.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); err = btintel_read_version(hdev, &ver);
if (IS_ERR(skb)) { if (err)
BT_ERR("%s reading Intel fw version command failed (%ld)", return err;
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s Intel version event length mismatch", hdev->name);
kfree_skb(skb);
return -EIO;
}
ver = (struct intel_version *)skb->data;
BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x", BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x",
hdev->name, ver->hw_platform, ver->hw_variant, hdev->name, ver.hw_platform, ver.hw_variant, ver.hw_revision,
ver->hw_revision, ver->fw_variant, ver->fw_revision, ver.fw_variant, ver.fw_revision, ver.fw_build_num,
ver->fw_build_num, ver->fw_build_ww, ver->fw_build_yy, ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);
ver->fw_patch_num);
/* fw_patch_num indicates the version of patch the device currently /* fw_patch_num indicates the version of patch the device currently
* have. If there is no patch data in the device, it is always 0x00. * have. If there is no patch data in the device, it is always 0x00.
* So, if it is other than 0x00, no need to patch the device again. * So, if it is other than 0x00, no need to patch the device again.
*/ */
if (ver->fw_patch_num) { if (ver.fw_patch_num) {
BT_INFO("%s: Intel device is already patched. patch num: %02x", BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num); hdev->name, ver.fw_patch_num);
kfree_skb(skb);
goto complete; goto complete;
} }
...@@ -1712,31 +1698,21 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1712,31 +1698,21 @@ static int btusb_setup_intel(struct hci_dev *hdev)
* If no patch file is found, allow the device to operate without * If no patch file is found, allow the device to operate without
* a patch. * a patch.
*/ */
fw = btusb_setup_intel_get_fw(hdev, ver); fw = btusb_setup_intel_get_fw(hdev, &ver);
if (!fw) { if (!fw)
kfree_skb(skb);
goto complete; goto complete;
}
fw_ptr = fw->data; fw_ptr = fw->data;
kfree_skb(skb); /* Enable the manufacturer mode of the controller.
/* This Intel specific command enables the manufacturer mode of the
* controller.
*
* Only while this mode is enabled, the driver can download the * Only while this mode is enabled, the driver can download the
* firmware patch data and configuration parameters. * firmware patch data and configuration parameters.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc11, 2, mfg_enable, HCI_INIT_TIMEOUT); err = btintel_enter_mfg(hdev);
if (IS_ERR(skb)) { if (err) {
BT_ERR("%s entering Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
release_firmware(fw); release_firmware(fw);
return PTR_ERR(skb); return err;
} }
kfree_skb(skb);
disable_patch = 1; disable_patch = 1;
/* The firmware data file consists of list of Intel specific HCI /* The firmware data file consists of list of Intel specific HCI
...@@ -1776,14 +1752,9 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1776,14 +1752,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
/* Patching completed successfully and disable the manufacturer mode /* Patching completed successfully and disable the manufacturer mode
* with reset and activate the downloaded firmware patches. * with reset and activate the downloaded firmware patches.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_activate), err = btintel_exit_mfg(hdev, true, true);
mfg_reset_activate, HCI_INIT_TIMEOUT); if (err)
if (IS_ERR(skb)) { return err;
BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated", BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name); hdev->name);
...@@ -1792,14 +1763,9 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1792,14 +1763,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
exit_mfg_disable: exit_mfg_disable:
/* Disable the manufacturer mode without reset */ /* Disable the manufacturer mode without reset */
skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_disable), mfg_disable, err = btintel_exit_mfg(hdev, false, false);
HCI_INIT_TIMEOUT); if (err)
if (IS_ERR(skb)) { return err;
BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
...@@ -1811,14 +1777,9 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1811,14 +1777,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
/* Patching failed. Disable the manufacturer mode with reset and /* Patching failed. Disable the manufacturer mode with reset and
* deactivate the downloaded firmware patches. * deactivate the downloaded firmware patches.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_deactivate), err = btintel_exit_mfg(hdev, true, false);
mfg_reset_deactivate, HCI_INIT_TIMEOUT); if (err)
if (IS_ERR(skb)) { return err;
BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated", BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name); hdev->name);
...@@ -2005,7 +1966,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2005,7 +1966,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
0x00, 0x08, 0x04, 0x00 }; 0x00, 0x08, 0x04, 0x00 };
struct btusb_data *data = hci_get_drvdata(hdev); struct btusb_data *data = hci_get_drvdata(hdev);
struct sk_buff *skb; struct sk_buff *skb;
struct intel_version *ver; struct intel_version ver;
struct intel_boot_params *params; struct intel_boot_params *params;
const struct firmware *fw; const struct firmware *fw;
const u8 *fw_ptr; const u8 *fw_ptr;
...@@ -2023,28 +1984,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2023,28 +1984,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* is in bootloader mode or if it already has operational firmware * is in bootloader mode or if it already has operational firmware
* loaded. * loaded.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); err = btintel_read_version(hdev, &ver);
if (IS_ERR(skb)) { if (err)
BT_ERR("%s: Reading Intel version information failed (%ld)", return err;
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s: Intel version event size mismatch", hdev->name);
kfree_skb(skb);
return -EILSEQ;
}
ver = (struct intel_version *)skb->data;
/* The hardware platform number has a fixed value of 0x37 and /* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value. * for now only accept this single value.
*/ */
if (ver->hw_platform != 0x37) { if (ver.hw_platform != 0x37) {
BT_ERR("%s: Unsupported Intel hardware platform (%u)", BT_ERR("%s: Unsupported Intel hardware platform (%u)",
hdev->name, ver->hw_platform); hdev->name, ver.hw_platform);
kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
...@@ -2053,14 +2002,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2053,14 +2002,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* put in place to ensure correct forward compatibility options * put in place to ensure correct forward compatibility options
* when newer hardware variants come along. * when newer hardware variants come along.
*/ */
if (ver->hw_variant != 0x0b) { if (ver.hw_variant != 0x0b) {
BT_ERR("%s: Unsupported Intel hardware variant (%u)", BT_ERR("%s: Unsupported Intel hardware variant (%u)",
hdev->name, ver->hw_variant); hdev->name, ver.hw_variant);
kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
btintel_version_info(hdev, ver); btintel_version_info(hdev, &ver);
/* The firmware variant determines if the device is in bootloader /* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x06 identifies * mode or is running operational firmware. The value 0x06 identifies
...@@ -2075,8 +2023,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2075,8 +2023,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* It is not possible to use the Secure Boot Parameters in this * It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode. * case since that command is only available in bootloader mode.
*/ */
if (ver->fw_variant == 0x23) { if (ver.fw_variant == 0x23) {
kfree_skb(skb);
clear_bit(BTUSB_BOOTLOADER, &data->flags); clear_bit(BTUSB_BOOTLOADER, &data->flags);
btintel_check_bdaddr(hdev); btintel_check_bdaddr(hdev);
return 0; return 0;
...@@ -2085,15 +2032,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2085,15 +2032,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
/* If the device is not in bootloader mode, then the only possible /* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization. * choice is to return an error and abort the device initialization.
*/ */
if (ver->fw_variant != 0x06) { if (ver.fw_variant != 0x06) {
BT_ERR("%s: Unsupported Intel firmware variant (%u)", BT_ERR("%s: Unsupported Intel firmware variant (%u)",
hdev->name, ver->fw_variant); hdev->name, ver.fw_variant);
kfree_skb(skb);
return -ENODEV; return -ENODEV;
} }
kfree_skb(skb);
/* Read the secure boot parameters to identify the operating /* Read the secure boot parameters to identify the operating
* details of the bootloader. * details of the bootloader.
*/ */
......
...@@ -116,18 +116,14 @@ static void h5_link_control(struct hci_uart *hu, const void *data, size_t len) ...@@ -116,18 +116,14 @@ static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
static u8 h5_cfg_field(struct h5 *h5) static u8 h5_cfg_field(struct h5 *h5)
{ {
u8 field = 0;
/* Sliding window size (first 3 bits) */ /* Sliding window size (first 3 bits) */
field |= (h5->tx_win & 0x07); return h5->tx_win & 0x07;
return field;
} }
static void h5_timed_event(unsigned long arg) 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[3] = { 0x03, 0xfc };
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;
...@@ -285,7 +281,7 @@ static void h5_handle_internal_rx(struct hci_uart *hu) ...@@ -285,7 +281,7 @@ static void h5_handle_internal_rx(struct hci_uart *hu)
struct h5 *h5 = hu->priv; struct h5 *h5 = hu->priv;
const unsigned char sync_req[] = { 0x01, 0x7e }; const unsigned char sync_req[] = { 0x01, 0x7e };
const unsigned char sync_rsp[] = { 0x02, 0x7d }; const unsigned char sync_rsp[] = { 0x02, 0x7d };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; unsigned char conf_req[3] = { 0x03, 0xfc };
const unsigned char conf_rsp[] = { 0x04, 0x7b }; const unsigned char conf_rsp[] = { 0x04, 0x7b };
const unsigned char wakeup_req[] = { 0x05, 0xfa }; const unsigned char wakeup_req[] = { 0x05, 0xfa };
const unsigned char woken_req[] = { 0x06, 0xf9 }; const unsigned char woken_req[] = { 0x06, 0xf9 };
...@@ -317,7 +313,7 @@ static void h5_handle_internal_rx(struct hci_uart *hu) ...@@ -317,7 +313,7 @@ static void h5_handle_internal_rx(struct hci_uart *hu)
h5_link_control(hu, conf_req, 3); h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_rsp, 2) == 0) { } else if (memcmp(data, conf_rsp, 2) == 0) {
if (H5_HDR_LEN(hdr) > 2) if (H5_HDR_LEN(hdr) > 2)
h5->tx_win = (data[2] & 7); h5->tx_win = (data[2] & 0x07);
BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win); BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win);
h5->state = H5_ACTIVE; h5->state = H5_ACTIVE;
hci_uart_init_ready(hu); hci_uart_init_ready(hu);
......
...@@ -502,7 +502,7 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed) ...@@ -502,7 +502,7 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
/* Device will not accept speed change if Intel version has not been /* Device will not accept speed change if Intel version has not been
* previously requested. * previously requested.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading Intel version information failed (%ld)", bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
...@@ -542,7 +542,7 @@ static int intel_setup(struct hci_uart *hu) ...@@ -542,7 +542,7 @@ static int intel_setup(struct hci_uart *hu)
struct intel_device *idev = NULL; struct intel_device *idev = NULL;
struct hci_dev *hdev = hu->hdev; struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb; struct sk_buff *skb;
struct intel_version *ver; struct intel_version ver;
struct intel_boot_params *params; struct intel_boot_params *params;
struct list_head *p; struct list_head *p;
const struct firmware *fw; const struct firmware *fw;
...@@ -590,35 +590,16 @@ static int intel_setup(struct hci_uart *hu) ...@@ -590,35 +590,16 @@ static int intel_setup(struct hci_uart *hu)
* is in bootloader mode or if it already has operational firmware * is in bootloader mode or if it already has operational firmware
* loaded. * loaded.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); err = btintel_read_version(hdev, &ver);
if (IS_ERR(skb)) { if (err)
bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
bt_dev_err(hdev, "Intel version event size mismatch");
kfree_skb(skb);
return -EILSEQ;
}
ver = (struct intel_version *)skb->data;
if (ver->status) {
bt_dev_err(hdev, "Intel version command failure (%02x)",
ver->status);
err = -bt_to_errno(ver->status);
kfree_skb(skb);
return err; return err;
}
/* The hardware platform number has a fixed value of 0x37 and /* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value. * for now only accept this single value.
*/ */
if (ver->hw_platform != 0x37) { if (ver.hw_platform != 0x37) {
bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)", bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
ver->hw_platform); ver.hw_platform);
kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
...@@ -627,14 +608,13 @@ static int intel_setup(struct hci_uart *hu) ...@@ -627,14 +608,13 @@ static int intel_setup(struct hci_uart *hu)
* put in place to ensure correct forward compatibility options * put in place to ensure correct forward compatibility options
* when newer hardware variants come along. * when newer hardware variants come along.
*/ */
if (ver->hw_variant != 0x0b) { if (ver.hw_variant != 0x0b) {
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
ver->hw_variant); ver.hw_variant);
kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
btintel_version_info(hdev, ver); btintel_version_info(hdev, &ver);
/* The firmware variant determines if the device is in bootloader /* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x06 identifies * mode or is running operational firmware. The value 0x06 identifies
...@@ -649,8 +629,7 @@ static int intel_setup(struct hci_uart *hu) ...@@ -649,8 +629,7 @@ static int intel_setup(struct hci_uart *hu)
* It is not possible to use the Secure Boot Parameters in this * It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode. * case since that command is only available in bootloader mode.
*/ */
if (ver->fw_variant == 0x23) { if (ver.fw_variant == 0x23) {
kfree_skb(skb);
clear_bit(STATE_BOOTLOADER, &intel->flags); clear_bit(STATE_BOOTLOADER, &intel->flags);
btintel_check_bdaddr(hdev); btintel_check_bdaddr(hdev);
return 0; return 0;
...@@ -659,19 +638,16 @@ static int intel_setup(struct hci_uart *hu) ...@@ -659,19 +638,16 @@ static int intel_setup(struct hci_uart *hu)
/* If the device is not in bootloader mode, then the only possible /* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization. * choice is to return an error and abort the device initialization.
*/ */
if (ver->fw_variant != 0x06) { if (ver.fw_variant != 0x06) {
bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)", bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
ver->fw_variant); ver.fw_variant);
kfree_skb(skb);
return -ENODEV; return -ENODEV;
} }
kfree_skb(skb);
/* Read the secure boot parameters to identify the operating /* Read the secure boot parameters to identify the operating
* details of the bootloader. * details of the bootloader.
*/ */
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)", bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
...@@ -881,7 +857,7 @@ static int intel_setup(struct hci_uart *hu) ...@@ -881,7 +857,7 @@ static int intel_setup(struct hci_uart *hu)
set_bit(STATE_BOOTING, &intel->flags); set_bit(STATE_BOOTING, &intel->flags);
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param, skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
HCI_INIT_TIMEOUT); HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
......
...@@ -462,13 +462,7 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -462,13 +462,7 @@ 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);
/* Flush any pending characters in the driver and line discipline. */ /* Flush any pending characters in the driver */
/* FIXME: why is this needed. Note don't use ldisc_ref here as the
open path is before the ldisc is referencable */
if (tty->ldisc->ops->flush_buffer)
tty->ldisc->ops->flush_buffer(tty);
tty_driver_flush_buffer(tty); tty_driver_flush_buffer(tty);
return 0; return 0;
......
...@@ -71,3 +71,14 @@ config IEEE802154_ATUSB ...@@ -71,3 +71,14 @@ config IEEE802154_ATUSB
This driver can also be built as a module. To do so say M here. This driver can also be built as a module. To do so say M here.
The module will be called 'atusb'. The module will be called 'atusb'.
config IEEE802154_ADF7242
tristate "ADF7242 transceiver driver"
depends on IEEE802154_DRIVERS && MAC802154
depends on SPI
---help---
Say Y here to enable the ADF7242 SPI 802.15.4 wireless
controller.
This driver can also be built as a module. To do so, say M here.
the module will be called 'adf7242'.
...@@ -3,3 +3,4 @@ obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o ...@@ -3,3 +3,4 @@ obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
obj-$(CONFIG_IEEE802154_CC2520) += cc2520.o obj-$(CONFIG_IEEE802154_CC2520) += cc2520.o
obj-$(CONFIG_IEEE802154_ATUSB) += atusb.o obj-$(CONFIG_IEEE802154_ATUSB) += atusb.o
obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
This diff is collapsed.
...@@ -310,7 +310,6 @@ static void atusb_free_urbs(struct atusb *atusb) ...@@ -310,7 +310,6 @@ static void atusb_free_urbs(struct atusb *atusb)
urb = usb_get_from_anchor(&atusb->idle_urbs); urb = usb_get_from_anchor(&atusb->idle_urbs);
if (!urb) if (!urb)
break; break;
if (urb->context)
kfree_skb(urb->context); kfree_skb(urb->context);
usb_free_urb(urb); usb_free_urb(urb);
} }
......
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
#ifndef __6LOWPAN_H__ #ifndef __6LOWPAN_H__
#define __6LOWPAN_H__ #define __6LOWPAN_H__
#include <linux/debugfs.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
...@@ -98,6 +100,7 @@ enum lowpan_lltypes { ...@@ -98,6 +100,7 @@ enum lowpan_lltypes {
struct lowpan_priv { struct lowpan_priv {
enum lowpan_lltypes lltype; enum lowpan_lltypes lltype;
struct dentry *iface_debugfs;
/* must be last */ /* must be last */
u8 priv[0] __aligned(sizeof(void *)); u8 priv[0] __aligned(sizeof(void *));
...@@ -185,7 +188,12 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data, ...@@ -185,7 +188,12 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
*hc_ptr += len; *hc_ptr += len;
} }
void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype); int lowpan_register_netdevice(struct net_device *dev,
enum lowpan_lltypes lltype);
int lowpan_register_netdev(struct net_device *dev,
enum lowpan_lltypes lltype);
void lowpan_unregister_netdevice(struct net_device *dev);
void lowpan_unregister_netdev(struct net_device *dev);
/** /**
* lowpan_header_decompress - replace 6LoWPAN header with IPv6 header * lowpan_header_decompress - replace 6LoWPAN header with IPv6 header
......
...@@ -239,7 +239,6 @@ enum { ...@@ -239,7 +239,6 @@ enum {
HCI_LE_ENABLED, HCI_LE_ENABLED,
HCI_ADVERTISING, HCI_ADVERTISING,
HCI_ADVERTISING_CONNECTABLE, HCI_ADVERTISING_CONNECTABLE,
HCI_ADVERTISING_INSTANCE,
HCI_CONNECTABLE, HCI_CONNECTABLE,
HCI_DISCOVERABLE, HCI_DISCOVERABLE,
HCI_LIMITED_DISCOVERABLE, HCI_LIMITED_DISCOVERABLE,
......
...@@ -329,6 +329,9 @@ struct hci_dev { ...@@ -329,6 +329,9 @@ struct hci_dev {
struct work_struct discov_update; struct work_struct discov_update;
struct work_struct bg_scan_update; struct work_struct bg_scan_update;
struct work_struct scan_update;
struct work_struct connectable_update;
struct work_struct discoverable_update;
struct delayed_work le_scan_disable; struct delayed_work le_scan_disable;
struct delayed_work le_scan_restart; struct delayed_work le_scan_restart;
...@@ -1432,10 +1435,8 @@ int mgmt_new_settings(struct hci_dev *hdev); ...@@ -1432,10 +1435,8 @@ int mgmt_new_settings(struct hci_dev *hdev);
void mgmt_index_added(struct hci_dev *hdev); void mgmt_index_added(struct hci_dev *hdev);
void mgmt_index_removed(struct hci_dev *hdev); void mgmt_index_removed(struct hci_dev *hdev);
void mgmt_set_powered_failed(struct hci_dev *hdev, int err); void mgmt_set_powered_failed(struct hci_dev *hdev, int err);
int mgmt_powered(struct hci_dev *hdev, u8 powered); void mgmt_power_on(struct hci_dev *hdev, int err);
int mgmt_update_adv_data(struct hci_dev *hdev); void __mgmt_power_off(struct hci_dev *hdev);
void mgmt_discoverable_timeout(struct hci_dev *hdev);
void mgmt_adv_timeout_expired(struct hci_dev *hdev);
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent); bool persistent);
void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn, void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
...@@ -1490,8 +1491,15 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, ...@@ -1490,8 +1491,15 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 bdaddr_type, u8 store_hint, u16 min_interval, u8 bdaddr_type, u8 store_hint, u16 min_interval,
u16 max_interval, u16 latency, u16 timeout); u16 max_interval, u16 latency, u16 timeout);
void mgmt_reenable_advertising(struct hci_dev *hdev);
void mgmt_smp_complete(struct hci_conn *conn, bool complete); void mgmt_smp_complete(struct hci_conn *conn, bool complete);
bool mgmt_get_connectable(struct hci_dev *hdev);
void mgmt_set_connectable_complete(struct hci_dev *hdev, u8 status);
void mgmt_set_discoverable_complete(struct hci_dev *hdev, u8 status);
u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev);
void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
u8 instance);
void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
u8 instance);
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
u16 to_multiplier); u16 to_multiplier);
......
...@@ -401,6 +401,21 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx, ...@@ -401,6 +401,21 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx,
pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b); pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
} }
static inline void ipv6_addr_prefix_copy(struct in6_addr *addr,
const struct in6_addr *pfx,
int plen)
{
/* caller must guarantee 0 <= plen <= 128 */
int o = plen >> 3,
b = plen & 0x7;
memcpy(addr->s6_addr, pfx, o);
if (b != 0) {
addr->s6_addr[o] &= ~(0xff00 >> b);
addr->s6_addr[o] |= (pfx->s6_addr[o] & (0xff00 >> b));
}
}
static inline void __ipv6_addr_set_half(__be32 *addr, static inline void __ipv6_addr_set_half(__be32 *addr,
__be32 wh, __be32 wl) __be32 wh, __be32 wl)
{ {
......
#ifndef __6LOWPAN_I_H
#define __6LOWPAN_I_H
#include <linux/netdevice.h>
#ifdef CONFIG_6LOWPAN_DEBUGFS
int lowpan_dev_debugfs_init(struct net_device *dev);
void lowpan_dev_debugfs_exit(struct net_device *dev);
int __init lowpan_debugfs_init(void);
void lowpan_debugfs_exit(void);
#else
static inline int lowpan_dev_debugfs_init(struct net_device *dev)
{
return 0;
}
static inline void lowpan_dev_debugfs_exit(struct net_device *dev) { }
static inline int __init lowpan_debugfs_init(void)
{
return 0;
}
static inline void lowpan_debugfs_exit(void) { }
#endif /* CONFIG_6LOWPAN_DEBUGFS */
#endif /* __6LOWPAN_I_H */
...@@ -5,12 +5,21 @@ menuconfig 6LOWPAN ...@@ -5,12 +5,21 @@ menuconfig 6LOWPAN
This enables IPv6 over Low power Wireless Personal Area Network - This enables IPv6 over Low power Wireless Personal Area Network -
"6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks. "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks.
config 6LOWPAN_DEBUGFS
bool "6LoWPAN debugfs support"
depends on 6LOWPAN
depends on DEBUG_FS
---help---
This enables 6LoWPAN debugfs support. For example to manipulate
IPHC context information at runtime.
menuconfig 6LOWPAN_NHC menuconfig 6LOWPAN_NHC
tristate "Next Header Compression Support" tristate "Next Header and Generic Header Compression Support"
depends on 6LOWPAN depends on 6LOWPAN
default y default y
---help--- ---help---
Support for next header compression. Support for next header and generic header compression defined in
RFC6282 and RFC7400.
if 6LOWPAN_NHC if 6LOWPAN_NHC
...@@ -58,4 +67,38 @@ config 6LOWPAN_NHC_UDP ...@@ -58,4 +67,38 @@ config 6LOWPAN_NHC_UDP
---help--- ---help---
6LoWPAN IPv6 UDP Header compression according to RFC6282. 6LoWPAN IPv6 UDP Header compression according to RFC6282.
config 6LOWPAN_GHC_EXT_HDR_HOP
tristate "GHC Hop-by-Hop Options Header Support"
---help---
6LoWPAN IPv6 Hop-by-Hop option generic header compression according
to RFC7400.
config 6LOWPAN_GHC_UDP
tristate "GHC UDP Support"
---help---
6LoWPAN IPv6 UDP generic header compression according to RFC7400.
config 6LOWPAN_GHC_ICMPV6
tristate "GHC ICMPv6 Support"
---help---
6LoWPAN IPv6 ICMPv6 generic header compression according to RFC7400.
config 6LOWPAN_GHC_EXT_HDR_DEST
tristate "GHC Destination Options Header Support"
---help---
6LoWPAN IPv6 destination option generic header compression according
to RFC7400.
config 6LOWPAN_GHC_EXT_HDR_FRAG
tristate "GHC Fragmentation Options Header Support"
---help---
6LoWPAN IPv6 fragmentation option generic header compression
according to RFC7400.
config 6LOWPAN_GHC_EXT_HDR_ROUTE
tristate "GHC Routing Options Header Support"
---help---
6LoWPAN IPv6 routing option generic header compression according
to RFC7400.
endif endif
obj-$(CONFIG_6LOWPAN) += 6lowpan.o obj-$(CONFIG_6LOWPAN) += 6lowpan.o
6lowpan-y := core.o iphc.o nhc.o 6lowpan-y := core.o iphc.o nhc.o
6lowpan-$(CONFIG_6LOWPAN_DEBUGFS) += debugfs.o
#rfc6282 nhcs #rfc6282 nhcs
obj-$(CONFIG_6LOWPAN_NHC_DEST) += nhc_dest.o obj-$(CONFIG_6LOWPAN_NHC_DEST) += nhc_dest.o
...@@ -10,3 +11,11 @@ obj-$(CONFIG_6LOWPAN_NHC_IPV6) += nhc_ipv6.o ...@@ -10,3 +11,11 @@ obj-$(CONFIG_6LOWPAN_NHC_IPV6) += nhc_ipv6.o
obj-$(CONFIG_6LOWPAN_NHC_MOBILITY) += nhc_mobility.o obj-$(CONFIG_6LOWPAN_NHC_MOBILITY) += nhc_mobility.o
obj-$(CONFIG_6LOWPAN_NHC_ROUTING) += nhc_routing.o obj-$(CONFIG_6LOWPAN_NHC_ROUTING) += nhc_routing.o
obj-$(CONFIG_6LOWPAN_NHC_UDP) += nhc_udp.o obj-$(CONFIG_6LOWPAN_NHC_UDP) += nhc_udp.o
#rfc7400 ghcs
obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_HOP) += nhc_ghc_ext_hop.o
obj-$(CONFIG_6LOWPAN_GHC_UDP) += nhc_ghc_udp.o
obj-$(CONFIG_6LOWPAN_GHC_ICMPV6) += nhc_ghc_icmpv6.o
obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_DEST) += nhc_ghc_ext_dest.o
obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG) += nhc_ghc_ext_frag.o
obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE) += nhc_ghc_ext_route.o
...@@ -15,19 +15,67 @@ ...@@ -15,19 +15,67 @@
#include <net/6lowpan.h> #include <net/6lowpan.h>
void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype) #include "6lowpan_i.h"
int lowpan_register_netdevice(struct net_device *dev,
enum lowpan_lltypes lltype)
{ {
int ret;
dev->addr_len = EUI64_ADDR_LEN; dev->addr_len = EUI64_ADDR_LEN;
dev->type = ARPHRD_6LOWPAN; dev->type = ARPHRD_6LOWPAN;
dev->mtu = IPV6_MIN_MTU; dev->mtu = IPV6_MIN_MTU;
dev->priv_flags |= IFF_NO_QUEUE; dev->priv_flags |= IFF_NO_QUEUE;
lowpan_priv(dev)->lltype = lltype; lowpan_priv(dev)->lltype = lltype;
ret = lowpan_dev_debugfs_init(dev);
if (ret < 0)
return ret;
ret = register_netdevice(dev);
if (ret < 0)
lowpan_dev_debugfs_exit(dev);
return ret;
} }
EXPORT_SYMBOL(lowpan_netdev_setup); EXPORT_SYMBOL(lowpan_register_netdevice);
int lowpan_register_netdev(struct net_device *dev,
enum lowpan_lltypes lltype)
{
int ret;
rtnl_lock();
ret = lowpan_register_netdevice(dev, lltype);
rtnl_unlock();
return ret;
}
EXPORT_SYMBOL(lowpan_register_netdev);
void lowpan_unregister_netdevice(struct net_device *dev)
{
unregister_netdevice(dev);
lowpan_dev_debugfs_exit(dev);
}
EXPORT_SYMBOL(lowpan_unregister_netdevice);
void lowpan_unregister_netdev(struct net_device *dev)
{
rtnl_lock();
lowpan_unregister_netdevice(dev);
rtnl_unlock();
}
EXPORT_SYMBOL(lowpan_unregister_netdev);
static int __init lowpan_module_init(void) static int __init lowpan_module_init(void)
{ {
int ret;
ret = lowpan_debugfs_init();
if (ret < 0)
return ret;
request_module_nowait("ipv6"); request_module_nowait("ipv6");
request_module_nowait("nhc_dest"); request_module_nowait("nhc_dest");
...@@ -40,6 +88,13 @@ static int __init lowpan_module_init(void) ...@@ -40,6 +88,13 @@ static int __init lowpan_module_init(void)
return 0; return 0;
} }
static void __exit lowpan_module_exit(void)
{
lowpan_debugfs_exit();
}
module_init(lowpan_module_init); module_init(lowpan_module_init);
module_exit(lowpan_module_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Authors:
* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
*/
#include <net/6lowpan.h>
#include "6lowpan_i.h"
static struct dentry *lowpan_debugfs;
int lowpan_dev_debugfs_init(struct net_device *dev)
{
struct lowpan_priv *lpriv = lowpan_priv(dev);
/* creating the root */
lpriv->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs);
if (!lpriv->iface_debugfs)
goto fail;
return 0;
fail:
return -EINVAL;
}
void lowpan_dev_debugfs_exit(struct net_device *dev)
{
debugfs_remove_recursive(lowpan_priv(dev)->iface_debugfs);
}
int __init lowpan_debugfs_init(void)
{
lowpan_debugfs = debugfs_create_dir("6lowpan", NULL);
if (!lowpan_debugfs)
return -EINVAL;
return 0;
}
void lowpan_debugfs_exit(void)
{
debugfs_remove_recursive(lowpan_debugfs);
}
/*
* 6LoWPAN Extension Header compression according to RFC7400
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "nhc.h"
#define LOWPAN_GHC_EXT_DEST_IDLEN 1
#define LOWPAN_GHC_EXT_DEST_ID_0 0xb6
#define LOWPAN_GHC_EXT_DEST_MASK_0 0xfe
static void dest_ghid_setup(struct lowpan_nhc *nhc)
{
nhc->id[0] = LOWPAN_GHC_EXT_DEST_ID_0;
nhc->idmask[0] = LOWPAN_GHC_EXT_DEST_MASK_0;
}
LOWPAN_NHC(ghc_ext_dest, "RFC7400 Destination Extension Header", NEXTHDR_DEST,
0, dest_ghid_setup, LOWPAN_GHC_EXT_DEST_IDLEN, NULL, NULL);
module_lowpan_nhc(ghc_ext_dest);
MODULE_DESCRIPTION("6LoWPAN generic header destination extension compression");
MODULE_LICENSE("GPL");
/*
* 6LoWPAN Extension Header compression according to RFC7400
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "nhc.h"
#define LOWPAN_GHC_EXT_FRAG_IDLEN 1
#define LOWPAN_GHC_EXT_FRAG_ID_0 0xb4
#define LOWPAN_GHC_EXT_FRAG_MASK_0 0xfe
static void frag_ghid_setup(struct lowpan_nhc *nhc)
{
nhc->id[0] = LOWPAN_GHC_EXT_FRAG_ID_0;
nhc->idmask[0] = LOWPAN_GHC_EXT_FRAG_MASK_0;
}
LOWPAN_NHC(ghc_ext_frag, "RFC7400 Fragmentation Extension Header",
NEXTHDR_FRAGMENT, 0, frag_ghid_setup,
LOWPAN_GHC_EXT_FRAG_IDLEN, NULL, NULL);
module_lowpan_nhc(ghc_ext_frag);
MODULE_DESCRIPTION("6LoWPAN generic header fragmentation extension compression");
MODULE_LICENSE("GPL");
/*
* 6LoWPAN Extension Header compression according to RFC7400
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "nhc.h"
#define LOWPAN_GHC_EXT_HOP_IDLEN 1
#define LOWPAN_GHC_EXT_HOP_ID_0 0xb0
#define LOWPAN_GHC_EXT_HOP_MASK_0 0xfe
static void hop_ghid_setup(struct lowpan_nhc *nhc)
{
nhc->id[0] = LOWPAN_GHC_EXT_HOP_ID_0;
nhc->idmask[0] = LOWPAN_GHC_EXT_HOP_MASK_0;
}
LOWPAN_NHC(ghc_ext_hop, "RFC7400 Hop-by-Hop Extension Header", NEXTHDR_HOP, 0,
hop_ghid_setup, LOWPAN_GHC_EXT_HOP_IDLEN, NULL, NULL);
module_lowpan_nhc(ghc_ext_hop);
MODULE_DESCRIPTION("6LoWPAN generic header hop-by-hop extension compression");
MODULE_LICENSE("GPL");
/*
* 6LoWPAN Extension Header compression according to RFC7400
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "nhc.h"
#define LOWPAN_GHC_EXT_ROUTE_IDLEN 1
#define LOWPAN_GHC_EXT_ROUTE_ID_0 0xb2
#define LOWPAN_GHC_EXT_ROUTE_MASK_0 0xfe
static void route_ghid_setup(struct lowpan_nhc *nhc)
{
nhc->id[0] = LOWPAN_GHC_EXT_ROUTE_ID_0;
nhc->idmask[0] = LOWPAN_GHC_EXT_ROUTE_MASK_0;
}
LOWPAN_NHC(ghc_ext_route, "RFC7400 Routing Extension Header", NEXTHDR_ROUTING,
0, route_ghid_setup, LOWPAN_GHC_EXT_ROUTE_IDLEN, NULL, NULL);
module_lowpan_nhc(ghc_ext_route);
MODULE_DESCRIPTION("6LoWPAN generic header routing extension compression");
MODULE_LICENSE("GPL");
/*
* 6LoWPAN ICMPv6 compression according to RFC7400
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "nhc.h"
#define LOWPAN_GHC_ICMPV6_IDLEN 1
#define LOWPAN_GHC_ICMPV6_ID_0 0xdf
#define LOWPAN_GHC_ICMPV6_MASK_0 0xff
static void icmpv6_ghid_setup(struct lowpan_nhc *nhc)
{
nhc->id[0] = LOWPAN_GHC_ICMPV6_ID_0;
nhc->idmask[0] = LOWPAN_GHC_ICMPV6_MASK_0;
}
LOWPAN_NHC(ghc_icmpv6, "RFC7400 ICMPv6", NEXTHDR_ICMP, 0,
icmpv6_ghid_setup, LOWPAN_GHC_ICMPV6_IDLEN, NULL, NULL);
module_lowpan_nhc(ghc_icmpv6);
MODULE_DESCRIPTION("6LoWPAN generic header ICMPv6 compression");
MODULE_LICENSE("GPL");
/*
* 6LoWPAN UDP compression according to RFC7400
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "nhc.h"
#define LOWPAN_GHC_UDP_IDLEN 1
#define LOWPAN_GHC_UDP_ID_0 0xd0
#define LOWPAN_GHC_UDP_MASK_0 0xf8
static void udp_ghid_setup(struct lowpan_nhc *nhc)
{
nhc->id[0] = LOWPAN_GHC_UDP_ID_0;
nhc->idmask[0] = LOWPAN_GHC_UDP_MASK_0;
}
LOWPAN_NHC(ghc_udp, "RFC7400 UDP", NEXTHDR_UDP, 0,
udp_ghid_setup, LOWPAN_GHC_UDP_IDLEN, NULL, NULL);
module_lowpan_nhc(ghc_udp);
MODULE_DESCRIPTION("6LoWPAN generic header UDP compression");
MODULE_LICENSE("GPL");
...@@ -825,9 +825,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) ...@@ -825,9 +825,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev)
list_add_rcu(&(*dev)->list, &bt_6lowpan_devices); list_add_rcu(&(*dev)->list, &bt_6lowpan_devices);
spin_unlock(&devices_lock); spin_unlock(&devices_lock);
lowpan_netdev_setup(netdev, LOWPAN_LLTYPE_BTLE); err = lowpan_register_netdev(netdev, LOWPAN_LLTYPE_BTLE);
err = register_netdev(netdev);
if (err < 0) { if (err < 0) {
BT_INFO("register_netdev failed %d", err); BT_INFO("register_netdev failed %d", err);
spin_lock(&devices_lock); spin_lock(&devices_lock);
...@@ -890,7 +888,7 @@ static void delete_netdev(struct work_struct *work) ...@@ -890,7 +888,7 @@ static void delete_netdev(struct work_struct *work)
struct lowpan_dev *entry = container_of(work, struct lowpan_dev, struct lowpan_dev *entry = container_of(work, struct lowpan_dev,
delete_netdev); delete_netdev);
unregister_netdev(entry->netdev); lowpan_unregister_netdev(entry->netdev);
/* The entry pointer is deleted by the netdev destructor. */ /* The entry pointer is deleted by the netdev destructor. */
} }
...@@ -1348,7 +1346,7 @@ static void disconnect_devices(void) ...@@ -1348,7 +1346,7 @@ static void disconnect_devices(void)
ifdown(entry->netdev); ifdown(entry->netdev);
BT_DBG("Unregistering netdev %s %p", BT_DBG("Unregistering netdev %s %p",
entry->netdev->name, entry->netdev); entry->netdev->name, entry->netdev);
unregister_netdev(entry->netdev); lowpan_unregister_netdev(entry->netdev);
kfree(entry); kfree(entry);
} }
} }
......
...@@ -186,8 +186,8 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) ...@@ -186,8 +186,8 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
/* FIXME: Is this check still needed */ /* FIXME: Is this check still needed */
if (sk->sk_state == BT_CLOSED) { if (sk->sk_state == BT_CLOSED) {
release_sock(sk);
bt_accept_unlink(sk); bt_accept_unlink(sk);
release_sock(sk);
continue; continue;
} }
......
...@@ -608,8 +608,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -608,8 +608,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
s->msg.msg_flags = MSG_NOSIGNAL; s->msg.msg_flags = MSG_NOSIGNAL;
#ifdef CONFIG_BT_BNEP_MC_FILTER #ifdef CONFIG_BT_BNEP_MC_FILTER
/* Set default mc filter */ /* Set default mc filter to not filter out any mc addresses
set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter); * as defined in the BNEP specification (revision 0.95a)
* http://grouper.ieee.org/groups/802/15/Bluetooth/BNEP.pdf
*/
s->mc_filter = ~0LL;
#endif #endif
#ifdef CONFIG_BT_BNEP_PROTO_FILTER #ifdef CONFIG_BT_BNEP_PROTO_FILTER
......
...@@ -668,8 +668,16 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status) ...@@ -668,8 +668,16 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
conn->state = BT_CLOSED; conn->state = BT_CLOSED;
mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, /* If the status indicates successful cancellation of
status); * the attempt (i.e. Unkown Connection Id) there's no point of
* notifying failure since we'll go back to keep trying to
* connect. The only exception is explicit connect requests
* where a timeout + cancel does indicate an actual failure.
*/
if (status != HCI_ERROR_UNKNOWN_CONN_ID ||
(params && params->explicit_connect))
mgmt_connect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, status);
hci_connect_cfm(conn, status); hci_connect_cfm(conn, status);
...@@ -683,7 +691,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status) ...@@ -683,7 +691,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
/* Re-enable advertising in case this was a failed connection /* Re-enable advertising in case this was a failed connection
* attempt as a peripheral. * attempt as a peripheral.
*/ */
mgmt_reenable_advertising(hdev); hci_req_reenable_advertising(hdev);
} }
static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode)
...@@ -726,8 +734,12 @@ static void hci_req_add_le_create_conn(struct hci_request *req, ...@@ -726,8 +734,12 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
if (hci_update_random_address(req, false, &own_addr_type)) if (hci_update_random_address(req, false, &own_addr_type))
return; return;
/* Set window to be the same value as the interval to enable
* continuous scanning.
*/
cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
cp.scan_window = cpu_to_le16(hdev->le_scan_window); cp.scan_window = cp.scan_interval;
bacpy(&cp.peer_addr, &conn->dst); bacpy(&cp.peer_addr, &conn->dst);
cp.peer_addr_type = conn->dst_type; cp.peer_addr_type = conn->dst_type;
cp.own_address_type = own_addr_type; cp.own_address_type = own_addr_type;
......
...@@ -1399,10 +1399,10 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1399,10 +1399,10 @@ static int hci_dev_do_open(struct hci_dev *hdev)
!hci_dev_test_flag(hdev, HCI_CONFIG) && !hci_dev_test_flag(hdev, HCI_CONFIG) &&
!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hci_dev_test_flag(hdev, HCI_MGMT) &&
hdev->dev_type == HCI_BREDR) { hdev->dev_type == HCI_BREDR) {
hci_dev_lock(hdev); ret = __hci_req_hci_power_on(hdev);
mgmt_powered(hdev, 1); mgmt_power_on(hdev, ret);
hci_dev_unlock(hdev);
} }
} else { } else {
/* Init failed, cleanup */ /* Init failed, cleanup */
...@@ -1537,7 +1537,6 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1537,7 +1537,6 @@ int hci_dev_do_close(struct hci_dev *hdev)
flush_work(&hdev->rx_work); flush_work(&hdev->rx_work);
if (hdev->discov_timeout > 0) { if (hdev->discov_timeout > 0) {
cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = 0; hdev->discov_timeout = 0;
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
...@@ -1549,11 +1548,6 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1549,11 +1548,6 @@ int hci_dev_do_close(struct hci_dev *hdev)
if (hci_dev_test_flag(hdev, HCI_MGMT)) if (hci_dev_test_flag(hdev, HCI_MGMT))
cancel_delayed_work_sync(&hdev->rpa_expired); cancel_delayed_work_sync(&hdev->rpa_expired);
if (hdev->adv_instance_timeout) {
cancel_delayed_work_sync(&hdev->adv_instance_expire);
hdev->adv_instance_timeout = 0;
}
/* Avoid potential lockdep warnings from the *_flush() calls by /* Avoid potential lockdep warnings from the *_flush() calls by
* ensuring the workqueue is empty up front. * ensuring the workqueue is empty up front.
*/ */
...@@ -1565,8 +1559,9 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1565,8 +1559,9 @@ int hci_dev_do_close(struct hci_dev *hdev)
auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF);
if (!auto_off && hdev->dev_type == HCI_BREDR) if (!auto_off && hdev->dev_type == HCI_BREDR &&
mgmt_powered(hdev, 0); hci_dev_test_flag(hdev, HCI_MGMT))
__mgmt_power_off(hdev);
hci_inquiry_cache_flush(hdev); hci_inquiry_cache_flush(hdev);
hci_pend_le_actions_clear(hdev); hci_pend_le_actions_clear(hdev);
...@@ -1774,7 +1769,7 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) ...@@ -1774,7 +1769,7 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan)
hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
mgmt_update_adv_data(hdev); hci_req_update_adv_data(hdev, hdev->cur_adv_instance);
mgmt_new_settings(hdev); mgmt_new_settings(hdev);
} }
...@@ -2019,6 +2014,16 @@ static void hci_power_on(struct work_struct *work) ...@@ -2019,6 +2014,16 @@ static void hci_power_on(struct work_struct *work)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (test_bit(HCI_UP, &hdev->flags) &&
hci_dev_test_flag(hdev, HCI_MGMT) &&
hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
hci_req_sync_lock(hdev);
err = __hci_req_hci_power_on(hdev);
hci_req_sync_unlock(hdev);
mgmt_power_on(hdev, err);
return;
}
err = hci_dev_do_open(hdev); err = hci_dev_do_open(hdev);
if (err < 0) { if (err < 0) {
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2101,28 +2106,6 @@ static void hci_error_reset(struct work_struct *work) ...@@ -2101,28 +2106,6 @@ static void hci_error_reset(struct work_struct *work)
hci_dev_do_open(hdev); hci_dev_do_open(hdev);
} }
static void hci_discov_off(struct work_struct *work)
{
struct hci_dev *hdev;
hdev = container_of(work, struct hci_dev, discov_off.work);
BT_DBG("%s", hdev->name);
mgmt_discoverable_timeout(hdev);
}
static void hci_adv_timeout_expire(struct work_struct *work)
{
struct hci_dev *hdev;
hdev = container_of(work, struct hci_dev, adv_instance_expire.work);
BT_DBG("%s", hdev->name);
mgmt_adv_timeout_expired(hdev);
}
void hci_uuids_clear(struct hci_dev *hdev) void hci_uuids_clear(struct hci_dev *hdev)
{ {
struct bt_uuid *uuid, *tmp; struct bt_uuid *uuid, *tmp;
...@@ -2627,10 +2610,13 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance) ...@@ -2627,10 +2610,13 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance)
BT_DBG("%s removing %dMR", hdev->name, instance); BT_DBG("%s removing %dMR", hdev->name, instance);
if (hdev->cur_adv_instance == instance && hdev->adv_instance_timeout) { if (hdev->cur_adv_instance == instance) {
if (hdev->adv_instance_timeout) {
cancel_delayed_work(&hdev->adv_instance_expire); cancel_delayed_work(&hdev->adv_instance_expire);
hdev->adv_instance_timeout = 0; hdev->adv_instance_timeout = 0;
} }
hdev->cur_adv_instance = 0x00;
}
list_del(&adv_instance->list); list_del(&adv_instance->list);
kfree(adv_instance); kfree(adv_instance);
...@@ -2656,6 +2642,7 @@ void hci_adv_instances_clear(struct hci_dev *hdev) ...@@ -2656,6 +2642,7 @@ void hci_adv_instances_clear(struct hci_dev *hdev)
} }
hdev->adv_instance_cnt = 0; hdev->adv_instance_cnt = 0;
hdev->cur_adv_instance = 0x00;
} }
/* This function requires the caller holds hdev->lock */ /* This function requires the caller holds hdev->lock */
...@@ -3002,8 +2989,6 @@ struct hci_dev *hci_alloc_dev(void) ...@@ -3002,8 +2989,6 @@ struct hci_dev *hci_alloc_dev(void)
INIT_WORK(&hdev->error_reset, hci_error_reset); INIT_WORK(&hdev->error_reset, hci_error_reset);
INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
INIT_DELAYED_WORK(&hdev->adv_instance_expire, hci_adv_timeout_expire);
skb_queue_head_init(&hdev->rx_q); skb_queue_head_init(&hdev->rx_q);
skb_queue_head_init(&hdev->cmd_q); skb_queue_head_init(&hdev->cmd_q);
......
...@@ -1183,7 +1183,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, ...@@ -1183,7 +1183,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) &&
hdev->discovery.state == DISCOVERY_FINDING) hdev->discovery.state == DISCOVERY_FINDING)
mgmt_reenable_advertising(hdev); hci_req_reenable_advertising(hdev);
break; break;
...@@ -2176,7 +2176,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2176,7 +2176,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
sizeof(cp), &cp); sizeof(cp), &cp);
hci_update_page_scan(hdev); hci_req_update_scan(hdev);
} }
/* Set packet type for incoming connection */ /* Set packet type for incoming connection */
...@@ -2362,7 +2362,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2362,7 +2362,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
hci_remove_link_key(hdev, &conn->dst); hci_remove_link_key(hdev, &conn->dst);
hci_update_page_scan(hdev); hci_req_update_scan(hdev);
} }
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
...@@ -2401,7 +2401,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2401,7 +2401,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
* is timed out due to Directed Advertising." * is timed out due to Directed Advertising."
*/ */
if (type == LE_LINK) if (type == LE_LINK)
mgmt_reenable_advertising(hdev); hci_req_reenable_advertising(hdev);
unlock: unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
This diff is collapsed.
...@@ -55,14 +55,38 @@ void hci_req_sync_cancel(struct hci_dev *hdev, int err); ...@@ -55,14 +55,38 @@ void hci_req_sync_cancel(struct hci_dev *hdev, int err);
struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param); const void *param);
int __hci_req_hci_power_on(struct hci_dev *hdev);
void __hci_req_write_fast_connectable(struct hci_request *req, bool enable);
void __hci_req_update_name(struct hci_request *req);
void __hci_req_update_eir(struct hci_request *req);
void hci_req_add_le_scan_disable(struct hci_request *req); void hci_req_add_le_scan_disable(struct hci_request *req);
void hci_req_add_le_passive_scan(struct hci_request *req); void hci_req_add_le_passive_scan(struct hci_request *req);
void hci_req_reenable_advertising(struct hci_dev *hdev);
void __hci_req_enable_advertising(struct hci_request *req);
void __hci_req_disable_advertising(struct hci_request *req);
void __hci_req_update_adv_data(struct hci_request *req, u8 instance);
int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance);
void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance);
int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
bool force);
void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req,
u8 instance, bool force);
void __hci_req_update_class(struct hci_request *req);
/* Returns true if HCI commands were queued */ /* Returns true if HCI commands were queued */
bool hci_req_stop_discovery(struct hci_request *req); bool hci_req_stop_discovery(struct hci_request *req);
void hci_update_page_scan(struct hci_dev *hdev); static inline void hci_req_update_scan(struct hci_dev *hdev)
void __hci_update_page_scan(struct hci_request *req); {
queue_work(hdev->req_workqueue, &hdev->scan_update);
}
void __hci_req_update_scan(struct hci_request *req);
int hci_update_random_address(struct hci_request *req, bool require_privacy, int hci_update_random_address(struct hci_request *req, bool require_privacy,
u8 *own_addr_type); u8 *own_addr_type);
......
This diff is collapsed.
...@@ -161,9 +161,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev, ...@@ -161,9 +161,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
wdev->needed_headroom; wdev->needed_headroom;
ldev->needed_tailroom = wdev->needed_tailroom; ldev->needed_tailroom = wdev->needed_tailroom;
lowpan_netdev_setup(ldev, LOWPAN_LLTYPE_IEEE802154); ret = lowpan_register_netdevice(ldev, LOWPAN_LLTYPE_IEEE802154);
ret = register_netdevice(ldev);
if (ret < 0) { if (ret < 0) {
dev_put(wdev); dev_put(wdev);
return ret; return ret;
...@@ -180,7 +178,7 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head) ...@@ -180,7 +178,7 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
ASSERT_RTNL(); ASSERT_RTNL();
wdev->ieee802154_ptr->lowpan_dev = NULL; wdev->ieee802154_ptr->lowpan_dev = NULL;
unregister_netdevice(ldev); lowpan_unregister_netdevice(ldev);
dev_put(wdev); dev_put(wdev);
} }
......
...@@ -18,9 +18,6 @@ drv_xmit_async(struct ieee802154_local *local, struct sk_buff *skb) ...@@ -18,9 +18,6 @@ drv_xmit_async(struct ieee802154_local *local, struct sk_buff *skb)
static inline int static inline int
drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb) drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb)
{ {
/* don't allow other operations while sync xmit */
ASSERT_RTNL();
might_sleep(); might_sleep();
return local->ops->xmit_sync(&local->hw, skb); return local->ops->xmit_sync(&local->hw, skb);
......
...@@ -38,12 +38,6 @@ void ieee802154_xmit_worker(struct work_struct *work) ...@@ -38,12 +38,6 @@ void ieee802154_xmit_worker(struct work_struct *work)
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
int res; int res;
rtnl_lock();
/* check if ifdown occurred while schedule */
if (!netif_running(dev))
goto err_tx;
res = drv_xmit_sync(local, skb); res = drv_xmit_sync(local, skb);
if (res) if (res)
goto err_tx; goto err_tx;
...@@ -53,14 +47,11 @@ void ieee802154_xmit_worker(struct work_struct *work) ...@@ -53,14 +47,11 @@ void ieee802154_xmit_worker(struct work_struct *work)
dev->stats.tx_packets++; dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len; dev->stats.tx_bytes += skb->len;
rtnl_unlock();
return; return;
err_tx: err_tx:
/* Restart the netif queue on each sub_if_data object. */ /* Restart the netif queue on each sub_if_data object. */
ieee802154_wake_queue(&local->hw); ieee802154_wake_queue(&local->hw);
rtnl_unlock();
kfree_skb(skb); kfree_skb(skb);
netdev_dbg(dev, "transmission failed\n"); netdev_dbg(dev, "transmission failed\n");
} }
......
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