Skip to content

Commit

Permalink
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2016-04-26

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

 - Cleanups & refactoring of ieee802154 & 6lowpan code
 - Security related additions to ieee802154 and mrf24j40 driver
 - Memory corruption fix to Bluetooth 6lowpan code
 - Race condition fix in vhci driver
 - Enhancements to the atusb 802.15.4 driver

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

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 26, 2016
2 parents 9c9f261 + 5544107 commit c0b0479
Show file tree
Hide file tree
Showing 19 changed files with 356 additions and 167 deletions.
6 changes: 4 additions & 2 deletions drivers/bluetooth/ath3k.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ static int ath3k_load_firmware(struct usb_device *udev,
const struct firmware *firmware)
{
u8 *send_buf;
int err, pipe, len, size, sent = 0;
int len = 0;
int err, pipe, size, sent = 0;
int count = firmware->size;

BT_DBG("udev %p", udev);
Expand Down Expand Up @@ -302,7 +303,8 @@ static int ath3k_load_fwfile(struct usb_device *udev,
const struct firmware *firmware)
{
u8 *send_buf;
int err, pipe, len, size, count, sent = 0;
int len = 0;
int err, pipe, size, count, sent = 0;
int ret;

count = firmware->size;
Expand Down
23 changes: 17 additions & 6 deletions drivers/bluetooth/hci_vhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct vhci_data {
wait_queue_head_t read_wait;
struct sk_buff_head readq;

struct mutex open_mutex;
struct delayed_work open_timeout;
};

Expand Down Expand Up @@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}

static int vhci_create_device(struct vhci_data *data, __u8 opcode)
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
{
struct hci_dev *hdev;
struct sk_buff *skb;
__u8 dev_type;

if (data->hdev)
return -EBADFD;

/* bits 0-1 are dev_type (BR/EDR or AMP) */
dev_type = opcode & 0x03;

Expand Down Expand Up @@ -151,6 +155,17 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode)
return 0;
}

static int vhci_create_device(struct vhci_data *data, __u8 opcode)
{
int err;

mutex_lock(&data->open_mutex);
err = __vhci_create_device(data, opcode);
mutex_unlock(&data->open_mutex);

return err;
}

static inline ssize_t vhci_get_user(struct vhci_data *data,
struct iov_iter *from)
{
Expand Down Expand Up @@ -191,11 +206,6 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
case HCI_VENDOR_PKT:
cancel_delayed_work_sync(&data->open_timeout);

if (data->hdev) {
kfree_skb(skb);
return -EBADFD;
}

opcode = *((__u8 *) skb->data);
skb_pull(skb, 1);

Expand Down Expand Up @@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode, struct file *file)
skb_queue_head_init(&data->readq);
init_waitqueue_head(&data->read_wait);

mutex_init(&data->open_mutex);
INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);

file->private_data = data;
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ieee802154/at86rf230.c
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,7 @@ static struct at86rf2xx_chip_data at86rf233_data = {
.t_off_to_aack = 80,
.t_off_to_tx_on = 80,
.t_off_to_sleep = 35,
.t_sleep_to_off = 210,
.t_sleep_to_off = 1000,
.t_frame = 4096,
.t_p_ack = 545,
.rssi_base_val = -91,
Expand All @@ -1355,7 +1355,7 @@ static struct at86rf2xx_chip_data at86rf231_data = {
.t_off_to_aack = 110,
.t_off_to_tx_on = 110,
.t_off_to_sleep = 35,
.t_sleep_to_off = 380,
.t_sleep_to_off = 1000,
.t_frame = 4096,
.t_p_ack = 545,
.rssi_base_val = -91,
Expand All @@ -1370,7 +1370,7 @@ static struct at86rf2xx_chip_data at86rf212_data = {
.t_off_to_aack = 200,
.t_off_to_tx_on = 200,
.t_off_to_sleep = 35,
.t_sleep_to_off = 380,
.t_sleep_to_off = 1000,
.t_frame = 4096,
.t_p_ack = 545,
.rssi_base_val = -100,
Expand Down
91 changes: 89 additions & 2 deletions drivers/net/ieee802154/atusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*
* Written 2013 by Werner Almesberger <werner@almesberger.net>
*
* Copyright (c) 2015 - 2016 Stefan Schmidt <stefan@datenfreihafen.org>
*
* 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, version 2
Expand Down Expand Up @@ -472,6 +474,76 @@ atusb_set_txpower(struct ieee802154_hw *hw, s32 mbm)
return -EINVAL;
}

#define ATUSB_MAX_ED_LEVELS 0xF
static const s32 atusb_ed_levels[ATUSB_MAX_ED_LEVELS + 1] = {
-9100, -8900, -8700, -8500, -8300, -8100, -7900, -7700, -7500, -7300,
-7100, -6900, -6700, -6500, -6300, -6100,
};

static int
atusb_set_cca_mode(struct ieee802154_hw *hw, const struct wpan_phy_cca *cca)
{
struct atusb *atusb = hw->priv;
u8 val;

/* mapping 802.15.4 to driver spec */
switch (cca->mode) {
case NL802154_CCA_ENERGY:
val = 1;
break;
case NL802154_CCA_CARRIER:
val = 2;
break;
case NL802154_CCA_ENERGY_CARRIER:
switch (cca->opt) {
case NL802154_CCA_OPT_ENERGY_CARRIER_AND:
val = 3;
break;
case NL802154_CCA_OPT_ENERGY_CARRIER_OR:
val = 0;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}

return atusb_write_subreg(atusb, SR_CCA_MODE, val);
}

static int
atusb_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
{
struct atusb *atusb = hw->priv;
u32 i;

for (i = 0; i < hw->phy->supported.cca_ed_levels_size; i++) {
if (hw->phy->supported.cca_ed_levels[i] == mbm)
return atusb_write_subreg(atusb, SR_CCA_ED_THRES, i);
}

return -EINVAL;
}

static int
atusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries)
{
struct atusb *atusb = hw->priv;
int ret;

ret = atusb_write_subreg(atusb, SR_MIN_BE, min_be);
if (ret)
return ret;

ret = atusb_write_subreg(atusb, SR_MAX_BE, max_be);
if (ret)
return ret;

return atusb_write_subreg(atusb, SR_MAX_CSMA_RETRIES, retries);
}

static int
atusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
{
Expand Down Expand Up @@ -508,6 +580,9 @@ static struct ieee802154_ops atusb_ops = {
.stop = atusb_stop,
.set_hw_addr_filt = atusb_set_hw_addr_filt,
.set_txpower = atusb_set_txpower,
.set_cca_mode = atusb_set_cca_mode,
.set_cca_ed_level = atusb_set_cca_ed_level,
.set_csma_params = atusb_set_csma_params,
.set_promiscuous_mode = atusb_set_promiscuous_mode,
};

Expand Down Expand Up @@ -636,9 +711,20 @@ static int atusb_probe(struct usb_interface *interface,

hw->parent = &usb_dev->dev;
hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
IEEE802154_HW_PROMISCUOUS;
IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS;

hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL |
WPAN_PHY_FLAG_CCA_MODE;

hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) |
BIT(NL802154_CCA_CARRIER) | BIT(NL802154_CCA_ENERGY_CARRIER);
hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND) |
BIT(NL802154_CCA_OPT_ENERGY_CARRIER_OR);

hw->phy->supported.cca_ed_levels = atusb_ed_levels;
hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(atusb_ed_levels);

hw->phy->flags = WPAN_PHY_FLAG_TXPOWER;
hw->phy->cca.mode = NL802154_CCA_ENERGY;

hw->phy->current_page = 0;
hw->phy->current_channel = 11; /* reset default */
Expand All @@ -647,6 +733,7 @@ static int atusb_probe(struct usb_interface *interface,
hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
hw->phy->transmit_power = hw->phy->supported.tx_powers[0];
ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
hw->phy->cca_ed_level = hw->phy->supported.cca_ed_levels[7];

atusb_command(atusb, ATUSB_RF_RESET, 0);
atusb_get_and_show_chip(atusb);
Expand Down
14 changes: 13 additions & 1 deletion drivers/net/ieee802154/mrf24j40.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#define REG_TXBCON0 0x1A
#define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */
#define BIT_TXNTRIG BIT(0)
#define BIT_TXNSECEN BIT(1)
#define BIT_TXNACKREQ BIT(2)

#define REG_TXG1CON 0x1C
Expand All @@ -85,10 +86,13 @@
#define REG_INTSTAT 0x31 /* Interrupt Status */
#define BIT_TXNIF BIT(0)
#define BIT_RXIF BIT(3)
#define BIT_SECIF BIT(4)
#define BIT_SECIGNORE BIT(7)

#define REG_INTCON 0x32 /* Interrupt Control */
#define BIT_TXNIE BIT(0)
#define BIT_RXIE BIT(3)
#define BIT_SECIE BIT(4)

#define REG_GPIO 0x33 /* GPIO */
#define REG_TRISGPIO 0x34 /* GPIO direction */
Expand Down Expand Up @@ -548,6 +552,9 @@ static void write_tx_buf_complete(void *context)
u8 val = BIT_TXNTRIG;
int ret;

if (ieee802154_is_secen(fc))
val |= BIT_TXNSECEN;

if (ieee802154_is_ackreq(fc))
val |= BIT_TXNACKREQ;

Expand Down Expand Up @@ -616,7 +623,7 @@ static int mrf24j40_start(struct ieee802154_hw *hw)

/* Clear TXNIE and RXIE. Enable interrupts */
return regmap_update_bits(devrec->regmap_short, REG_INTCON,
BIT_TXNIE | BIT_RXIE, 0);
BIT_TXNIE | BIT_RXIE | BIT_SECIE, 0);
}

static void mrf24j40_stop(struct ieee802154_hw *hw)
Expand Down Expand Up @@ -1025,6 +1032,11 @@ static void mrf24j40_intstat_complete(void *context)

enable_irq(devrec->spi->irq);

/* Ignore Rx security decryption */
if (intstat & BIT_SECIF)
regmap_write_async(devrec->regmap_short, REG_SECCON0,
BIT_SECIGNORE);

/* Check for TX complete */
if (intstat & BIT_TXNIF)
ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false);
Expand Down
45 changes: 42 additions & 3 deletions include/linux/ieee802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#define IEEE802154_ADDR_SHORT_UNSPEC 0xfffe

#define IEEE802154_EXTENDED_ADDR_LEN 8
#define IEEE802154_SHORT_ADDR_LEN 2

#define IEEE802154_LIFS_PERIOD 40
#define IEEE802154_SIFS_PERIOD 12
Expand Down Expand Up @@ -218,6 +219,7 @@ enum {
/* frame control handling */
#define IEEE802154_FCTL_FTYPE 0x0003
#define IEEE802154_FCTL_ACKREQ 0x0020
#define IEEE802154_FCTL_SECEN 0x0004
#define IEEE802154_FCTL_INTRA_PAN 0x0040

#define IEEE802154_FTYPE_DATA 0x0001
Expand All @@ -232,6 +234,15 @@ static inline int ieee802154_is_data(__le16 fc)
cpu_to_le16(IEEE802154_FTYPE_DATA);
}

/**
* ieee802154_is_secen - check if Security bit is set
* @fc: frame control bytes in little-endian byteorder
*/
static inline bool ieee802154_is_secen(__le16 fc)
{
return fc & cpu_to_le16(IEEE802154_FCTL_SECEN);
}

/**
* ieee802154_is_ackreq - check if acknowledgment request bit is set
* @fc: frame control bytes in little-endian byteorder
Expand Down Expand Up @@ -260,17 +271,17 @@ static inline bool ieee802154_is_intra_pan(__le16 fc)
*
* @len: psdu len with (MHR + payload + MFR)
*/
static inline bool ieee802154_is_valid_psdu_len(const u8 len)
static inline bool ieee802154_is_valid_psdu_len(u8 len)
{
return (len == IEEE802154_ACK_PSDU_LEN ||
(len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU));
}

/**
* ieee802154_is_valid_psdu_len - check if extended addr is valid
* ieee802154_is_valid_extended_unicast_addr - check if extended addr is valid
* @addr: extended addr to check
*/
static inline bool ieee802154_is_valid_extended_unicast_addr(const __le64 addr)
static inline bool ieee802154_is_valid_extended_unicast_addr(__le64 addr)
{
/* Bail out if the address is all zero, or if the group
* address bit is set.
Expand All @@ -279,6 +290,34 @@ static inline bool ieee802154_is_valid_extended_unicast_addr(const __le64 addr)
!(addr & cpu_to_le64(0x0100000000000000ULL)));
}

/**
* ieee802154_is_broadcast_short_addr - check if short addr is broadcast
* @addr: short addr to check
*/
static inline bool ieee802154_is_broadcast_short_addr(__le16 addr)
{
return (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST));
}

/**
* ieee802154_is_unspec_short_addr - check if short addr is unspecified
* @addr: short addr to check
*/
static inline bool ieee802154_is_unspec_short_addr(__le16 addr)
{
return (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC));
}

/**
* ieee802154_is_valid_src_short_addr - check if source short address is valid
* @addr: short addr to check
*/
static inline bool ieee802154_is_valid_src_short_addr(__le16 addr)
{
return !(ieee802154_is_broadcast_short_addr(addr) ||
ieee802154_is_unspec_short_addr(addr));
}

/**
* ieee802154_random_extended_addr - generates a random extended address
* @addr: extended addr pointer to place the random address
Expand Down
Loading

0 comments on commit c0b0479

Please sign in to comment.