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

This commit is contained in:
John W. Linville 2014-12-01 15:49:58 -05:00
commit 992066c8d3
13 changed files with 140 additions and 58 deletions

View File

@ -0,0 +1,29 @@
btmrvl
------
Required properties:
- compatible : must be "btmrvl,cfgdata"
Optional properties:
- btmrvl,cal-data : Calibration data downloaded to the device during
initialization. This is an array of 28 values(u8).
- btmrvl,gpio-gap : gpio and gap (in msecs) combination to be
configured.
Example:
GPIO pin 13 is configured as a wakeup source and GAP is set to 100 msecs
in below example.
btmrvl {
compatible = "btmrvl,cfgdata";
btmrvl,cal-data = /bits/ 8 <
0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0xf0 0x00>;
btmrvl,gpio-gap = <0x0d64>;
};

View File

@ -106,6 +106,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x13d3, 0x3402) },
{ USB_DEVICE(0x13d3, 0x3408) },
{ USB_DEVICE(0x13d3, 0x3432) }, { USB_DEVICE(0x13d3, 0x3432) },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
@ -158,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */

View File

@ -41,6 +41,11 @@ void btmrvl_interrupt(struct btmrvl_private *priv)
priv->adapter->int_count++; priv->adapter->int_count++;
if (priv->adapter->hs_state == HS_ACTIVATED) {
BT_DBG("BT: HS DEACTIVATED in ISR!\n");
priv->adapter->hs_state = HS_DEACTIVATED;
}
wake_up_interruptible(&priv->main_thread.wait_q); wake_up_interruptible(&priv->main_thread.wait_q);
} }
EXPORT_SYMBOL_GPL(btmrvl_interrupt); EXPORT_SYMBOL_GPL(btmrvl_interrupt);
@ -323,6 +328,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
} else { } else {
ret = priv->hw_wakeup_firmware(priv); ret = priv->hw_wakeup_firmware(priv);
priv->adapter->hs_state = HS_DEACTIVATED; priv->adapter->hs_state = HS_DEACTIVATED;
BT_DBG("BT: HS DEACTIVATED due to host activity!\n");
} }
} }
@ -492,29 +498,31 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv,
return 0; return 0;
} }
static int btmrvl_cal_data_dt(struct btmrvl_private *priv) static int btmrvl_check_device_tree(struct btmrvl_private *priv)
{ {
struct device_node *dt_node; struct device_node *dt_node;
u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE]; u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
const char name[] = "btmrvl_caldata";
const char property[] = "btmrvl,caldata";
int ret; int ret;
u32 val;
dt_node = of_find_node_by_name(NULL, name); for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") {
if (!dt_node) ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val);
return -ENODEV; if (!ret)
priv->btmrvl_dev.gpio_gap = val;
ret = of_property_read_u8_array(dt_node, property, ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data",
cal_data + BT_CAL_HDR_LEN, cal_data + BT_CAL_HDR_LEN,
BT_CAL_DATA_SIZE); BT_CAL_DATA_SIZE);
if (ret) if (ret)
return ret; return ret;
BT_DBG("Use cal data from device tree"); BT_DBG("Use cal data from device tree");
ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE); ret = btmrvl_download_cal_data(priv, cal_data,
if (ret) { BT_CAL_DATA_SIZE);
BT_ERR("Fail to download calibrate data"); if (ret) {
return ret; BT_ERR("Fail to download calibrate data");
return ret;
}
} }
return 0; return 0;
@ -526,14 +534,15 @@ static int btmrvl_setup(struct hci_dev *hdev)
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
btmrvl_cal_data_dt(priv); priv->btmrvl_dev.gpio_gap = 0xffff;
btmrvl_check_device_tree(priv);
btmrvl_pscan_window_reporting(priv, 0x01); btmrvl_pscan_window_reporting(priv, 0x01);
priv->btmrvl_dev.psmode = 1; priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv); btmrvl_enable_ps(priv);
priv->btmrvl_dev.gpio_gap = 0xffff;
btmrvl_send_hscfg_cmd(priv); btmrvl_send_hscfg_cmd(priv);
return 0; return 0;

View File

@ -185,6 +185,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */

View File

@ -130,6 +130,7 @@ struct smp_irk {
struct link_key { struct link_key {
struct list_head list; struct list_head list;
struct rcu_head rcu;
bdaddr_t bdaddr; bdaddr_t bdaddr;
u8 type; u8 type;
u8 val[HCI_LINK_KEY_SIZE]; u8 val[HCI_LINK_KEY_SIZE];

View File

@ -274,15 +274,13 @@ static const struct file_operations inquiry_cache_fops = {
static int link_keys_show(struct seq_file *f, void *ptr) static int link_keys_show(struct seq_file *f, void *ptr)
{ {
struct hci_dev *hdev = f->private; struct hci_dev *hdev = f->private;
struct list_head *p, *n; struct link_key *key;
hci_dev_lock(hdev); rcu_read_lock();
list_for_each_safe(p, n, &hdev->link_keys) { list_for_each_entry_rcu(key, &hdev->link_keys, list)
struct link_key *key = list_entry(p, struct link_key, list);
seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type, seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
HCI_LINK_KEY_SIZE, key->val, key->pin_len); HCI_LINK_KEY_SIZE, key->val, key->pin_len);
} rcu_read_unlock();
hci_dev_unlock(hdev);
return 0; return 0;
} }
@ -1128,6 +1126,7 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
err = hci_req_run(&req, hci_req_sync_complete); err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0) { if (err < 0) {
remove_wait_queue(&hdev->req_wait_q, &wait); remove_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_RUNNING);
return ERR_PTR(err); return ERR_PTR(err);
} }
@ -1196,6 +1195,7 @@ static int __hci_req_sync(struct hci_dev *hdev,
hdev->req_status = 0; hdev->req_status = 0;
remove_wait_queue(&hdev->req_wait_q, &wait); remove_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_RUNNING);
/* ENODATA means the HCI request command queue is empty. /* ENODATA means the HCI request command queue is empty.
* This can happen when a request with conditionals doesn't * This can happen when a request with conditionals doesn't
@ -3099,15 +3099,11 @@ void hci_uuids_clear(struct hci_dev *hdev)
void hci_link_keys_clear(struct hci_dev *hdev) void hci_link_keys_clear(struct hci_dev *hdev)
{ {
struct list_head *p, *n; struct link_key *key;
list_for_each_safe(p, n, &hdev->link_keys) { list_for_each_entry_rcu(key, &hdev->link_keys, list) {
struct link_key *key; list_del_rcu(&key->list);
kfree_rcu(key, rcu);
key = list_entry(p, struct link_key, list);
list_del(p);
kfree(key);
} }
} }
@ -3135,9 +3131,14 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{ {
struct link_key *k; struct link_key *k;
list_for_each_entry(k, &hdev->link_keys, list) rcu_read_lock();
if (bacmp(bdaddr, &k->bdaddr) == 0) list_for_each_entry_rcu(k, &hdev->link_keys, list) {
if (bacmp(bdaddr, &k->bdaddr) == 0) {
rcu_read_unlock();
return k; return k;
}
}
rcu_read_unlock();
return NULL; return NULL;
} }
@ -3288,7 +3289,7 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
key = kzalloc(sizeof(*key), GFP_KERNEL); key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key) if (!key)
return NULL; return NULL;
list_add(&key->list, &hdev->link_keys); list_add_rcu(&key->list, &hdev->link_keys);
} }
BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type); BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
@ -3381,8 +3382,8 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
BT_DBG("%s removing %pMR", hdev->name, bdaddr); BT_DBG("%s removing %pMR", hdev->name, bdaddr);
list_del(&key->list); list_del_rcu(&key->list);
kfree(key); kfree_rcu(key, rcu);
return 0; return 0;
} }

View File

@ -3191,6 +3191,38 @@ unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
{
if (key_type == HCI_LK_CHANGED_COMBINATION)
return;
conn->pin_length = pin_len;
conn->key_type = key_type;
switch (key_type) {
case HCI_LK_LOCAL_UNIT:
case HCI_LK_REMOTE_UNIT:
case HCI_LK_DEBUG_COMBINATION:
return;
case HCI_LK_COMBINATION:
if (pin_len == 16)
conn->pending_sec_level = BT_SECURITY_HIGH;
else
conn->pending_sec_level = BT_SECURITY_MEDIUM;
break;
case HCI_LK_UNAUTH_COMBINATION_P192:
case HCI_LK_UNAUTH_COMBINATION_P256:
conn->pending_sec_level = BT_SECURITY_MEDIUM;
break;
case HCI_LK_AUTH_COMBINATION_P192:
conn->pending_sec_level = BT_SECURITY_HIGH;
break;
case HCI_LK_AUTH_COMBINATION_P256:
conn->pending_sec_level = BT_SECURITY_FIPS;
break;
}
}
static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_ev_link_key_req *ev = (void *) skb->data; struct hci_ev_link_key_req *ev = (void *) skb->data;
@ -3232,8 +3264,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
goto not_found; goto not_found;
} }
conn->key_type = key->type; conn_set_key(conn, key->type, key->pin_len);
conn->pin_length = key->pin_len;
} }
bacpy(&cp.bdaddr, &ev->bdaddr); bacpy(&cp.bdaddr, &ev->bdaddr);
@ -3266,12 +3297,8 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn) { if (conn) {
hci_conn_hold(conn); hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT; conn->disc_timeout = HCI_DISCONN_TIMEOUT;
pin_len = conn->pin_length;
if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
conn->key_type = ev->key_type;
hci_conn_drop(conn); hci_conn_drop(conn);
conn_set_key(conn, ev->key_type, conn->pin_length);
} }
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!test_bit(HCI_MGMT, &hdev->dev_flags))
@ -3282,6 +3309,12 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (!key) if (!key)
goto unlock; goto unlock;
/* Update connection information since adding the key will have
* fixed up the type in the case of changed combination keys.
*/
if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
conn_set_key(conn, key->type, key->pin_len);
mgmt_new_link_key(hdev, key, persistent); mgmt_new_link_key(hdev, key, persistent);
/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
@ -3291,8 +3324,8 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
*/ */
if (key->type == HCI_LK_DEBUG_COMBINATION && if (key->type == HCI_LK_DEBUG_COMBINATION &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) { !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
list_del(&key->list); list_del_rcu(&key->list);
kfree(key); kfree_rcu(key, rcu);
} else if (conn) { } else if (conn) {
if (persistent) if (persistent)
clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);

View File

@ -840,7 +840,10 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
if (!skb) if (!skb)
return; return;
if (lmp_no_flush_capable(conn->hcon->hdev)) /* Use NO_FLUSH if supported or we have an LE link (which does
* not support auto-flushing packets) */
if (lmp_no_flush_capable(conn->hcon->hdev) ||
conn->hcon->type == LE_LINK)
flags = ACL_START_NO_FLUSH; flags = ACL_START_NO_FLUSH;
else else
flags = ACL_START; flags = ACL_START;
@ -874,8 +877,13 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
return; return;
} }
if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && /* Use NO_FLUSH for LE links (where this is the only option) or
lmp_no_flush_capable(hcon->hdev)) * if the BR/EDR link supports it and flushing has not been
* explicitly requested (through FLAG_FLUSHABLE).
*/
if (hcon->type == LE_LINK ||
(!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
lmp_no_flush_capable(hcon->hdev)))
flags = ACL_START_NO_FLUSH; flags = ACL_START_NO_FLUSH;
else else
flags = ACL_START; flags = ACL_START;

View File

@ -597,7 +597,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
entry->ldev = dev; entry->ldev = dev;
/* Set the lowpan harware address to the wpan hardware address. */ /* Set the lowpan hardware address to the wpan hardware address. */
memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN); memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx); mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);

View File

@ -1,5 +1,5 @@
/* /*
* Netlink inteface for IEEE 802.15.4 stack * Netlink interface for IEEE 802.15.4 stack
* *
* Copyright 2007, 2008 Siemens AG * Copyright 2007, 2008 Siemens AG
* *

View File

@ -1,5 +1,5 @@
/* /*
* Netlink inteface for IEEE 802.15.4 stack * Netlink interface for IEEE 802.15.4 stack
* *
* Copyright 2007, 2008 Siemens AG * Copyright 2007, 2008 Siemens AG
* *

View File

@ -1,5 +1,5 @@
/* /*
* Netlink inteface for IEEE 802.15.4 stack * Netlink interface for IEEE 802.15.4 stack
* *
* Copyright 2007, 2008 Siemens AG * Copyright 2007, 2008 Siemens AG
* *

View File

@ -510,11 +510,9 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name,
if (ret) if (ret)
goto err; goto err;
if (ndev) { ret = register_netdevice(ndev);
ret = register_netdevice(ndev); if (ret < 0)
if (ret < 0) goto err;
goto err;
}
mutex_lock(&local->iflist_mtx); mutex_lock(&local->iflist_mtx);
list_add_tail_rcu(&sdata->list, &local->interfaces); list_add_tail_rcu(&sdata->list, &local->interfaces);