Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

John W. Linville says:

====================
pull request: wireless 2014-06-18

Please pull this batch of fixes intended for the 3.16 stream!

For the Bluetooth bits, Gustavo says:

"This is our first batch of fixes for 3.16. Be aware that two patches here
are not exactly bugfixes:

* 71f28af57066 Bluetooth: Add clarifying comment for conn->auth_type
This commit just add some important security comments to the code, we found
it important enough to include it here for 3.16 since it is security related.

* 9f7ec8871132 Bluetooth: Refactor discovery stopping into its own function
This commit is just a refactor in a preparation for a fix in the next
commit (f8680f128b).

All the other patches are fixes for deadlocks and for the Bluetooth protocols,
most of them related to authentication and encryption."

On top of that...

Chin-Ran Lo fixes a problems with overlapping DMA areas in mwifiex.

Michael Braun corrects a couple of issues in order to enable a new
device in rt2800usb.

Rafał Miłecki reverts a b43 patch that caused a regression, fixes a
Kconfig typo, and corrects a frequency reporting error with the G-PHY.

Stanislaw Grsuzka fixes an rfkill regression for rt2500pci, and avoids
a rt2x00 scheduling while atomic BUG.

Please let me know if there are problems!
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-06-19 21:32:21 -07:00
Родитель 24599e61b7 2ee3f63d39
Коммит 1b0608fd9b
17 изменённых файлов: 200 добавлений и 92 удалений

Просмотреть файл

@ -36,7 +36,7 @@ config B43_SSB
choice choice
prompt "Supported bus types" prompt "Supported bus types"
depends on B43 depends on B43
default B43_BCMA_AND_SSB default B43_BUSES_BCMA_AND_SSB
config B43_BUSES_BCMA_AND_SSB config B43_BUSES_BCMA_AND_SSB
bool "BCMA and SSB" bool "BCMA and SSB"

Просмотреть файл

@ -5221,6 +5221,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
/* We don't support 5 GHz on some PHYs yet */ /* We don't support 5 GHz on some PHYs yet */
switch (dev->phy.type) { switch (dev->phy.type) {
case B43_PHYTYPE_A: case B43_PHYTYPE_A:
case B43_PHYTYPE_G:
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT: case B43_PHYTYPE_HT:

Просмотреть файл

@ -811,9 +811,13 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
break; break;
case B43_PHYTYPE_G: case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ; status.band = IEEE80211_BAND_2GHZ;
/* chanid is the radio channel cookie value as used /* Somewhere between 478.104 and 508.1084 firmware for G-PHY
* to tune the radio. */ * has been modified to be compatible with N-PHY and others.
status.freq = chanid + 2400; */
if (dev->fw.rev >= 508)
status.freq = ieee80211_channel_to_frequency(chanid, status.band);
else
status.freq = chanid + 2400;
break; break;
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:

Просмотреть файл

@ -50,7 +50,7 @@ mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
return -1; return -1;
} }
mapping.len = size; mapping.len = size;
memcpy(skb->cb, &mapping, sizeof(mapping)); mwifiex_store_mapping(skb, &mapping);
return 0; return 0;
} }
@ -60,7 +60,7 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
struct pcie_service_card *card = adapter->card; struct pcie_service_card *card = adapter->card;
struct mwifiex_dma_mapping mapping; struct mwifiex_dma_mapping mapping;
MWIFIEX_SKB_PACB(skb, &mapping); mwifiex_get_mapping(skb, &mapping);
pci_unmap_single(card->dev, mapping.addr, mapping.len, flags); pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
} }

Просмотреть файл

@ -20,32 +20,55 @@
#ifndef _MWIFIEX_UTIL_H_ #ifndef _MWIFIEX_UTIL_H_
#define _MWIFIEX_UTIL_H_ #define _MWIFIEX_UTIL_H_
static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
{
return (struct mwifiex_rxinfo *)(skb->cb + sizeof(dma_addr_t));
}
static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
{
return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t));
}
struct mwifiex_dma_mapping { struct mwifiex_dma_mapping {
dma_addr_t addr; dma_addr_t addr;
size_t len; size_t len;
}; };
static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, struct mwifiex_cb {
struct mwifiex_dma_mapping *mapping) struct mwifiex_dma_mapping dma_mapping;
union {
struct mwifiex_rxinfo rx_info;
struct mwifiex_txinfo tx_info;
};
};
static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
{ {
memcpy(mapping, skb->cb, sizeof(*mapping)); struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb));
return &cb->rx_info;
}
static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
{
struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
return &cb->tx_info;
}
static inline void mwifiex_store_mapping(struct sk_buff *skb,
struct mwifiex_dma_mapping *mapping)
{
struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
memcpy(&cb->dma_mapping, mapping, sizeof(*mapping));
}
static inline void mwifiex_get_mapping(struct sk_buff *skb,
struct mwifiex_dma_mapping *mapping)
{
struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
memcpy(mapping, &cb->dma_mapping, sizeof(*mapping));
} }
static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb) static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb)
{ {
struct mwifiex_dma_mapping mapping; struct mwifiex_dma_mapping mapping;
MWIFIEX_SKB_PACB(skb, &mapping); mwifiex_get_mapping(skb, &mapping);
return mapping.addr; return mapping.addr;
} }

Просмотреть файл

@ -1681,8 +1681,13 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/* /*
* Detect if this device has an hardware controlled radio. * Detect if this device has an hardware controlled radio.
*/ */
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) {
__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
/*
* On this device RFKILL initialized during probe does not work.
*/
__set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags);
}
/* /*
* Check if the BBP tuning should be enabled. * Check if the BBP tuning should be enabled.

Просмотреть файл

@ -229,6 +229,27 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
/* /*
* Firmware functions * Firmware functions
*/ */
static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
{
__le32 reg;
u32 fw_mode;
/* cannot use rt2x00usb_register_read here as it uses different
* mode (MULTI_READ vs. DEVICE_MODE) and does not pass the
* magic value USB_MODE_AUTORUN (0x11) to the device, thus the
* returned value would be invalid.
*/
rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
USB_VENDOR_REQUEST_IN, 0, USB_MODE_AUTORUN,
&reg, sizeof(reg), REGISTER_TIMEOUT_FIRMWARE);
fw_mode = le32_to_cpu(reg);
if ((fw_mode & 0x00000003) == 2)
return 1;
return 0;
}
static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{ {
return FIRMWARE_RT2870; return FIRMWARE_RT2870;
@ -257,8 +278,13 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
/* /*
* Write firmware to device. * Write firmware to device.
*/ */
rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, if (rt2800usb_autorun_detect(rt2x00dev)) {
data + offset, length); rt2x00_info(rt2x00dev,
"Firmware loading not required - NIC in AutoRun mode\n");
} else {
rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
data + offset, length);
}
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
@ -735,11 +761,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
/* /*
* Device probe functions. * Device probe functions.
*/ */
static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
{
if (rt2800usb_autorun_detect(rt2x00dev))
return 1;
return rt2800_efuse_detect(rt2x00dev);
}
static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
if (rt2800_efuse_detect(rt2x00dev)) if (rt2800usb_efuse_detect(rt2x00dev))
retval = rt2800_read_eeprom_efuse(rt2x00dev); retval = rt2800_read_eeprom_efuse(rt2x00dev);
else else
retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,

Просмотреть файл

@ -693,6 +693,7 @@ enum rt2x00_capability_flags {
REQUIRE_SW_SEQNO, REQUIRE_SW_SEQNO,
REQUIRE_HT_TX_DESC, REQUIRE_HT_TX_DESC,
REQUIRE_PS_AUTOWAKE, REQUIRE_PS_AUTOWAKE,
REQUIRE_DELAYED_RFKILL,
/* /*
* Capabilities * Capabilities

Просмотреть файл

@ -1126,9 +1126,10 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
return; return;
/* /*
* Unregister extra components. * Stop rfkill polling.
*/ */
rt2x00rfkill_unregister(rt2x00dev); if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
rt2x00rfkill_unregister(rt2x00dev);
/* /*
* Allow the HW to uninitialize. * Allow the HW to uninitialize.
@ -1166,6 +1167,12 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
/*
* Start rfkill polling.
*/
if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
rt2x00rfkill_register(rt2x00dev);
return 0; return 0;
} }
@ -1375,7 +1382,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00link_register(rt2x00dev); rt2x00link_register(rt2x00dev);
rt2x00leds_register(rt2x00dev); rt2x00leds_register(rt2x00dev);
rt2x00debug_register(rt2x00dev); rt2x00debug_register(rt2x00dev);
rt2x00rfkill_register(rt2x00dev);
/*
* Start rfkill polling.
*/
if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
rt2x00rfkill_register(rt2x00dev);
return 0; return 0;
@ -1390,6 +1402,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
{ {
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
/*
* Stop rfkill polling.
*/
if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
rt2x00rfkill_unregister(rt2x00dev);
/* /*
* Disable radio. * Disable radio.
*/ */

Просмотреть файл

@ -487,6 +487,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
crypto.cipher = rt2x00crypto_key_to_cipher(key); crypto.cipher = rt2x00crypto_key_to_cipher(key);
if (crypto.cipher == CIPHER_NONE) if (crypto.cipher == CIPHER_NONE)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev))
return -EOPNOTSUPP;
crypto.cmd = cmd; crypto.cmd = cmd;

Просмотреть файл

@ -93,6 +93,7 @@ enum rt2x00usb_mode_offset {
USB_MODE_SLEEP = 7, /* RT73USB */ USB_MODE_SLEEP = 7, /* RT73USB */
USB_MODE_FIRMWARE = 8, /* RT73USB */ USB_MODE_FIRMWARE = 8, /* RT73USB */
USB_MODE_WAKEUP = 9, /* RT73USB */ USB_MODE_WAKEUP = 9, /* RT73USB */
USB_MODE_AUTORUN = 17, /* RT2800USB */
}; };
/** /**

Просмотреть файл

@ -610,11 +610,6 @@ 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;
/* Save the address type used for this connnection attempt so we able
* to retrieve this information if we need it.
*/
conn->src_type = own_addr_type;
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 = cpu_to_le16(hdev->le_scan_window);
bacpy(&cp.peer_addr, &conn->dst); bacpy(&cp.peer_addr, &conn->dst);
@ -894,7 +889,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
/* If we're already encrypted set the REAUTH_PEND flag, /* If we're already encrypted set the REAUTH_PEND flag,
* otherwise set the ENCRYPT_PEND. * otherwise set the ENCRYPT_PEND.
*/ */
if (conn->key_type != 0xff) if (conn->link_mode & HCI_LM_ENCRYPT)
set_bit(HCI_CONN_REAUTH_PEND, &conn->flags); set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
else else
set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);

Просмотреть файл

@ -48,6 +48,10 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
wake_up_bit(&hdev->flags, HCI_INQUIRY); wake_up_bit(&hdev->flags, HCI_INQUIRY);
hci_dev_lock(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
hci_conn_check_pending(hdev); hci_conn_check_pending(hdev);
} }
@ -3537,7 +3541,11 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
cp.authentication = conn->auth_type; cp.authentication = conn->auth_type;
/* Request MITM protection if our IO caps allow it /* Request MITM protection if our IO caps allow it
* except for the no-bonding case * except for the no-bonding case.
* conn->auth_type is not updated here since
* that might cause the user confirmation to be
* rejected in case the remote doesn't have the
* IO capabilities for MITM.
*/ */
if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
cp.authentication != HCI_AT_NO_BONDING) cp.authentication != HCI_AT_NO_BONDING)
@ -3628,8 +3636,11 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
/* If we're not the initiators request authorization to /* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with * proceed from user space (mgmt_user_confirm with
* confirm_hint set to 1). */ * confirm_hint set to 1). The exception is if neither
if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { * side had MITM in which case we do auto-accept.
*/
if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
(loc_mitm || rem_mitm)) {
BT_DBG("Confirming auto-accept as acceptor"); BT_DBG("Confirming auto-accept as acceptor");
confirm_hint = 1; confirm_hint = 1;
goto confirm; goto confirm;

Просмотреть файл

@ -1663,7 +1663,13 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
kfree_skb(conn->rx_skb); kfree_skb(conn->rx_skb);
skb_queue_purge(&conn->pending_rx); skb_queue_purge(&conn->pending_rx);
flush_work(&conn->pending_rx_work);
/* We can not call flush_work(&conn->pending_rx_work) here since we
* might block if we are running on a worker from the same workqueue
* pending_rx_work is waiting on.
*/
if (work_pending(&conn->pending_rx_work))
cancel_work_sync(&conn->pending_rx_work);
l2cap_unregister_all_users(conn); l2cap_unregister_all_users(conn);

Просмотреть файл

@ -787,11 +787,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
/*change security for LE channels */ /*change security for LE channels */
if (chan->scid == L2CAP_CID_ATT) { if (chan->scid == L2CAP_CID_ATT) {
if (!conn->hcon->out) {
err = -EINVAL;
break;
}
if (smp_conn_security(conn->hcon, sec.level)) if (smp_conn_security(conn->hcon, sec.level))
break; break;
sk->sk_state = BT_CONFIG; sk->sk_state = BT_CONFIG;

Просмотреть файл

@ -1047,6 +1047,43 @@ static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
} }
} }
static void hci_stop_discovery(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_remote_name_req_cancel cp;
struct inquiry_entry *e;
switch (hdev->discovery.state) {
case DISCOVERY_FINDING:
if (test_bit(HCI_INQUIRY, &hdev->flags)) {
hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
} else {
cancel_delayed_work(&hdev->le_scan_disable);
hci_req_add_le_scan_disable(req);
}
break;
case DISCOVERY_RESOLVING:
e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
NAME_PENDING);
if (!e)
return;
bacpy(&cp.bdaddr, &e->data.bdaddr);
hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
&cp);
break;
default:
/* Passive scanning */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
hci_req_add_le_scan_disable(req);
break;
}
}
static int clean_up_hci_state(struct hci_dev *hdev) static int clean_up_hci_state(struct hci_dev *hdev)
{ {
struct hci_request req; struct hci_request req;
@ -1063,9 +1100,7 @@ static int clean_up_hci_state(struct hci_dev *hdev)
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
disable_advertising(&req); disable_advertising(&req);
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { hci_stop_discovery(&req);
hci_req_add_le_scan_disable(&req);
}
list_for_each_entry(conn, &hdev->conn_hash.list, list) { list_for_each_entry(conn, &hdev->conn_hash.list, list) {
struct hci_cp_disconnect dc; struct hci_cp_disconnect dc;
@ -2996,8 +3031,13 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
} }
if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
/* Continue with pairing via SMP */ /* Continue with pairing via SMP. The hdev lock must be
* released as SMP may try to recquire it for crypto
* purposes.
*/
hci_dev_unlock(hdev);
err = smp_user_confirm_reply(conn, mgmt_op, passkey); err = smp_user_confirm_reply(conn, mgmt_op, passkey);
hci_dev_lock(hdev);
if (!err) if (!err)
err = cmd_complete(sk, hdev->id, mgmt_op, err = cmd_complete(sk, hdev->id, mgmt_op,
@ -3574,8 +3614,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
{ {
struct mgmt_cp_stop_discovery *mgmt_cp = data; struct mgmt_cp_stop_discovery *mgmt_cp = data;
struct pending_cmd *cmd; struct pending_cmd *cmd;
struct hci_cp_remote_name_req_cancel cp;
struct inquiry_entry *e;
struct hci_request req; struct hci_request req;
int err; int err;
@ -3605,52 +3643,22 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
switch (hdev->discovery.state) { hci_stop_discovery(&req);
case DISCOVERY_FINDING:
if (test_bit(HCI_INQUIRY, &hdev->flags)) {
hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
} else {
cancel_delayed_work(&hdev->le_scan_disable);
hci_req_add_le_scan_disable(&req); err = hci_req_run(&req, stop_discovery_complete);
} if (!err) {
hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
break;
case DISCOVERY_RESOLVING:
e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
NAME_PENDING);
if (!e) {
mgmt_pending_remove(cmd);
err = cmd_complete(sk, hdev->id,
MGMT_OP_STOP_DISCOVERY, 0,
&mgmt_cp->type,
sizeof(mgmt_cp->type));
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
goto unlock;
}
bacpy(&cp.bdaddr, &e->data.bdaddr);
hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
&cp);
break;
default:
BT_DBG("unknown discovery state %u", hdev->discovery.state);
mgmt_pending_remove(cmd);
err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_FAILED, &mgmt_cp->type,
sizeof(mgmt_cp->type));
goto unlock; goto unlock;
} }
err = hci_req_run(&req, stop_discovery_complete); mgmt_pending_remove(cmd);
if (err < 0)
mgmt_pending_remove(cmd); /* If no HCI commands were sent we're done */
else if (err == -ENODATA) {
hci_discovery_set_state(hdev, DISCOVERY_STOPPING); err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
&mgmt_cp->type, sizeof(mgmt_cp->type));
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
}
unlock: unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);

Просмотреть файл

@ -544,7 +544,7 @@ static u8 smp_random(struct smp_chan *smp)
hci_le_start_enc(hcon, ediv, rand, stk); hci_le_start_enc(hcon, ediv, rand, stk);
hcon->enc_key_size = smp->enc_key_size; hcon->enc_key_size = smp->enc_key_size;
} else { } else {
u8 stk[16]; u8 stk[16], auth;
__le64 rand = 0; __le64 rand = 0;
__le16 ediv = 0; __le16 ediv = 0;
@ -556,8 +556,13 @@ static u8 smp_random(struct smp_chan *smp)
memset(stk + smp->enc_key_size, 0, memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
if (hcon->pending_sec_level == BT_SECURITY_HIGH)
auth = 1;
else
auth = 0;
hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
HCI_SMP_STK_SLAVE, 0, stk, smp->enc_key_size, HCI_SMP_STK_SLAVE, auth, stk, smp->enc_key_size,
ediv, rand); ediv, rand);
} }