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-09-18

Here's the first bluetooth-next pull request for the 4.4 kernel:

 - ieee802154 cleanups & fixes
 - debugfs support for the at86rf230 driver
 - Support for quirky (seemingly counterfeit) CSR Bluetooth controllers
 - Power management and device config improvements for Intel controllers
 - Fix for devices with incorrect advertising data length
 - Fix for closing HCI user channel socket

Please let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2015-09-21 16:00:44 -07:00
31 changed files with 1604 additions and 551 deletions
+4 -4
View File
@@ -7,11 +7,11 @@ Introduction
The IEEE 802.15.4 working group focuses on standardization of bottom
two layers: Medium Access Control (MAC) and Physical (PHY). And there
are mainly two options available for upper layers:
- ZigBee - proprietary protocol from ZigBee Alliance
- 6LowPAN - IPv6 networking over low rate personal area networks
- ZigBee - proprietary protocol from the ZigBee Alliance
- 6LoWPAN - IPv6 networking over low rate personal area networks
The Linux-ZigBee project goal is to provide complete implementation
of IEEE 802.15.4 and 6LoWPAN protocols. IEEE 802.15.4 is a stack
The linux-wpan project goal is to provide a complete implementation
of the IEEE 802.15.4 and 6LoWPAN protocols. IEEE 802.15.4 is a stack
of protocols for organizing Low-Rate Wireless Personal Area Networks.
The stack is composed of three main parts:
+8 -4
View File
@@ -453,7 +453,8 @@ static int bt3c_load_firmware(struct bt3c_info *info,
{
char *ptr = (char *) firmware;
char b[9];
unsigned int iobase, size, addr, fcs, tmp;
unsigned int iobase, tmp;
unsigned long size, addr, fcs;
int i, err = 0;
iobase = info->p_dev->resource[0]->start;
@@ -478,15 +479,18 @@ static int bt3c_load_firmware(struct bt3c_info *info,
memset(b, 0, sizeof(b));
memcpy(b, ptr + 2, 2);
size = simple_strtoul(b, NULL, 16);
if (kstrtoul(b, 16, &size) < 0)
return -EINVAL;
memset(b, 0, sizeof(b));
memcpy(b, ptr + 4, 8);
addr = simple_strtoul(b, NULL, 16);
if (kstrtoul(b, 16, &addr) < 0)
return -EINVAL;
memset(b, 0, sizeof(b));
memcpy(b, ptr + (size * 2) + 2, 2);
fcs = simple_strtoul(b, NULL, 16);
if (kstrtoul(b, 16, &fcs) < 0)
return -EINVAL;
memset(b, 0, sizeof(b));
for (tmp = 0, i = 0; i < size; i++) {
+46
View File
@@ -22,6 +22,7 @@
*/
#include <linux/module.h>
#include <linux/firmware.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -169,6 +170,51 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
}
EXPORT_SYMBOL_GPL(btintel_secure_send);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)
{
const struct firmware *fw;
struct sk_buff *skb;
const u8 *fw_ptr;
int err;
err = request_firmware_direct(&fw, ddc_name, &hdev->dev);
if (err < 0) {
bt_dev_err(hdev, "Failed to load Intel DDC file %s (%d)",
ddc_name, err);
return err;
}
bt_dev_info(hdev, "Found Intel DDC parameters: %s", ddc_name);
fw_ptr = fw->data;
/* DDC file contains one or more DDC structure which has
* Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
*/
while (fw->size > fw_ptr - fw->data) {
u8 cmd_plen = fw_ptr[0] + sizeof(u8);
skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Failed to send Intel_Write_DDC (%ld)",
PTR_ERR(skb));
release_firmware(fw);
return PTR_ERR(skb);
}
fw_ptr += cmd_plen;
kfree_skb(skb);
}
release_firmware(fw);
bt_dev_info(hdev, "Applying Intel DDC parameters completed");
return 0;
}
EXPORT_SYMBOL_GPL(btintel_load_ddc_config);
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION);
+9 -1
View File
@@ -78,6 +78,7 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code);
void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver);
int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
#else
@@ -95,7 +96,8 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code)
{
}
static void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
static inline void btintel_version_info(struct hci_dev *hdev,
struct intel_version *ver)
{
}
@@ -105,4 +107,10 @@ static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type,
return -EOPNOTSUPP;
}
static inline int btintel_load_ddc_config(struct hci_dev *hdev,
const char *ddc_name)
{
return -EOPNOTSUPP;
}
#endif
-14
View File
@@ -377,20 +377,6 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
return -EINVAL;
}
if (skb_headroom(skb) < BTM_HEADER_LEN) {
struct sk_buff *tmp = skb;
skb = skb_realloc_headroom(skb, BTM_HEADER_LEN);
if (!skb) {
BT_ERR("Tx Error: realloc_headroom failed %d",
BTM_HEADER_LEN);
skb = tmp;
return -EINVAL;
}
kfree_skb(tmp);
}
skb_push(skb, BTM_HEADER_LEN);
/* header type: byte[3]
+19 -32
View File
@@ -1277,6 +1277,20 @@ static void btusb_work(struct work_struct *work)
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
usb_kill_anchored_urbs(&data->isoc_anchor);
/* When isochronous alternate setting needs to be
* changed, because SCO connection has been added
* or removed, a packet fragment may be left in the
* reassembling state. This could lead to wrongly
* assembled fragments.
*
* Clear outstanding fragment when selecting a new
* alternate setting.
*/
spin_lock(&data->rxlock);
kfree_skb(data->sco_skb);
data->sco_skb = NULL;
spin_unlock(&data->rxlock);
if (__set_isoc_interface(hdev, new_alts) < 0)
return;
}
@@ -1348,7 +1362,9 @@ static int btusb_setup_csr(struct hci_dev *hdev)
rp = (struct hci_rp_read_local_version *)skb->data;
if (le16_to_cpu(rp->manufacturer) != 10) {
/* Detect controllers which aren't real CSR ones. */
if (le16_to_cpu(rp->manufacturer) != 10 ||
le16_to_cpu(rp->lmp_subver) == 0x0c5c) {
/* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR.
*/
@@ -2217,36 +2233,7 @@ done:
* The device can work without DDC parameters, so even if it fails
* to load the file, no need to fail the setup.
*/
err = request_firmware_direct(&fw, fwname, &hdev->dev);
if (err < 0)
return 0;
BT_INFO("%s: Found Intel DDC parameters: %s", hdev->name, fwname);
fw_ptr = fw->data;
/* DDC file contains one or more DDC structure which has
* Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
*/
while (fw->size > fw_ptr - fw->data) {
u8 cmd_plen = fw_ptr[0] + sizeof(u8);
skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s: Failed to send Intel_Write_DDC (%ld)",
hdev->name, PTR_ERR(skb));
release_firmware(fw);
return PTR_ERR(skb);
}
fw_ptr += cmd_plen;
kfree_skb(skb);
}
release_firmware(fw);
BT_INFO("%s: Applying Intel DDC parameters completed", hdev->name);
btintel_load_ddc_config(hdev, fwname);
return 0;
}
@@ -2782,7 +2769,7 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
/* Fake CSR devices with broken commands */
if (bcdDevice <= 0x100)
if (bcdDevice <= 0x100 || bcdDevice == 0x134)
hdev->setup = btusb_setup_csr;
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+179 -39
View File
@@ -31,6 +31,7 @@
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -51,6 +52,8 @@ struct bcm_device {
bool clk_enabled;
u32 init_speed;
int irq;
u8 irq_polarity;
#ifdef CONFIG_PM_SLEEP
struct hci_uart *hu;
@@ -66,7 +69,7 @@ struct bcm_data {
};
/* List of BCM BT UART devices */
static DEFINE_SPINLOCK(bcm_device_lock);
static DEFINE_MUTEX(bcm_device_lock);
static LIST_HEAD(bcm_device_list);
static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
@@ -80,7 +83,7 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
clock.type = BCM_UART_CLOCK_48MHZ;
BT_DBG("%s: Set Controller clock (%d)", hdev->name, clock.type);
bt_dev_dbg(hdev, "Set Controller clock (%d)", clock.type);
/* This Broadcom specific command changes the UART's controller
* clock for baud rate > 3000000.
@@ -88,15 +91,15 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
skb = __hci_cmd_sync(hdev, 0xfc45, 1, &clock, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
BT_ERR("%s: BCM: failed to write clock command (%d)",
hdev->name, err);
bt_dev_err(hdev, "BCM: failed to write clock (%d)",
err);
return err;
}
kfree_skb(skb);
}
BT_DBG("%s: Set Controller UART speed to %d bit/s", hdev->name, speed);
bt_dev_dbg(hdev, "Set Controller UART speed to %d bit/s", speed);
param.zero = cpu_to_le16(0);
param.baud_rate = cpu_to_le32(speed);
@@ -108,8 +111,8 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
BT_ERR("%s: BCM: failed to write update baudrate command (%d)",
hdev->name, err);
bt_dev_err(hdev, "BCM: failed to write update baudrate (%d)",
err);
return err;
}
@@ -149,12 +152,92 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static irqreturn_t bcm_host_wake(int irq, void *data)
{
struct bcm_device *bdev = data;
bt_dev_dbg(bdev, "Host wake IRQ");
return IRQ_HANDLED;
}
static int bcm_request_irq(struct bcm_data *bcm)
{
struct bcm_device *bdev = bcm->dev;
int err = 0;
/* If this is not a platform device, do not enable PM functionalities */
mutex_lock(&bcm_device_lock);
if (!bcm_device_exists(bdev)) {
err = -ENODEV;
goto unlock;
}
if (bdev->irq > 0) {
err = devm_request_irq(&bdev->pdev->dev, bdev->irq,
bcm_host_wake, IRQF_TRIGGER_RISING,
"host_wake", bdev);
if (err)
goto unlock;
device_init_wakeup(&bdev->pdev->dev, true);
}
unlock:
mutex_unlock(&bcm_device_lock);
return err;
}
static const struct bcm_set_sleep_mode default_sleep_params = {
.sleep_mode = 1, /* 0=Disabled, 1=UART, 2=Reserved, 3=USB */
.idle_host = 2, /* idle threshold HOST, in 300ms */
.idle_dev = 2, /* idle threshold device, in 300ms */
.bt_wake_active = 1, /* BT_WAKE active mode: 1 = high, 0 = low */
.host_wake_active = 0, /* HOST_WAKE active mode: 1 = high, 0 = low */
.allow_host_sleep = 1, /* Allow host sleep in SCO flag */
.combine_modes = 0, /* Combine sleep and LPM flag */
.tristate_control = 0, /* Allow tri-state control of UART tx flag */
/* Irrelevant USB flags */
.usb_auto_sleep = 0,
.usb_resume_timeout = 0,
.pulsed_host_wake = 0,
.break_to_host = 0
};
static int bcm_setup_sleep(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
struct sk_buff *skb;
struct bcm_set_sleep_mode sleep_params = default_sleep_params;
sleep_params.host_wake_active = !bcm->dev->irq_polarity;
skb = __hci_cmd_sync(hu->hdev, 0xfc27, sizeof(sleep_params),
&sleep_params, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
bt_dev_err(hu->hdev, "Sleep VSC failed (%d)", err);
return err;
}
kfree_skb(skb);
bt_dev_dbg(hu->hdev, "Set Sleep Parameters VSC succeeded");
return 0;
}
#else
static inline int bcm_request_irq(struct bcm_data *bcm) { return 0; }
static inline int bcm_setup_sleep(struct hci_uart *hu) { return 0; }
#endif
static int bcm_open(struct hci_uart *hu)
{
struct bcm_data *bcm;
struct list_head *p;
BT_DBG("hu %p", hu);
bt_dev_dbg(hu->hdev, "hu %p", hu);
bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
if (!bcm)
@@ -164,7 +247,7 @@ static int bcm_open(struct hci_uart *hu)
hu->priv = bcm;
spin_lock(&bcm_device_lock);
mutex_lock(&bcm_device_lock);
list_for_each(p, &bcm_device_list) {
struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@@ -178,14 +261,12 @@ static int bcm_open(struct hci_uart *hu)
#ifdef CONFIG_PM_SLEEP
dev->hu = hu;
#endif
bcm_gpio_set_power(bcm->dev, true);
break;
}
}
if (bcm->dev)
bcm_gpio_set_power(bcm->dev, true);
spin_unlock(&bcm_device_lock);
mutex_unlock(&bcm_device_lock);
return 0;
}
@@ -193,18 +274,24 @@ static int bcm_open(struct hci_uart *hu)
static int bcm_close(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
struct bcm_device *bdev = bcm->dev;
BT_DBG("hu %p", hu);
bt_dev_dbg(hu->hdev, "hu %p", hu);
/* Protect bcm->dev against removal of the device or driver */
spin_lock(&bcm_device_lock);
if (bcm_device_exists(bcm->dev)) {
bcm_gpio_set_power(bcm->dev, false);
mutex_lock(&bcm_device_lock);
if (bcm_device_exists(bdev)) {
bcm_gpio_set_power(bdev, false);
#ifdef CONFIG_PM_SLEEP
bcm->dev->hu = NULL;
if (device_can_wakeup(&bdev->pdev->dev)) {
devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
device_init_wakeup(&bdev->pdev->dev, false);
}
bdev->hu = NULL;
#endif
}
spin_unlock(&bcm_device_lock);
mutex_unlock(&bcm_device_lock);
skb_queue_purge(&bcm->txq);
kfree_skb(bcm->rx_skb);
@@ -218,7 +305,7 @@ static int bcm_flush(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
BT_DBG("hu %p", hu);
bt_dev_dbg(hu->hdev, "hu %p", hu);
skb_queue_purge(&bcm->txq);
@@ -227,12 +314,13 @@ static int bcm_flush(struct hci_uart *hu)
static int bcm_setup(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
char fw_name[64];
const struct firmware *fw;
unsigned int speed;
int err;
BT_DBG("hu %p", hu);
bt_dev_dbg(hu->hdev, "hu %p", hu);
hu->hdev->set_bdaddr = btbcm_set_bdaddr;
@@ -242,13 +330,13 @@ static int bcm_setup(struct hci_uart *hu)
err = request_firmware(&fw, fw_name, &hu->hdev->dev);
if (err < 0) {
BT_INFO("%s: BCM: Patch %s not found", hu->hdev->name, fw_name);
bt_dev_info(hu->hdev, "BCM: Patch %s not found", fw_name);
return 0;
}
err = btbcm_patchram(hu->hdev, fw);
if (err) {
BT_INFO("%s: BCM: Patch failed (%d)", hu->hdev->name, err);
bt_dev_info(hu->hdev, "BCM: Patch failed (%d)", err);
goto finalize;
}
@@ -281,6 +369,12 @@ finalize:
release_firmware(fw);
err = btbcm_finalize(hu->hdev);
if (err)
return err;
err = bcm_request_irq(bcm);
if (!err)
err = bcm_setup_sleep(hu);
return err;
}
@@ -302,7 +396,7 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
bcm_recv_pkts, ARRAY_SIZE(bcm_recv_pkts));
if (IS_ERR(bcm->rx_skb)) {
int err = PTR_ERR(bcm->rx_skb);
BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
bcm->rx_skb = NULL;
return err;
}
@@ -314,7 +408,7 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct bcm_data *bcm = hu->priv;
BT_DBG("hu %p skb %p", hu, skb);
bt_dev_dbg(hu->hdev, "hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
@@ -335,10 +429,11 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
static int bcm_suspend(struct device *dev)
{
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
int error;
BT_DBG("suspend (%p): is_suspended %d", bdev, bdev->is_suspended);
bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
spin_lock(&bcm_device_lock);
mutex_lock(&bcm_device_lock);
if (!bdev->hu)
goto unlock;
@@ -353,12 +448,18 @@ static int bcm_suspend(struct device *dev)
/* Suspend the device */
if (bdev->device_wakeup) {
gpiod_set_value(bdev->device_wakeup, false);
BT_DBG("suspend, delaying 15 ms");
bt_dev_dbg(bdev, "suspend, delaying 15 ms");
mdelay(15);
}
if (device_may_wakeup(&bdev->pdev->dev)) {
error = enable_irq_wake(bdev->irq);
if (!error)
bt_dev_dbg(bdev, "BCM irq: enabled");
}
unlock:
spin_unlock(&bcm_device_lock);
mutex_unlock(&bcm_device_lock);
return 0;
}
@@ -368,16 +469,21 @@ static int bcm_resume(struct device *dev)
{
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
BT_DBG("resume (%p): is_suspended %d", bdev, bdev->is_suspended);
bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
spin_lock(&bcm_device_lock);
mutex_lock(&bcm_device_lock);
if (!bdev->hu)
goto unlock;
if (device_may_wakeup(&bdev->pdev->dev)) {
disable_irq_wake(bdev->irq);
bt_dev_dbg(bdev, "BCM irq: disabled");
}
if (bdev->device_wakeup) {
gpiod_set_value(bdev->device_wakeup, true);
BT_DBG("resume, delaying 15 ms");
bt_dev_dbg(bdev, "resume, delaying 15 ms");
mdelay(15);
}
@@ -389,7 +495,7 @@ static int bcm_resume(struct device *dev)
}
unlock:
spin_unlock(&bcm_device_lock);
mutex_unlock(&bcm_device_lock);
return 0;
}
@@ -397,10 +503,12 @@ unlock:
static const struct acpi_gpio_params device_wakeup_gpios = { 0, 0, false };
static const struct acpi_gpio_params shutdown_gpios = { 1, 0, false };
static const struct acpi_gpio_params host_wakeup_gpios = { 2, 0, false };
static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
{ "device-wakeup-gpios", &device_wakeup_gpios, 1 },
{ "shutdown-gpios", &shutdown_gpios, 1 },
{ "host-wakeup-gpios", &host_wakeup_gpios, 1 },
{ },
};
@@ -408,13 +516,30 @@ static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
static int bcm_resource(struct acpi_resource *ares, void *data)
{
struct bcm_device *dev = data;
struct acpi_resource_extended_irq *irq;
struct acpi_resource_gpio *gpio;
struct acpi_resource_uart_serialbus *sb;
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
struct acpi_resource_uart_serialbus *sb;
switch (ares->type) {
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
irq = &ares->data.extended_irq;
dev->irq_polarity = irq->polarity;
break;
case ACPI_RESOURCE_TYPE_GPIO:
gpio = &ares->data.gpio;
if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
dev->irq_polarity = gpio->polarity;
break;
case ACPI_RESOURCE_TYPE_SERIAL_BUS:
sb = &ares->data.uart_serial_bus;
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART)
dev->init_speed = sb->default_baud_rate;
break;
default:
break;
}
/* Always tell the ACPI core to skip this resource */
@@ -453,6 +578,21 @@ static int bcm_acpi_probe(struct bcm_device *dev)
if (IS_ERR(dev->shutdown))
return PTR_ERR(dev->shutdown);
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
dev->irq = platform_get_irq(pdev, 0);
if (dev->irq <= 0) {
struct gpio_desc *gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "host-wakeup",
GPIOD_IN);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
dev->irq = gpiod_to_irq(gpio);
}
dev_info(&pdev->dev, "BCM irq: %d\n", dev->irq);
/* Make sure at-least one of the GPIO is defined and that
* a name is specified for this instance
*/
@@ -504,9 +644,9 @@ static int bcm_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s device registered.\n", dev->name);
/* Place this instance on the device list */
spin_lock(&bcm_device_lock);
mutex_lock(&bcm_device_lock);
list_add_tail(&dev->list, &bcm_device_list);
spin_unlock(&bcm_device_lock);
mutex_unlock(&bcm_device_lock);
bcm_gpio_set_power(dev, false);
@@ -517,9 +657,9 @@ static int bcm_remove(struct platform_device *pdev)
{
struct bcm_device *dev = platform_get_drvdata(pdev);
spin_lock(&bcm_device_lock);
mutex_lock(&bcm_device_lock);
list_del(&dev->list);
spin_unlock(&bcm_device_lock);
mutex_unlock(&bcm_device_lock);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -41,13 +41,13 @@
#define HCI_IBS_SLEEP_IND 0xFE
#define HCI_IBS_WAKE_IND 0xFD
#define HCI_IBS_WAKE_ACK 0xFC
#define HCI_MAX_IBS_SIZE 10
#define HCI_MAX_IBS_SIZE 10
/* Controller states */
#define STATE_IN_BAND_SLEEP_ENABLED 1
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_TX_IDLE_TIMEOUT_MS 2000
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_TX_IDLE_TIMEOUT_MS 2000
#define BAUDRATE_SETTLE_TIMEOUT_MS 300
/* HCI_IBS transmit side sleep protocol states */
@@ -181,8 +181,8 @@ static void serial_clock_vote(unsigned long vote, struct hci_uart *hu)
else
__serial_clock_off(hu->tty);
BT_DBG("Vote serial clock %s(%s)", new_vote? "true" : "false",
vote? "true" : "false");
BT_DBG("Vote serial clock %s(%s)", new_vote ? "true" : "false",
vote ? "true" : "false");
diff = jiffies_to_msecs(jiffies - qca->vote_last_jif);
@@ -821,7 +821,7 @@ static struct sk_buff *qca_dequeue(struct hci_uart *hu)
static uint8_t qca_get_baudrate_value(int speed)
{
switch(speed) {
switch (speed) {
case 9600:
return QCA_BAUDRATE_9600;
case 19200:
+7
View File
@@ -32,6 +32,13 @@ config IEEE802154_AT86RF230
This driver can also be built as a module. To do so, say M here.
the module will be called 'at86rf230'.
config IEEE802154_AT86RF230_DEBUGFS
depends on IEEE802154_AT86RF230
bool "AT86RF230 debugfs interface"
depends on DEBUG_FS
---help---
This option compiles debugfs code for the at86rf230 driver.
config IEEE802154_MRF24J40
tristate "Microchip MRF24J40 transceiver driver"
depends on IEEE802154_DRIVERS && MAC802154
+148 -47
View File
@@ -31,6 +31,7 @@
#include <linux/skbuff.h>
#include <linux/of_gpio.h>
#include <linux/ieee802154.h>
#include <linux/debugfs.h>
#include <net/mac802154.h>
#include <net/cfg802154.h>
@@ -83,6 +84,15 @@ struct at86rf230_state_change {
bool irq_enable;
};
struct at86rf230_trac {
u64 success;
u64 success_data_pending;
u64 success_wait_for_ack;
u64 channel_access_failure;
u64 no_ack;
u64 invalid;
};
struct at86rf230_local {
struct spi_device *spi;
@@ -103,6 +113,8 @@ struct at86rf230_local {
u8 tx_retry;
struct sk_buff *tx_skb;
struct at86rf230_state_change tx;
struct at86rf230_trac trac;
};
#define AT86RF2XX_NUMREGS 0x3F
@@ -377,14 +389,6 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
}
}
static inline u8 at86rf230_state_to_force(u8 state)
{
if (state == STATE_TX_ON)
return STATE_FORCE_TX_ON;
else
return STATE_FORCE_TRX_OFF;
}
static void
at86rf230_async_state_assert(void *context)
{
@@ -426,7 +430,7 @@ at86rf230_async_state_assert(void *context)
u8 state = ctx->to_state;
if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
state = at86rf230_state_to_force(state);
state = STATE_FORCE_TRX_OFF;
lp->tx_retry++;
at86rf230_async_state_change(lp, ctx, state,
@@ -667,28 +671,34 @@ at86rf230_tx_trac_check(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
const u8 *buf = ctx->buf;
const u8 trac = (buf[1] & 0xe0) >> 5;
/* If trac status is different than zero we need to do a state change
* to STATE_FORCE_TRX_OFF then STATE_RX_AACK_ON to recover the
* transceiver.
*/
if (trac)
at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
at86rf230_tx_on, true);
else
at86rf230_tx_on(context);
}
if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
u8 trac = TRAC_MASK(ctx->buf[1]);
static void
at86rf230_tx_trac_status(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
switch (trac) {
case TRAC_SUCCESS:
lp->trac.success++;
break;
case TRAC_SUCCESS_DATA_PENDING:
lp->trac.success_data_pending++;
break;
case TRAC_CHANNEL_ACCESS_FAILURE:
lp->trac.channel_access_failure++;
break;
case TRAC_NO_ACK:
lp->trac.no_ack++;
break;
case TRAC_INVALID:
lp->trac.invalid++;
break;
default:
WARN_ONCE(1, "received tx trac status %d\n", trac);
break;
}
}
at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
at86rf230_tx_trac_check, true);
at86rf230_async_state_change(lp, &lp->irq, STATE_TX_ON,
at86rf230_tx_on, true);
}
static void
@@ -723,13 +733,32 @@ at86rf230_rx_read_frame_complete(void *context)
}
static void
at86rf230_rx_read_frame(void *context)
at86rf230_rx_trac_check(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
u8 *buf = ctx->buf;
int rc;
if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
u8 trac = TRAC_MASK(buf[1]);
switch (trac) {
case TRAC_SUCCESS:
lp->trac.success++;
break;
case TRAC_SUCCESS_WAIT_FOR_ACK:
lp->trac.success_wait_for_ack++;
break;
case TRAC_INVALID:
lp->trac.invalid++;
break;
default:
WARN_ONCE(1, "received rx trac status %d\n", trac);
break;
}
}
buf[0] = CMD_FB;
ctx->trx.len = AT86RF2XX_MAX_BUF;
ctx->msg.complete = at86rf230_rx_read_frame_complete;
@@ -741,27 +770,13 @@ at86rf230_rx_read_frame(void *context)
}
}
static void
at86rf230_rx_trac_check(void *context)
{
/* Possible check on trac status here. This could be useful to make
* some stats why receive is failed. Not used at the moment, but it's
* maybe timing relevant. Datasheet doesn't say anything about this.
* The programming guide say do it so.
*/
at86rf230_rx_read_frame(context);
}
static void
at86rf230_irq_trx_end(struct at86rf230_local *lp)
{
if (lp->is_tx) {
lp->is_tx = 0;
at86rf230_async_state_change(lp, &lp->irq,
STATE_FORCE_TX_ON,
at86rf230_tx_trac_status,
true);
at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
at86rf230_tx_trac_check, true);
} else {
at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
at86rf230_rx_trac_check, true);
@@ -920,6 +935,10 @@ at86rf230_start(struct ieee802154_hw *hw)
{
struct at86rf230_local *lp = hw->priv;
/* reset trac stats on start */
if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS))
memset(&lp->trac, 0, sizeof(struct at86rf230_trac));
at86rf230_awake(lp);
enable_irq(lp->spi->irq);
@@ -1357,7 +1376,7 @@ static int at86rf230_hw_init(struct at86rf230_local *lp, u8 xtal_trim)
if (irq_type == IRQ_TYPE_EDGE_RISING ||
irq_type == IRQ_TYPE_EDGE_FALLING)
dev_warn(&lp->spi->dev,
"Using edge triggered irq's are not recommended!\n");
"Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n");
if (irq_type == IRQ_TYPE_EDGE_FALLING ||
irq_type == IRQ_TYPE_LEVEL_LOW)
irq_pol = IRQ_ACTIVE_LOW;
@@ -1620,6 +1639,81 @@ at86rf230_setup_spi_messages(struct at86rf230_local *lp)
lp->tx.timer.function = at86rf230_async_state_timer;
}
#ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS
static struct dentry *at86rf230_debugfs_root;
static int at86rf230_stats_show(struct seq_file *file, void *offset)
{
struct at86rf230_local *lp = file->private;
int ret;
ret = seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success);
if (ret < 0)
return ret;
ret = seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n",
lp->trac.success_data_pending);
if (ret < 0)
return ret;
ret = seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n",
lp->trac.success_wait_for_ack);
if (ret < 0)
return ret;
ret = seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n",
lp->trac.channel_access_failure);
if (ret < 0)
return ret;
ret = seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack);
if (ret < 0)
return ret;
return seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid);
}
static int at86rf230_stats_open(struct inode *inode, struct file *file)
{
return single_open(file, at86rf230_stats_show, inode->i_private);
}
static const struct file_operations at86rf230_stats_fops = {
.open = at86rf230_stats_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int at86rf230_debugfs_init(struct at86rf230_local *lp)
{
char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-";
struct dentry *stats;
strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN);
at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
if (!at86rf230_debugfs_root)
return -ENOMEM;
stats = debugfs_create_file("trac_stats", S_IRUGO,
at86rf230_debugfs_root, lp,
&at86rf230_stats_fops);
if (!stats)
return -ENOMEM;
return 0;
}
static void at86rf230_debugfs_remove(void)
{
debugfs_remove_recursive(at86rf230_debugfs_root);
}
#else
static int at86rf230_debugfs_init(struct at86rf230_local *lp) { return 0; }
static void at86rf230_debugfs_remove(void) { }
#endif
static int at86rf230_probe(struct spi_device *spi)
{
struct ieee802154_hw *hw;
@@ -1715,12 +1809,18 @@ static int at86rf230_probe(struct spi_device *spi)
/* going into sleep by default */
at86rf230_sleep(lp);
rc = ieee802154_register_hw(lp->hw);
rc = at86rf230_debugfs_init(lp);
if (rc)
goto free_dev;
rc = ieee802154_register_hw(lp->hw);
if (rc)
goto free_debugfs;
return rc;
free_debugfs:
at86rf230_debugfs_remove();
free_dev:
ieee802154_free_hw(lp->hw);
@@ -1735,6 +1835,7 @@ static int at86rf230_remove(struct spi_device *spi)
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
ieee802154_unregister_hw(lp->hw);
ieee802154_free_hw(lp->hw);
at86rf230_debugfs_remove();
dev_dbg(&spi->dev, "unregistered at86rf230\n");
return 0;
+8
View File
@@ -216,5 +216,13 @@
#define STATE_TRANSITION_IN_PROGRESS 0x1F
#define TRX_STATE_MASK (0x1F)
#define TRAC_MASK(x) ((x & 0xe0) >> 5)
#define TRAC_SUCCESS 0
#define TRAC_SUCCESS_DATA_PENDING 1
#define TRAC_SUCCESS_WAIT_FOR_ACK 2
#define TRAC_CHANNEL_ACCESS_FAILURE 3
#define TRAC_NO_ACK 5
#define TRAC_INVALID 7
#endif /* !_AT86RF230_H */
+11 -2
View File
@@ -559,6 +559,7 @@ static int atusb_get_and_show_chip(struct atusb *atusb)
{
struct usb_device *usb_dev = atusb->usb_dev;
uint8_t man_id_0, man_id_1, part_num, version_num;
const char *chip;
man_id_0 = atusb_read_reg(atusb, RG_MAN_ID_0);
man_id_1 = atusb_read_reg(atusb, RG_MAN_ID_1);
@@ -574,14 +575,22 @@ static int atusb_get_and_show_chip(struct atusb *atusb)
man_id_1, man_id_0);
goto fail;
}
if (part_num != 3 && part_num != 2) {
switch (part_num) {
case 2:
chip = "AT86RF230";
break;
case 3:
chip = "AT86RF231";
break;
default:
dev_err(&usb_dev->dev,
"unexpected transceiver, part 0x%02x version 0x%02x\n",
part_num, version_num);
goto fail;
}
dev_info(&usb_dev->dev, "ATUSB: AT86RF231 version %d\n", version_num);
dev_info(&usb_dev->dev, "ATUSB: %s version %d\n", chip, version_num);
return 0;
+25
View File
@@ -205,6 +205,31 @@ enum {
IEEE802154_SCAN_IN_PROGRESS = 0xfc,
};
/* frame control handling */
#define IEEE802154_FCTL_FTYPE 0x0003
#define IEEE802154_FCTL_INTRA_PAN 0x0040
#define IEEE802154_FTYPE_DATA 0x0001
/*
* ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA
* @fc: frame control bytes in little-endian byteorder
*/
static inline int ieee802154_is_data(__le16 fc)
{
return (fc & cpu_to_le16(IEEE802154_FCTL_FTYPE)) ==
cpu_to_le16(IEEE802154_FTYPE_DATA);
}
/**
* ieee802154_is_intra_pan - check if intra pan id communication
* @fc: frame control bytes in little-endian byteorder
*/
static inline bool ieee802154_is_intra_pan(__le16 fc)
{
return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN);
}
/**
* ieee802154_is_valid_psdu_len - check if psdu len is valid
* available lengths:
+25 -119
View File
@@ -126,13 +126,19 @@
(((a)[6]) == 0xFF) && \
(((a)[7]) == 0xFF))
#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
#define LOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */
#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
#define LOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */
#define LOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */
#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
#define LOWPAN_DISPATCH_IPHC_MASK 0xe0
#define LOWPAN_DISPATCH_MASK 0xf8 /* 11111000 */
static inline bool lowpan_is_ipv6(u8 dispatch)
{
return dispatch == LOWPAN_DISPATCH_IPV6;
}
static inline bool lowpan_is_iphc(u8 dispatch)
{
return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC;
}
#define LOWPAN_FRAG_TIMEOUT (HZ * 60) /* time-out 60 sec */
@@ -218,6 +224,19 @@ struct lowpan_priv *lowpan_priv(const struct net_device *dev)
return netdev_priv(dev);
}
struct lowpan_802154_cb {
u16 d_tag;
unsigned int d_size;
u8 d_offset;
};
static inline
struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb));
return (struct lowpan_802154_cb *)skb->cb;
}
#ifdef DEBUG
/* print data in line */
static inline void raw_dump_inline(const char *caller, char *msg,
@@ -280,119 +299,6 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
*hc_ptr += len;
}
static inline u8 lowpan_addr_mode_size(const u8 addr_mode)
{
static const u8 addr_sizes[] = {
[LOWPAN_IPHC_ADDR_00] = 16,
[LOWPAN_IPHC_ADDR_01] = 8,
[LOWPAN_IPHC_ADDR_02] = 2,
[LOWPAN_IPHC_ADDR_03] = 0,
};
return addr_sizes[addr_mode];
}
static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 *uncomp_header)
{
u8 ret = 1;
if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
*uncomp_header += sizeof(struct udphdr);
switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) {
case LOWPAN_NHC_UDP_CS_P_00:
ret += 4;
break;
case LOWPAN_NHC_UDP_CS_P_01:
case LOWPAN_NHC_UDP_CS_P_10:
ret += 3;
break;
case LOWPAN_NHC_UDP_CS_P_11:
ret++;
break;
default:
break;
}
if (!(h_enc & LOWPAN_NHC_UDP_CS_C))
ret += 2;
}
return ret;
}
/**
* lowpan_uncompress_size - returns skb->len size with uncompressed header
* @skb: sk_buff with 6lowpan header inside
* @datagram_offset: optional to get the datagram_offset value
*
* Returns the skb->len with uncompressed header
*/
static inline u16
lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
{
u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr);
u8 iphc0, iphc1, h_enc;
iphc0 = skb_network_header(skb)[0];
iphc1 = skb_network_header(skb)[1];
switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
case 0:
ret += 4;
break;
case 1:
ret += 3;
break;
case 2:
ret++;
break;
default:
break;
}
if (!(iphc0 & LOWPAN_IPHC_NH_C))
ret++;
if (!(iphc0 & 0x03))
ret++;
ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >>
LOWPAN_IPHC_SAM_BIT);
if (iphc1 & LOWPAN_IPHC_M) {
switch ((iphc1 & LOWPAN_IPHC_DAM_11) >>
LOWPAN_IPHC_DAM_BIT) {
case LOWPAN_IPHC_DAM_00:
ret += 16;
break;
case LOWPAN_IPHC_DAM_01:
ret += 6;
break;
case LOWPAN_IPHC_DAM_10:
ret += 4;
break;
case LOWPAN_IPHC_DAM_11:
ret++;
break;
default:
break;
}
} else {
ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >>
LOWPAN_IPHC_DAM_BIT);
}
if (iphc0 & LOWPAN_IPHC_NH_C) {
h_enc = skb_network_header(skb)[ret];
ret += lowpan_next_hdr_size(h_enc, &uncomp_header);
}
if (dgram_offset)
*dgram_offset = uncomp_header;
return skb->len + uncomp_header - ret;
}
void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype);
int
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* IEEE 802.15.4 inteface for userspace
* IEEE 802.15.4 interface for userspace
*
* Copyright 2007, 2008 Siemens AG
*
+11
View File
@@ -123,11 +123,22 @@ __printf(1, 2)
void bt_info(const char *fmt, ...);
__printf(1, 2)
void bt_err(const char *fmt, ...);
__printf(1, 2)
void bt_err_ratelimited(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(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_ERR_RATELIMITED(fmt, ...) bt_err_ratelimited(fmt "\n", ##__VA_ARGS__)
#define bt_dev_info(hdev, fmt, ...) \
BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_err(hdev, fmt, ...) \
BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_dbg(hdev, fmt, ...) \
BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
/* Connection and socket states */
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
+1
View File
@@ -987,6 +987,7 @@ int hci_resume_dev(struct hci_dev *hdev);
int hci_reset_dev(struct hci_dev *hdev);
int hci_dev_open(__u16 dev);
int hci_dev_close(__u16 dev);
int hci_dev_do_close(struct hci_dev *hdev);
int hci_dev_reset(__u16 dev);
int hci_dev_reset_stat(__u16 dev);
int hci_dev_cmd(unsigned int cmd, void __user *arg);
+15
View File
@@ -249,6 +249,21 @@ struct ieee802154_ops {
const bool on);
};
/**
* ieee802154_get_fc_from_skb - get the frame control field from an skb
* @skb: skb where the frame control field will be get from
*/
static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb)
{
/* return some invalid fc on failure */
if (unlikely(skb->mac_len < 2)) {
WARN_ON(1);
return cpu_to_le16(0);
}
return (__force __le16)__get_unaligned_memmove16(skb_mac_header(skb));
}
/**
* ieee802154_be64_to_le64 - copies and convert be64 to le64
* @le64_dst: le64 destination pointer
+12 -1
View File
@@ -366,7 +366,18 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
return err;
}
hdr.payload_len = htons(skb->len);
switch (lowpan_priv(dev)->lltype) {
case LOWPAN_LLTYPE_IEEE802154:
if (lowpan_802154_cb(skb)->d_size)
hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size -
sizeof(struct ipv6hdr));
else
hdr.payload_len = htons(skb->len);
break;
default:
hdr.payload_len = htons(skb->len);
break;
}
pr_debug("skb headroom size = %d, data length = %d\n",
skb_headroom(skb), skb->len);

Some files were not shown because too many files have changed in this diff Show More