Commit 250fbf12 authored by David S. Miller's avatar David S. Miller
Browse files

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 2016-01-08

Here's one more bluetooth-next pull request for the 4.5 kernel:

 - Support for CRC check and promiscuous mode for CC2520
 - Fixes to btmrvl driver
 - New ACPI IDs for hci_bcm driver
 - Limited Discovery support for the Bluetooth mgmt interface
 - Minor other cleanups here and there

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a33ad9ac 8cf60cf2
......@@ -89,6 +89,7 @@ struct btmrvl_adapter {
wait_queue_head_t event_hs_wait_q;
u8 cmd_complete;
bool is_suspended;
bool is_suspending;
};
struct btmrvl_private {
......
......@@ -436,6 +436,11 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("type=%d, len=%d", hci_skb_pkt_type(skb), skb->len);
if (priv->adapter->is_suspending || priv->adapter->is_suspended) {
BT_ERR("%s: Device is suspending or suspended", __func__);
return -EBUSY;
}
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
......@@ -452,7 +457,8 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
skb_queue_tail(&priv->adapter->tx_queue, skb);
wake_up_interruptible(&priv->main_thread.wait_q);
if (!priv->adapter->is_suspended)
wake_up_interruptible(&priv->main_thread.wait_q);
return 0;
}
......@@ -543,7 +549,7 @@ static int btmrvl_setup(struct hci_dev *hdev)
if (ret)
return ret;
priv->btmrvl_dev.gpio_gap = 0xffff;
priv->btmrvl_dev.gpio_gap = 0xfffe;
btmrvl_check_device_tree(priv);
......@@ -643,7 +649,8 @@ static int btmrvl_service_main_thread(void *data)
if (adapter->ps_state == PS_SLEEP)
continue;
if (!priv->btmrvl_dev.tx_dnld_rdy)
if (!priv->btmrvl_dev.tx_dnld_rdy ||
priv->adapter->is_suspended)
continue;
skb = skb_dequeue(&adapter->tx_queue);
......
......@@ -1112,7 +1112,8 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
*/
if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
BT_ERR("FW failed to be active in time!");
return -ETIMEDOUT;
ret = -ETIMEDOUT;
goto done;
}
sdio_release_host(card->func);
......@@ -1544,10 +1545,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
priv = card->priv;
priv->adapter->is_suspending = true;
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO suspend", hcidev->name);
hci_suspend_dev(hcidev);
skb_queue_purge(&priv->adapter->tx_queue);
if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
......@@ -1556,6 +1557,7 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
}
priv->adapter->is_suspending = false;
priv->adapter->is_suspended = true;
/* We will keep the power when hs enabled successfully */
......
......@@ -814,9 +814,16 @@ static const struct hci_uart_proto bcm_proto = {
#ifdef CONFIG_ACPI
static const struct acpi_device_id bcm_acpi_match[] = {
{ "BCM2E1A", 0 },
{ "BCM2E39", 0 },
{ "BCM2E3A", 0 },
{ "BCM2E3D", 0 },
{ "BCM2E3F", 0 },
{ "BCM2E40", 0 },
{ "BCM2E64", 0 },
{ "BCM2E65", 0 },
{ "BCM2E67", 0 },
{ "BCM2E7B", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
......
......@@ -21,6 +21,8 @@
#include <linux/skbuff.h>
#include <linux/of_gpio.h>
#include <linux/ieee802154.h>
#include <linux/crc-ccitt.h>
#include <asm/unaligned.h>
#include <net/mac802154.h>
#include <net/cfg802154.h>
......@@ -189,6 +191,18 @@
#define CC2520_RXFIFOCNT 0x3E
#define CC2520_TXFIFOCNT 0x3F
/* CC2520_FRMFILT0 */
#define FRMFILT0_FRAME_FILTER_EN BIT(0)
#define FRMFILT0_PAN_COORDINATOR BIT(1)
/* CC2520_FRMCTRL0 */
#define FRMCTRL0_AUTOACK BIT(5)
#define FRMCTRL0_AUTOCRC BIT(6)
/* CC2520_FRMCTRL1 */
#define FRMCTRL1_SET_RXENMASK_ON_TX BIT(0)
#define FRMCTRL1_IGNORE_TX_UNDERF BIT(1)
/* Driver private information */
struct cc2520_private {
struct spi_device *spi; /* SPI device structure */
......@@ -201,6 +215,7 @@ struct cc2520_private {
struct work_struct fifop_irqwork;/* Workqueue for FIFOP */
spinlock_t lock; /* Lock for is_tx*/
struct completion tx_complete; /* Work completion for Tx */
bool promiscuous; /* Flag for promiscuous mode */
};
/* Generic Functions */
......@@ -367,14 +382,14 @@ cc2520_read_register(struct cc2520_private *priv, u8 reg, u8 *data)
}
static int
cc2520_write_txfifo(struct cc2520_private *priv, u8 *data, u8 len)
cc2520_write_txfifo(struct cc2520_private *priv, u8 pkt_len, u8 *data, u8 len)
{
int status;
/* length byte must include FCS even
* if it is calculated in the hardware
*/
int len_byte = len + 2;
int len_byte = pkt_len;
struct spi_message msg;
......@@ -414,7 +429,7 @@ cc2520_write_txfifo(struct cc2520_private *priv, u8 *data, u8 len)
}
static int
cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len, u8 *lqi)
cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len)
{
int status;
struct spi_message msg;
......@@ -470,12 +485,25 @@ cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
unsigned long flags;
int rc;
u8 status = 0;
u8 pkt_len;
/* In promiscuous mode we disable AUTOCRC so we can get the raw CRC
* values on RX. This means we need to manually add the CRC on TX.
*/
if (priv->promiscuous) {
u16 crc = crc_ccitt(0, skb->data, skb->len);
put_unaligned_le16(crc, skb_put(skb, 2));
pkt_len = skb->len;
} else {
pkt_len = skb->len + 2;
}
rc = cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
if (rc)
goto err_tx;
rc = cc2520_write_txfifo(priv, skb->data, skb->len);
rc = cc2520_write_txfifo(priv, pkt_len, skb->data, skb->len);
if (rc)
goto err_tx;
......@@ -518,22 +546,62 @@ static int cc2520_rx(struct cc2520_private *priv)
u8 len = 0, lqi = 0, bytes = 1;
struct sk_buff *skb;
cc2520_read_rxfifo(priv, &len, bytes, &lqi);
/* Read single length byte from the radio. */
cc2520_read_rxfifo(priv, &len, bytes);
if (len < 2 || len > IEEE802154_MTU)
return -EINVAL;
if (!ieee802154_is_valid_psdu_len(len)) {
/* Corrupted frame received, clear frame buffer by
* reading entire buffer.
*/
dev_dbg(&priv->spi->dev, "corrupted frame received\n");
len = IEEE802154_MTU;
}
skb = dev_alloc_skb(len);
if (!skb)
return -ENOMEM;
if (cc2520_read_rxfifo(priv, skb_put(skb, len), len, &lqi)) {
if (cc2520_read_rxfifo(priv, skb_put(skb, len), len)) {
dev_dbg(&priv->spi->dev, "frame reception failed\n");
kfree_skb(skb);
return -EINVAL;
}
skb_trim(skb, skb->len - 2);
/* In promiscuous mode, we configure the radio to include the
* CRC (AUTOCRC==0) and we pass on the packet unconditionally. If not
* in promiscuous mode, we check the CRC here, but leave the
* RSSI/LQI/CRC_OK bytes as they will get removed in the mac layer.
*/
if (!priv->promiscuous) {
bool crc_ok;
/* Check if the CRC is valid. With AUTOCRC set, the most
* significant bit of the last byte returned from the CC2520
* is CRC_OK flag. See section 20.3.4 of the datasheet.
*/
crc_ok = skb->data[len - 1] & BIT(7);
/* If we failed CRC drop the packet in the driver layer. */
if (!crc_ok) {
dev_dbg(&priv->spi->dev, "CRC check failed\n");
kfree_skb(skb);
return -EINVAL;
}
/* To calculate LQI, the lower 7 bits of the last byte (the
* correlation value provided by the radio) must be scaled to
* the range 0-255. According to section 20.6, the correlation
* value ranges from 50-110. Ideally this would be calibrated
* per hardware design, but we use roughly the datasheet values
* to get close enough while avoiding floating point.
*/
lqi = skb->data[len - 1] & 0x7f;
if (lqi < 50)
lqi = 50;
else if (lqi > 113)
lqi = 113;
lqi = (lqi - 50) * 4;
}
ieee802154_rx_irqsafe(priv->hw, skb, lqi);
......@@ -619,14 +687,19 @@ cc2520_filter(struct ieee802154_hw *hw,
}
if (changed & IEEE802154_AFILT_PANC_CHANGED) {
u8 frmfilt0;
dev_vdbg(&priv->spi->dev,
"cc2520_filter called for panc change\n");
cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
if (filt->pan_coord)
ret = cc2520_write_register(priv, CC2520_FRMFILT0,
0x02);
frmfilt0 |= FRMFILT0_PAN_COORDINATOR;
else
ret = cc2520_write_register(priv, CC2520_FRMFILT0,
0x00);
frmfilt0 &= ~FRMFILT0_PAN_COORDINATOR;
ret = cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
}
return ret;
......@@ -723,6 +796,30 @@ cc2520_set_txpower(struct ieee802154_hw *hw, s32 mbm)
return cc2520_cc2591_set_tx_power(priv, mbm);
}
static int
cc2520_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
{
struct cc2520_private *priv = hw->priv;
u8 frmfilt0;
dev_dbg(&priv->spi->dev, "%s : mode %d\n", __func__, on);
priv->promiscuous = on;
cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
if (on) {
/* Disable automatic ACK, automatic CRC, and frame filtering. */
cc2520_write_register(priv, CC2520_FRMCTRL0, 0);
frmfilt0 &= ~FRMFILT0_FRAME_FILTER_EN;
} else {
cc2520_write_register(priv, CC2520_FRMCTRL0, FRMCTRL0_AUTOACK |
FRMCTRL0_AUTOCRC);
frmfilt0 |= FRMFILT0_FRAME_FILTER_EN;
}
return cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
}
static const struct ieee802154_ops cc2520_ops = {
.owner = THIS_MODULE,
.start = cc2520_start,
......@@ -732,6 +829,7 @@ static const struct ieee802154_ops cc2520_ops = {
.set_channel = cc2520_set_channel,
.set_hw_addr_filt = cc2520_filter,
.set_txpower = cc2520_set_txpower,
.set_promiscuous_mode = cc2520_set_promiscuous_mode,
};
static int cc2520_register(struct cc2520_private *priv)
......@@ -749,7 +847,8 @@ static int cc2520_register(struct cc2520_private *priv)
/* We do support only 2.4 Ghz */
priv->hw->phy->supported.channels[0] = 0x7FFF800;
priv->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT;
priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
IEEE802154_HW_PROMISCUOUS;
priv->hw->phy->flags = WPAN_PHY_FLAG_TXPOWER;
......@@ -919,6 +1018,11 @@ static int cc2520_hw_init(struct cc2520_private *priv)
}
/* Registers default value: section 28.1 in Datasheet */
/* Set the CCA threshold to -50 dBm. This seems to have been copied
* from the TinyOS CC2520 driver and is much higher than the -84 dBm
* threshold suggested in the datasheet.
*/
ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A);
if (ret)
goto err_ret;
......@@ -955,15 +1059,10 @@ static int cc2520_hw_init(struct cc2520_private *priv)
if (ret)
goto err_ret;
ret = cc2520_write_register(priv, CC2520_FRMCTRL0, 0x60);
if (ret)
goto err_ret;
ret = cc2520_write_register(priv, CC2520_FRMCTRL1, 0x03);
if (ret)
goto err_ret;
ret = cc2520_write_register(priv, CC2520_FRMFILT0, 0x00);
/* Configure registers correctly for this driver. */
ret = cc2520_write_register(priv, CC2520_FRMCTRL1,
FRMCTRL1_SET_RXENMASK_ON_TX |
FRMCTRL1_IGNORE_TX_UNDERF);
if (ret)
goto err_ret;
......
......@@ -77,6 +77,7 @@ struct discovery_state {
u8 last_adv_data_len;
bool report_invalid_rssi;
bool result_filtering;
bool limited;
s8 rssi;
u16 uuid_count;
u8 (*uuids)[16];
......@@ -1283,31 +1284,41 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
mutex_unlock(&hci_cb_list_lock);
}
static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
static inline void *eir_get_data(u8 *eir, size_t eir_len, u8 type,
size_t *data_len)
{
size_t parsed = 0;
if (data_len < 2)
return false;
if (eir_len < 2)
return NULL;
while (parsed < data_len - 1) {
u8 field_len = data[0];
while (parsed < eir_len - 1) {
u8 field_len = eir[0];
if (field_len == 0)
break;
parsed += field_len + 1;
if (parsed > data_len)
if (parsed > eir_len)
break;
if (data[1] == type)
return true;
if (eir[1] != type) {
eir += field_len + 1;
continue;
}
/* Zero length data */
if (field_len == 1)
return NULL;
data += field_len + 1;
if (data_len)
*data_len = field_len - 1;
return &eir[2];
}
return false;
return NULL;
}
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
......
......@@ -584,6 +584,8 @@ struct mgmt_rp_get_adv_size_info {
__u8 max_scan_rsp_len;
} __packed;
#define MGMT_OP_START_LIMITED_DISCOVERY 0x0041
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
......
......@@ -337,7 +337,7 @@ struct ieee802154_mlme_ops {
void (*get_mac_params)(struct net_device *dev,
struct ieee802154_mac_params *params);
struct ieee802154_llsec_ops *llsec;
const struct ieee802154_llsec_ops *llsec;
};
static inline struct ieee802154_mlme_ops *
......
......@@ -3833,9 +3833,9 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
data.ssp_mode = 0x01;
if (hci_dev_test_flag(hdev, HCI_MGMT))
name_known = eir_has_data_type(info->data,
sizeof(info->data),
EIR_NAME_COMPLETE);
name_known = eir_get_data(info->data,
sizeof(info->data),
EIR_NAME_COMPLETE, NULL);
else
name_known = true;
......
......@@ -1737,8 +1737,8 @@ static int le_scan_disable(struct hci_request *req, unsigned long opt)
static int bredr_inquiry(struct hci_request *req, unsigned long opt)
{
u8 length = opt;
/* General inquiry access code (GIAC) */
u8 lap[3] = { 0x33, 0x8b, 0x9e };
const u8 giac[3] = { 0x33, 0x8b, 0x9e };
const u8 liac[3] = { 0x00, 0x8b, 0x9e };
struct hci_cp_inquiry cp;
BT_DBG("%s", req->hdev->name);
......@@ -1748,7 +1748,12 @@ static int bredr_inquiry(struct hci_request *req, unsigned long opt)
hci_dev_unlock(req->hdev);
memset(&cp, 0, sizeof(cp));
memcpy(&cp.lap, lap, sizeof(cp.lap));
if (req->hdev->discovery.limited)
memcpy(&cp.lap, liac, sizeof(cp.lap));
else
memcpy(&cp.lap, giac, sizeof(cp.lap));
cp.length = length;
hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
......
......@@ -25,9 +25,8 @@
/* Bluetooth HCI sockets. */
#include <linux/export.h>
#include <linux/utsname.h>
#include <asm/unaligned.h>
#include <generated/compile.h>
#include <generated/utsrelease.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
......@@ -385,17 +384,26 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
return skb;
}
static void send_monitor_note(struct sock *sk, const char *text)
static void __printf(2, 3)
send_monitor_note(struct sock *sk, const char *fmt, ...)
{
size_t len = strlen(text);
size_t len;
struct hci_mon_hdr *hdr;
struct sk_buff *skb;
va_list args;
va_start(args, fmt);
len = vsnprintf(NULL, 0, fmt, args);
va_end(args);
skb = bt_skb_alloc(len + 1, GFP_ATOMIC);
if (!skb)
return;
strcpy(skb_put(skb, len + 1), text);
va_start(args, fmt);
vsprintf(skb_put(skb, len), fmt, args);
*skb_put(skb, 1) = 0;
va_end(args);
__net_timestamp(skb);
......@@ -897,10 +905,11 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
*/
hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
send_monitor_note(sk, "Linux version " UTS_RELEASE
" (" UTS_MACHINE ")");
send_monitor_note(sk, "Bluetooth subsystem version "
BT_SUBSYS_VERSION);
send_monitor_note(sk, "Linux version %s (%s)",
init_utsname()->release,
init_utsname()->machine);
send_monitor_note(sk, "Bluetooth subsystem version %s",
BT_SUBSYS_VERSION);
send_monitor_replay(sk);
atomic_inc(&monitor_promisc);
......
......@@ -103,6 +103,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_ADD_ADVERTISING,
MGMT_OP_REMOVE_ADVERTISING,
MGMT_OP_GET_ADV_SIZE_INFO,
MGMT_OP_START_LIMITED_DISCOVERY,
};
static const u16 mgmt_events[] = {
......@@ -3283,6 +3284,9 @@ void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
if (!cmd)
cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
if (!cmd)
cmd = pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev);
if (cmd) {
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
......@@ -3318,8 +3322,8 @@ static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
return true;
}
static int start_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
u16 op, void *data, u16 len)
{
struct mgmt_cp_start_discovery *cp = data;
struct mgmt_pending_cmd *cmd;
......@@ -3331,7 +3335,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
err = mgmt_cmd_complete(sk, hdev->id, op,
MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type));
goto failed;
......@@ -3339,15 +3343,14 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
if (hdev->discovery.state != DISCOVERY_STOPPED ||
hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
&cp->type, sizeof(cp->type));
goto failed;
}
if (!discovery_type_is_valid(hdev, cp->type, &status)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
status, &cp->type, sizeof(cp->type));
err = mgmt_cmd_complete(sk, hdev->id, op, status,
&cp->type, sizeof(cp->type));
goto failed;
}
......@@ -3358,8 +3361,12 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
hdev->discovery.type = cp->type;
hdev->discovery.report_invalid_rssi = false;
if (op == MGMT_OP_START_LIMITED_DISCOVERY)
hdev->discovery.limited = true;
else
hdev->discovery.limited = false;
cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
cmd = mgmt_pending_add(sk, op, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
......@@ -3376,6 +3383,21 @@ failed:
return err;
}
static int start_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
return start_discovery_internal(sk, hdev, MGMT_OP_START_DISCOVERY,
data, len);
}
static int start_limited_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
return start_discovery_internal(sk, hdev,
MGMT_OP_START_LIMITED_DISCOVERY,
data, len);