summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller2014-03-26 00:25:39 +0100
committerDavid S. Miller2014-03-26 00:25:39 +0100
commit0fc31966035d7a540c011b6c967ce8eae1db121b (patch)
tree83f328a064cb123a10f5977c69ec3e28396970bc /net
parentxen-netback: Proper printf format for ptrdiff_t is 't'. (diff)
parentMerge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil... (diff)
downloadkernel-qcow2-linux-0fc31966035d7a540c011b6c967ce8eae1db121b.tar.gz
kernel-qcow2-linux-0fc31966035d7a540c011b6c967ce8eae1db121b.tar.xz
kernel-qcow2-linux-0fc31966035d7a540c011b6c967ce8eae1db121b.zip
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== Please pull this batch of wireless updates intended for 3.15! For the mac80211 bits, Johannes says: "This has a whole bunch of bugfixes for things that went into -next previously as well as some other bugfixes I didn't want to rush into 3.14 at this point. The rest of it is some cleanups and a few small features, the biggest of which is probably Janusz's regulatory DFS CAC time code." For the Bluetooth bits, Gustavo says: "One more pull request to 3.15. This is mostly and bug fix pull request, it contains several fixes and clean up all over the tree, plus some small new features." For the NFC bits, Samuel says: "This is the NFC pull request for 3.15. With this one we have: - Support for ISO 15693 a.k.a. NFC vicinity a.k.a. Type 5 tags. ISO 15693 are long range (1 - 2 meters) vicinity tags/cards. The kernel now supports those through the NFC netlink and digital APIs. - Support for TI's trf7970a chipset. This chipset relies on the NFC digital layer and the driver currently supports type 2, 4A and 5 tags. - Support for NXP's pn544 secure firmare download. The pn544 C3 chipsets relies on a different firmware download protocal than the C2 one. We now support both and use the right one depending on the version we detect at runtime. - Support for 4A tags from the NFC digital layer. - A bunch of cleanups and minor fixes from Axel Lin and Thierry Escande." For the iwlwifi bits, Emmanuel says: "We were sending a host command while the mutex wasn't held. This led to hard-to-catch races." And... "I have a fix for a "merge damage" which is not really a merge damage: it enables scheduled scan which has been disabled in wireless.git. Since you merged wireless.git into wireless-next.git, this can now be fixed in wireless-next.git. Besides this, Alex made a workaround for a hardware bug. This fix allows us to consume less power in S3. Arik and Eliad continue to work on D0i3 which is a run-time power saving feature. Eliad also contributes a few bits to the rate scaling logic to which Eyal adds his own contribution. Avri dives deep in the power code - newer firmware will allow to enable power save in newer scenarios. Johannes made a few clean-ups. I have the regular amount of BT Coex boring stuff. I disable uAPSD since we identified firmware bugs that cause packet loss. One thing that do stand out is the udev event that we now send when the FW asserts. I hope it will allow us to debug the FW more easily." Also included is one last iwlwifi pull for a build breakage fix... For the Atheros bits, Kalle says: "Michal now did some optimisations and was able to improve throughput by 100 Mbps on our MIPS based AP135 platform. Chun-Yeow added some workarounds to be able to better use ad-hoc mode. Ben improved log messages and added support for MSDU chaining. And, as usual, also some smaller fixes." Beyond that... Andrea Merello continues his rtl8180 refactoring, in preparation for a long-awaited rtl8187 driver. We get a new driver (rsi) for the RS9113 chip, from Fariya Fatima. And, of course, we get the usual round of updates for ath9k, brcmfmac, mwifiex, wil6210, etc. as well. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/6lowpan.h21
-rw-r--r--net/bluetooth/Kconfig8
-rw-r--r--net/bluetooth/Makefile3
-rw-r--r--net/bluetooth/a2mp.c12
-rw-r--r--net/bluetooth/hci_conn.c37
-rw-r--r--net/bluetooth/hci_core.c14
-rw-r--r--net/bluetooth/hci_event.c27
-rw-r--r--net/bluetooth/hci_sock.c16
-rw-r--r--net/bluetooth/l2cap_core.c90
-rw-r--r--net/bluetooth/l2cap_sock.c6
-rw-r--r--net/bluetooth/mgmt.c83
-rw-r--r--net/bluetooth/rfcomm/core.c4
-rw-r--r--net/bluetooth/sco.c10
-rw-r--r--net/bluetooth/smp.c208
-rw-r--r--net/bluetooth/smp.h4
-rw-r--r--net/mac80211/cfg.c121
-rw-r--r--net/mac80211/ibss.c12
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c70
-rw-r--r--net/mac80211/pm.c14
-rw-r--r--net/mac80211/rx.c3
-rw-r--r--net/mac80211/scan.c6
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/nfc/core.c10
-rw-r--r--net/nfc/digital.h6
-rw-r--r--net/nfc/digital_core.c67
-rw-r--r--net/nfc/digital_technology.c247
-rw-r--r--net/nfc/hci/llc.c4
-rw-r--r--net/nfc/llcp_core.c16
-rw-r--r--net/nfc/nci/core.c3
-rw-r--r--net/nfc/nci/spi.c3
-rw-r--r--net/nfc/netlink.c8
-rw-r--r--net/wireless/ap.c9
-rw-r--r--net/wireless/chan.c56
-rw-r--r--net/wireless/core.c2
-rw-r--r--net/wireless/core.h10
-rw-r--r--net/wireless/genregdb.awk8
-rw-r--r--net/wireless/ibss.c8
-rw-r--r--net/wireless/mlme.c2
-rw-r--r--net/wireless/nl80211.c24
-rw-r--r--net/wireless/reg.c86
-rw-r--r--net/wireless/reg.h1
-rw-r--r--net/wireless/scan.c31
-rw-r--r--net/wireless/sme.c1
-rw-r--r--net/wireless/util.c5
-rw-r--r--net/wireless/wext-sme.c2
46 files changed, 989 insertions, 392 deletions
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
index 680eac808d74..5d281f1eaf55 100644
--- a/net/bluetooth/6lowpan.h
+++ b/net/bluetooth/6lowpan.h
@@ -14,13 +14,34 @@
#ifndef __6LOWPAN_H
#define __6LOWPAN_H
+#include <linux/errno.h>
#include <linux/skbuff.h>
#include <net/bluetooth/l2cap.h>
+#if IS_ENABLED(CONFIG_BT_6LOWPAN)
int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
int bt_6lowpan_add_conn(struct l2cap_conn *conn);
int bt_6lowpan_del_conn(struct l2cap_conn *conn);
int bt_6lowpan_init(void);
void bt_6lowpan_cleanup(void);
+#else
+static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ return -EOPNOTSUPP;
+}
+static int bt_6lowpan_add_conn(struct l2cap_conn *conn)
+{
+ return -EOPNOTSUPP;
+}
+int bt_6lowpan_del_conn(struct l2cap_conn *conn)
+{
+ return -EOPNOTSUPP;
+}
+static int bt_6lowpan_init(void)
+{
+ return -EOPNOTSUPP;
+}
+static void bt_6lowpan_cleanup(void) { }
+#endif
#endif /* __6LOWPAN_H */
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 985b56070d26..06ec14499ca1 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -6,13 +6,13 @@ menuconfig BT
tristate "Bluetooth subsystem support"
depends on NET && !S390
depends on RFKILL || !RFKILL
+ select 6LOWPAN_IPHC if BT_6LOWPAN
select CRC16
select CRYPTO
select CRYPTO_BLKCIPHER
select CRYPTO_AES
select CRYPTO_ECB
select CRYPTO_SHA256
- select 6LOWPAN_IPHC
help
Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range
@@ -40,6 +40,12 @@ menuconfig BT
to Bluetooth kernel modules are provided in the BlueZ packages. For
more information, see <http://www.bluez.org/>.
+config BT_6LOWPAN
+ bool "Bluetooth 6LoWPAN support"
+ depends on BT && IPV6
+ help
+ IPv6 compression over Bluetooth.
+
source "net/bluetooth/rfcomm/Kconfig"
source "net/bluetooth/bnep/Kconfig"
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index 80cb215826e8..ca51246b1016 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
- a2mp.o amp.o 6lowpan.o
+ a2mp.o amp.o
+bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o
subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index f986b9968bdb..9514cc9e850c 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -162,7 +162,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
return -ENOMEM;
}
- rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+ rsp->mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
rsp->ext_feat = 0;
__a2mp_add_cl(mgr, rsp->cl);
@@ -649,7 +649,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
if (err) {
struct a2mp_cmd_rej rej;
- rej.reason = __constant_cpu_to_le16(0);
+ rej.reason = cpu_to_le16(0);
hdr = (void *) skb->data;
BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
@@ -695,7 +695,13 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
unsigned long len, int nb)
{
- return bt_skb_alloc(len, GFP_KERNEL);
+ struct sk_buff *skb;
+
+ skb = bt_skb_alloc(len, GFP_KERNEL);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ return skb;
}
static struct l2cap_ops a2mp_chan_ops = {
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7c713c4675ba..d958e2dca52f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -82,7 +82,7 @@ static void hci_acl_create_connection(struct hci_conn *conn)
cp.pscan_rep_mode = ie->data.pscan_rep_mode;
cp.pscan_mode = ie->data.pscan_mode;
cp.clock_offset = ie->data.clock_offset |
- __constant_cpu_to_le16(0x8000);
+ cpu_to_le16(0x8000);
}
memcpy(conn->dev_class, ie->data.dev_class, 3);
@@ -182,8 +182,8 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
cp.handle = cpu_to_le16(handle);
- cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
- cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.tx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = cpu_to_le32(0x00001f40);
cp.voice_setting = cpu_to_le16(conn->setting);
switch (conn->setting & SCO_AIRMODE_MASK) {
@@ -225,8 +225,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
cp.conn_interval_max = cpu_to_le16(max);
cp.conn_latency = cpu_to_le16(latency);
cp.supervision_timeout = cpu_to_le16(to_multiplier);
- cp.min_ce_len = __constant_cpu_to_le16(0x0000);
- cp.max_ce_len = __constant_cpu_to_le16(0x0000);
+ cp.min_ce_len = cpu_to_le16(0x0000);
+ cp.max_ce_len = cpu_to_le16(0x0000);
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
}
@@ -337,9 +337,9 @@ static void hci_conn_idle(struct work_struct *work)
if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
struct hci_cp_sniff_subrate cp;
cp.handle = cpu_to_le16(conn->handle);
- cp.max_latency = __constant_cpu_to_le16(0);
- cp.min_remote_timeout = __constant_cpu_to_le16(0);
- cp.min_local_timeout = __constant_cpu_to_le16(0);
+ cp.max_latency = cpu_to_le16(0);
+ cp.min_remote_timeout = cpu_to_le16(0);
+ cp.min_local_timeout = cpu_to_le16(0);
hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
}
@@ -348,8 +348,8 @@ static void hci_conn_idle(struct work_struct *work)
cp.handle = cpu_to_le16(conn->handle);
cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
- cp.attempt = __constant_cpu_to_le16(4);
- cp.timeout = __constant_cpu_to_le16(1);
+ cp.attempt = cpu_to_le16(4);
+ cp.timeout = cpu_to_le16(1);
hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
}
}
@@ -596,9 +596,9 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
cp.own_address_type = own_addr_type;
cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
- cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
- cp.min_ce_len = __constant_cpu_to_le16(0x0000);
- cp.max_ce_len = __constant_cpu_to_le16(0x0000);
+ cp.supervision_timeout = cpu_to_le16(0x002a);
+ cp.min_ce_len = cpu_to_le16(0x0000);
+ cp.max_ce_len = cpu_to_le16(0x0000);
hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
@@ -781,6 +781,17 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
{
BT_DBG("hcon %p", conn);
+ /* In Secure Connections Only mode, it is required that Secure
+ * Connections is used and the link is encrypted with AES-CCM
+ * using a P-256 authenticated combination key.
+ */
+ if (test_bit(HCI_SC_ONLY, &conn->hdev->flags)) {
+ if (!hci_conn_sc_enabled(conn) ||
+ !test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
+ conn->key_type != HCI_LK_AUTH_COMBINATION_P256)
+ return 0;
+ }
+
if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT))
return 0;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 8bbfdea9cbec..1c6ffaa8902f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1349,7 +1349,7 @@ static void bredr_setup(struct hci_request *req)
hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
/* Connection accept timeout ~20 secs */
- param = __constant_cpu_to_le16(0x7d00);
+ param = cpu_to_le16(0x7d00);
hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
/* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2,
@@ -5270,7 +5270,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
memset(&enable_cp, 0, sizeof(enable_cp));
enable_cp.enable = LE_SCAN_ENABLE;
- enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+ enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
&enable_cp);
}
@@ -5313,10 +5313,6 @@ void hci_update_background_scan(struct hci_dev *hdev)
* keep the background scan running.
*/
- /* If controller is already scanning we are done. */
- if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
- return;
-
/* If controller is connecting, we should not start scanning
* since some controllers are not able to scan and connect at
* the same time.
@@ -5325,6 +5321,12 @@ void hci_update_background_scan(struct hci_dev *hdev)
if (conn)
return;
+ /* If controller is currently scanning, we stop it to ensure we
+ * don't miss any advertising (due to duplicates filter).
+ */
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ hci_req_add_le_scan_disable(&req);
+
hci_req_add_le_passive_scan(&req);
BT_DBG("%s starting background scanning", hdev->name);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c3b0a08f5ab4..a6a3d32553c5 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1924,9 +1924,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
bacpy(&cp.bdaddr, &ev->bdaddr);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
- cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
- cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
- cp.max_latency = __constant_cpu_to_le16(0xffff);
+ cp.tx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.max_latency = cpu_to_le16(0xffff);
cp.content_format = cpu_to_le16(hdev->voice_setting);
cp.retrans_effort = 0xff;
@@ -2183,6 +2183,18 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (!ev->status)
conn->state = BT_CONNECTED;
+ /* In Secure Connections Only mode, do not allow any
+ * connections that are not encrypted with AES-CCM
+ * using a P-256 authenticated combination key.
+ */
+ if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) &&
+ (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
+ conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
+ hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
+ hci_conn_drop(conn);
+ goto unlock;
+ }
+
hci_proto_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
} else
@@ -3157,6 +3169,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
case 0x1c: /* SCO interval rejected */
case 0x1a: /* Unsupported Remote Feature */
case 0x1f: /* Unspecified error */
+ case 0x20: /* Unsupported LMP Parameter value */
if (conn->out) {
conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);
@@ -3961,7 +3974,13 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
- if (ltk->type & HCI_SMP_STK) {
+ /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
+ * temporary key used to encrypt a connection following
+ * pairing. It is used during the Encrypted Session Setup to
+ * distribute the keys. Later, security can be re-established
+ * using a distributed LTK.
+ */
+ if (ltk->type == HCI_SMP_STK_SLAVE) {
list_del(&ltk->list);
kfree(ltk);
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 68e51a84e72d..b9a418e578e0 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -211,22 +211,22 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
- opcode = __constant_cpu_to_le16(HCI_MON_COMMAND_PKT);
+ opcode = cpu_to_le16(HCI_MON_COMMAND_PKT);
break;
case HCI_EVENT_PKT:
- opcode = __constant_cpu_to_le16(HCI_MON_EVENT_PKT);
+ opcode = cpu_to_le16(HCI_MON_EVENT_PKT);
break;
case HCI_ACLDATA_PKT:
if (bt_cb(skb)->incoming)
- opcode = __constant_cpu_to_le16(HCI_MON_ACL_RX_PKT);
+ opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT);
else
- opcode = __constant_cpu_to_le16(HCI_MON_ACL_TX_PKT);
+ opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT);
break;
case HCI_SCODATA_PKT:
if (bt_cb(skb)->incoming)
- opcode = __constant_cpu_to_le16(HCI_MON_SCO_RX_PKT);
+ opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT);
else
- opcode = __constant_cpu_to_le16(HCI_MON_SCO_TX_PKT);
+ opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT);
break;
default:
return;
@@ -319,7 +319,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
bacpy(&ni->bdaddr, &hdev->bdaddr);
memcpy(ni->name, hdev->name, 8);
- opcode = __constant_cpu_to_le16(HCI_MON_NEW_INDEX);
+ opcode = cpu_to_le16(HCI_MON_NEW_INDEX);
break;
case HCI_DEV_UNREG:
@@ -327,7 +327,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
if (!skb)
return NULL;
- opcode = __constant_cpu_to_le16(HCI_MON_DEL_INDEX);
+ opcode = cpu_to_le16(HCI_MON_DEL_INDEX);
break;
default:
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9ed2168fa59f..a1e5bb7d06e8 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -665,7 +665,7 @@ static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(result);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
}
@@ -727,7 +727,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
}
break;
case L2CAP_CHAN_CONN_LESS:
- if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
+ if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
if (chan->sec_level == BT_SECURITY_LOW)
chan->sec_level = BT_SECURITY_SDP;
}
@@ -738,7 +738,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
return HCI_AT_NO_BONDING;
break;
case L2CAP_CHAN_CONN_ORIENTED:
- if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
+ if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
if (chan->sec_level == BT_SECURITY_LOW)
chan->sec_level = BT_SECURITY_SDP;
@@ -1273,7 +1273,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
}
} else {
struct l2cap_info_req req;
- req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
conn->info_ident = l2cap_get_ident(conn);
@@ -1370,18 +1370,18 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
if (l2cap_chan_check_security(chan)) {
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
+ rsp.result = cpu_to_le16(L2CAP_CR_PEND);
+ rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
chan->ops->defer(chan);
} else {
l2cap_state_change(chan, BT_CONFIG);
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
}
} else {
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
+ rsp.result = cpu_to_le16(L2CAP_CR_PEND);
+ rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
}
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
@@ -2895,9 +2895,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
if (conn->hcon->type == LE_LINK)
- lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
+ lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
else
- lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
+ lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
cmd->code = code;
@@ -3010,8 +3010,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
efs.stype = chan->local_stype;
efs.msdu = cpu_to_le16(chan->local_msdu);
efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
- efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
- efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
+ efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
+ efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
break;
case L2CAP_MODE_STREAMING:
@@ -3152,8 +3152,8 @@ static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
rfc->monitor_timeout = rfc->retrans_timeout;
} else {
- rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
}
}
@@ -3285,7 +3285,7 @@ done:
}
req->dcid = cpu_to_le16(chan->dcid);
- req->flags = __constant_cpu_to_le16(0);
+ req->flags = cpu_to_le16(0);
return ptr - data;
}
@@ -3499,7 +3499,7 @@ done:
}
rsp->scid = cpu_to_le16(chan->dcid);
rsp->result = cpu_to_le16(result);
- rsp->flags = __constant_cpu_to_le16(0);
+ rsp->flags = cpu_to_le16(0);
return ptr - data;
}
@@ -3608,7 +3608,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
}
req->dcid = cpu_to_le16(chan->dcid);
- req->flags = __constant_cpu_to_le16(0);
+ req->flags = cpu_to_le16(0);
return ptr - data;
}
@@ -3639,7 +3639,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
rsp.mtu = cpu_to_le16(chan->imtu);
rsp.mps = cpu_to_le16(chan->mps);
rsp.credits = cpu_to_le16(chan->rx_credits);
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
&rsp);
@@ -3654,8 +3654,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
if (chan->hs_hcon)
rsp_code = L2CAP_CREATE_CHAN_RSP;
@@ -3684,8 +3684,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
u16 txwin_ext = chan->ack_win;
struct l2cap_conf_rfc rfc = {
.mode = chan->mode,
- .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
- .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
+ .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
+ .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
.max_pdu_size = cpu_to_le16(chan->imtu),
.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
};
@@ -3776,7 +3776,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
l2cap_chan_lock(pchan);
/* Check if the ACL is secure enough (if not SDP) */
- if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
+ if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
!hci_conn_check_link_mode(conn->hcon)) {
conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
result = L2CAP_CR_SEC_BLOCK;
@@ -3861,7 +3861,7 @@ sendresp:
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
struct l2cap_info_req info;
- info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
conn->info_ident = l2cap_get_ident(conn);
@@ -4010,7 +4010,7 @@ static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
{
struct l2cap_cmd_rej_cid rej;
- rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
+ rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
rej.scid = __cpu_to_le16(scid);
rej.dcid = __cpu_to_le16(dcid);
@@ -4342,8 +4342,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
u8 buf[8];
u32 feat_mask = l2cap_feat_mask;
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
- rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
- rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
+ rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
if (!disable_ertm)
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
| L2CAP_FEAT_FCS;
@@ -4363,15 +4363,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
else
l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
- rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
- rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
+ rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
+ rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
buf);
} else {
struct l2cap_info_rsp rsp;
rsp.type = cpu_to_le16(type);
- rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
+ rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
&rsp);
}
@@ -4416,7 +4416,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
struct l2cap_info_req req;
- req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
+ req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
conn->info_ident = l2cap_get_ident(conn);
@@ -4510,8 +4510,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
error:
rsp.dcid = 0;
rsp.scid = cpu_to_le16(scid);
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
sizeof(rsp), &rsp);
@@ -4575,7 +4575,7 @@ static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
cfm.icid = cpu_to_le16(icid);
- cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
+ cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
sizeof(cfm), &cfm);
@@ -4758,12 +4758,12 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
if (result == L2CAP_CR_SUCCESS) {
/* Send successful response */
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
} else {
/* Send negative response */
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
- rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
}
l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
@@ -4891,7 +4891,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
chan = l2cap_get_chan_by_dcid(conn, icid);
if (!chan) {
rsp.icid = cpu_to_le16(icid);
- rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
+ rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
sizeof(rsp), &rsp);
return 0;
@@ -5235,9 +5235,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
err = l2cap_check_conn_param(min, max, latency, to_multiplier);
if (err)
- rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
+ rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
else
- rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+ rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
sizeof(rsp), &rsp);
@@ -5650,7 +5650,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err);
- rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+ rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
}
@@ -5695,7 +5695,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err);
- rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+ rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b247f9d27fed..33cd5615ff1e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -111,7 +111,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
/* We only allow ATT user space socket */
if (la.l2_cid &&
- la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+ la.l2_cid != cpu_to_le16(L2CAP_CID_ATT))
return -EINVAL;
}
@@ -209,7 +209,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
* ATT. Anything else is an invalid combination.
*/
if (chan->scid != L2CAP_CID_ATT ||
- la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+ la.l2_cid != cpu_to_le16(L2CAP_CID_ATT))
return -EINVAL;
/* We don't have the hdev available here to make a
@@ -227,7 +227,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
/* We only allow ATT user space socket */
if (la.l2_cid &&
- la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+ la.l2_cid != cpu_to_le16(L2CAP_CID_ATT))
return -EINVAL;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 98e9df3556e7..96670f581bb0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -108,6 +108,7 @@ static const u16 mgmt_events[] = {
MGMT_EV_DEVICE_UNPAIRED,
MGMT_EV_PASSKEY_NOTIFY,
MGMT_EV_NEW_IRK,
+ MGMT_EV_NEW_CSRK,
};
#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
@@ -212,7 +213,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
hdr = (void *) skb_put(skb, sizeof(*hdr));
- hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS);
+ hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(sizeof(*ev));
@@ -243,7 +244,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
hdr = (void *) skb_put(skb, sizeof(*hdr));
- hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE);
+ hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
@@ -269,7 +270,7 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("sock %p", sk);
rp.version = MGMT_VERSION;
- rp.revision = __constant_cpu_to_le16(MGMT_REVISION);
+ rp.revision = cpu_to_le16(MGMT_REVISION);
return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
sizeof(rp));
@@ -293,8 +294,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
if (!rp)
return -ENOMEM;
- rp->num_commands = __constant_cpu_to_le16(num_commands);
- rp->num_events = __constant_cpu_to_le16(num_events);
+ rp->num_commands = cpu_to_le16(num_commands);
+ rp->num_events = cpu_to_le16(num_events);
for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
put_unaligned_le16(mgmt_commands[i], opcode);
@@ -857,8 +858,8 @@ static void enable_advertising(struct hci_request *req)
return;
memset(&cp, 0, sizeof(cp));
- cp.min_interval = __constant_cpu_to_le16(0x0800);
- cp.max_interval = __constant_cpu_to_le16(0x0800);
+ cp.min_interval = cpu_to_le16(0x0800);
+ cp.max_interval = cpu_to_le16(0x0800);
cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
cp.own_address_type = own_addr_type;
cp.channel_map = hdev->le_adv_channel_map;
@@ -1180,7 +1181,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
if (hdev)
hdr->index = cpu_to_le16(hdev->id);
else
- hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
+ hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
hdr->len = cpu_to_le16(data_len);
if (data)
@@ -1492,15 +1493,15 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
type = PAGE_SCAN_TYPE_INTERLACED;
/* 160 msec page scan interval */
- acp.interval = __constant_cpu_to_le16(0x0100);
+ acp.interval = cpu_to_le16(0x0100);
} else {
type = PAGE_SCAN_TYPE_STANDARD; /* default */
/* default 1.28 sec page scan */
- acp.interval = __constant_cpu_to_le16(0x0800);
+ acp.interval = cpu_to_le16(0x0800);
}
- acp.window = __constant_cpu_to_le16(0x0012);
+ acp.window = cpu_to_le16(0x0012);
if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
__cpu_to_le16(hdev->page_scan_window) != acp.window)
@@ -2351,7 +2352,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
sizeof(struct mgmt_link_key_info);
if (expected_len != len) {
BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
- len, expected_len);
+ expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
@@ -2761,11 +2762,23 @@ static struct pending_cmd *find_pairing(struct hci_conn *conn)
static void pairing_complete(struct pending_cmd *cmd, u8 status)
{
+ const struct mgmt_cp_pair_device *cp = cmd->param;
struct mgmt_rp_pair_device rp;
struct hci_conn *conn = cmd->user_data;
- bacpy(&rp.addr.bdaddr, &conn->dst);
- rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+ /* If we had a pairing failure we might have already received
+ * the remote Identity Address Information and updated the
+ * hci_conn variables with it, however we would not yet have
+ * notified user space of the resolved identity. Therefore, use
+ * the address given in the Pair Device command in case the
+ * pairing failed.
+ */
+ if (status) {
+ memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
+ } else {
+ bacpy(&rp.addr.bdaddr, &conn->dst);
+ rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+ }
cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
&rp, sizeof(rp));
@@ -4427,7 +4440,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
if (expected_len != len) {
BT_ERR("load_irks: expected %u bytes, got %u bytes",
- len, expected_len);
+ expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS);
}
@@ -4507,7 +4520,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
sizeof(struct mgmt_ltk_info);
if (expected_len != len) {
BT_ERR("load_keys: expected %u bytes, got %u bytes",
- len, expected_len);
+ expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
@@ -5004,7 +5017,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
}
-void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
+void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
{
struct mgmt_ev_new_long_term_key ev;
@@ -5025,7 +5038,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
(key->bdaddr.b[5] & 0xc0) != 0xc0)
ev.store_hint = 0x00;
else
- ev.store_hint = 0x01;
+ ev.store_hint = persistent;
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
@@ -5072,6 +5085,36 @@ void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
}
+void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
+ bool persistent)
+{
+ struct mgmt_ev_new_csrk ev;
+
+ memset(&ev, 0, sizeof(ev));
+
+ /* Devices using resolvable or non-resolvable random addresses
+ * without providing an indentity resolving key don't require
+ * to store signature resolving keys. Their addresses will change
+ * the next time around.
+ *
+ * Only when a remote device provides an identity address
+ * make sure the signature resolving key is stored. So allow
+ * static random and public addresses here.
+ */
+ if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
+ (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
+ ev.store_hint = 0x00;
+ else
+ ev.store_hint = persistent;
+
+ bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
+ ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
+ ev.key.master = csrk->master;
+ memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
+
+ mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
+}
+
static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
u8 data_len)
{
@@ -5665,9 +5708,9 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
ev->rssi = rssi;
if (cfm_name)
- ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
+ ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
if (!ssp)
- ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
+ ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
if (eir_len > 0)
memcpy(ev->eir, eir, eir_len);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 21e15318937c..633cceeb943e 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -768,7 +768,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
bacpy(&addr.l2_bdaddr, dst);
addr.l2_family = AF_BLUETOOTH;
- addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
+ addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0;
addr.l2_bdaddr_type = BDADDR_BREDR;
*err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
@@ -2032,7 +2032,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Bind socket */
bacpy(&addr.l2_bdaddr, ba);
addr.l2_family = AF_BLUETOOTH;
- addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
+ addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0;
addr.l2_bdaddr_type = BDADDR_BREDR;
err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 24fa3964b3c8..ab1e6fcca4c5 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -676,20 +676,20 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting)
bacpy(&cp.bdaddr, &conn->dst);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
- cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
- cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.tx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = cpu_to_le32(0x00001f40);
cp.content_format = cpu_to_le16(setting);
switch (setting & SCO_AIRMODE_MASK) {
case SCO_AIRMODE_TRANSP:
if (conn->pkt_type & ESCO_2EV3)
- cp.max_latency = __constant_cpu_to_le16(0x0008);
+ cp.max_latency = cpu_to_le16(0x0008);
else
- cp.max_latency = __constant_cpu_to_le16(0x000D);
+ cp.max_latency = cpu_to_le16(0x000D);
cp.retrans_effort = 0x02;
break;
case SCO_AIRMODE_CVSD:
- cp.max_latency = __constant_cpu_to_le16(0xffff);
+ cp.max_latency = cpu_to_le16(0xffff);
cp.retrans_effort = 0xff;
break;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index f886bcae1b7e..2a7ee7f6cd8b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -35,14 +35,14 @@
#define AUTH_REQ_MASK 0x07
-static inline void swap128(u8 src[16], u8 dst[16])
+static inline void swap128(const u8 src[16], u8 dst[16])
{
int i;
for (i = 0; i < 16; i++)
dst[15 - i] = src[i];
}
-static inline void swap56(u8 src[7], u8 dst[7])
+static inline void swap56(const u8 src[7], u8 dst[7])
{
int i;
for (i = 0; i < 7; i++)
@@ -53,6 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
{
struct blkcipher_desc desc;
struct scatterlist sg;
+ uint8_t tmp[16], data[16];
int err;
if (tfm == NULL) {
@@ -63,34 +64,40 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
desc.tfm = tfm;
desc.flags = 0;
- err = crypto_blkcipher_setkey(tfm, k, 16);
+ /* The most significant octet of key corresponds to k[0] */
+ swap128(k, tmp);
+
+ err = crypto_blkcipher_setkey(tfm, tmp, 16);
if (err) {
BT_ERR("cipher setkey failed: %d", err);
return err;
}
- sg_init_one(&sg, r, 16);
+ /* Most significant octet of plaintextData corresponds to data[0] */
+ swap128(r, data);
+
+ sg_init_one(&sg, data, 16);
err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
if (err)
BT_ERR("Encrypt data error %d", err);
+ /* Most significant octet of encryptedData corresponds to data[0] */
+ swap128(data, r);
+
return err;
}
static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
{
- u8 _res[16], k[16];
+ u8 _res[16];
int err;
/* r' = padding || r */
- memset(_res, 0, 13);
- _res[13] = r[2];
- _res[14] = r[1];
- _res[15] = r[0];
+ memcpy(_res, r, 3);
+ memset(_res + 3, 0, 13);
- swap128(irk, k);
- err = smp_e(tfm, k, _res);
+ err = smp_e(tfm, irk, _res);
if (err) {
BT_ERR("Encrypt error");
return err;
@@ -102,9 +109,7 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
* by taking the least significant 24 bits of the output of e as the
* result of ah.
*/
- res[0] = _res[15];
- res[1] = _res[14];
- res[2] = _res[13];
+ memcpy(res, _res, 3);
return 0;
}
@@ -152,16 +157,15 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
memset(p1, 0, 16);
/* p1 = pres || preq || _rat || _iat */
- swap56(pres, p1);
- swap56(preq, p1 + 7);
- p1[14] = _rat;
- p1[15] = _iat;
-
- memset(p2, 0, 16);
+ p1[0] = _iat;
+ p1[1] = _rat;
+ memcpy(p1 + 2, preq, 7);
+ memcpy(p1 + 9, pres, 7);
/* p2 = padding || ia || ra */
- baswap((bdaddr_t *) (p2 + 4), ia);
- baswap((bdaddr_t *) (p2 + 10), ra);
+ memcpy(p2, ra, 6);
+ memcpy(p2 + 6, ia, 6);
+ memset(p2 + 12, 0, 4);
/* res = r XOR p1 */
u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
@@ -190,8 +194,8 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
int err;
/* Just least significant octets from r1 and r2 are considered */
- memcpy(_r, r1 + 8, 8);
- memcpy(_r + 8, r2 + 8, 8);
+ memcpy(_r, r2, 8);
+ memcpy(_r + 8, r1, 8);
err = smp_e(tfm, k, _r);
if (err)
@@ -218,7 +222,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->len = cpu_to_le16(sizeof(code) + dlen);
- lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
+ lh->cid = cpu_to_le16(L2CAP_CID_SMP);
memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
@@ -273,8 +277,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
u8 local_dist = 0, remote_dist = 0;
if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
- local_dist = SMP_DIST_ENC_KEY;
- remote_dist = SMP_DIST_ENC_KEY;
+ local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
+ remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
authreq |= SMP_AUTH_BONDING;
} else {
authreq &= ~SMP_AUTH_BONDING;
@@ -403,16 +407,14 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
method = REQ_PASSKEY;
}
- /* Generate random passkey. Not valid until confirmed. */
+ /* Generate random passkey. */
if (method == CFM_PASSKEY) {
- u8 key[16];
-
- memset(key, 0, sizeof(key));
+ memset(smp->tk, 0, sizeof(smp->tk));
get_random_bytes(&passkey, sizeof(passkey));
passkey %= 1000000;
- put_unaligned_le32(passkey, key);
- swap128(key, smp->tk);
+ put_unaligned_le32(passkey, smp->tk);
BT_DBG("PassKey: %d", passkey);
+ set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
}
hci_dev_lock(hcon->hdev);
@@ -421,7 +423,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type);
else
- ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
+ ret = mgmt_user_passkey_notify(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type,
cpu_to_le32(passkey), 0);
@@ -438,7 +440,7 @@ static void confirm_work(struct work_struct *work)
struct crypto_blkcipher *tfm = hdev->tfm_aes;
struct smp_cmd_pairing_confirm cp;
int ret;
- u8 res[16], reason;
+ u8 reason;
BT_DBG("conn %p", conn);
@@ -447,7 +449,8 @@ static void confirm_work(struct work_struct *work)
ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
conn->hcon->init_addr_type, &conn->hcon->init_addr,
- conn->hcon->resp_addr_type, &conn->hcon->resp_addr, res);
+ conn->hcon->resp_addr_type, &conn->hcon->resp_addr,
+ cp.confirm_val);
hci_dev_unlock(hdev);
@@ -458,7 +461,6 @@ static void confirm_work(struct work_struct *work)
clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
- swap128(res, cp.confirm_val);
smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
return;
@@ -474,7 +476,7 @@ static void random_work(struct work_struct *work)
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
struct crypto_blkcipher *tfm = hdev->tfm_aes;
- u8 reason, confirm[16], res[16], key[16];
+ u8 reason, confirm[16];
int ret;
if (IS_ERR_OR_NULL(tfm)) {
@@ -489,7 +491,7 @@ static void random_work(struct work_struct *work)
ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
hcon->init_addr_type, &hcon->init_addr,
- hcon->resp_addr_type, &hcon->resp_addr, res);
+ hcon->resp_addr_type, &hcon->resp_addr, confirm);
hci_dev_unlock(hdev);
@@ -498,8 +500,6 @@ static void random_work(struct work_struct *work)
goto error;
}
- swap128(res, confirm);
-
if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
BT_ERR("Pairing failed (confirmation values mismatch)");
reason = SMP_CONFIRM_FAILED;
@@ -511,8 +511,7 @@ static void random_work(struct work_struct *work)
__le64 rand = 0;
__le16 ediv = 0;
- smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
- swap128(key, stk);
+ smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, stk);
memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
@@ -525,15 +524,14 @@ static void random_work(struct work_struct *work)
hci_le_start_enc(hcon, ediv, rand, stk);
hcon->enc_key_size = smp->enc_key_size;
} else {
- u8 stk[16], r[16];
+ u8 stk[16];
__le64 rand = 0;
__le16 ediv = 0;
- swap128(smp->prnd, r);
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
+ smp->prnd);
- smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
- swap128(key, stk);
+ smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, stk);
memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
@@ -596,6 +594,9 @@ void smp_chan_destroy(struct l2cap_conn *conn)
complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
mgmt_smp_complete(conn->hcon, complete);
+ kfree(smp->csrk);
+ kfree(smp->slave_csrk);
+
/* If pairing failed clean up any keys we might have */
if (!complete) {
if (smp->ltk) {
@@ -625,7 +626,6 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
struct l2cap_conn *conn = hcon->smp_conn;
struct smp_chan *smp;
u32 value;
- u8 key[16];
BT_DBG("");
@@ -637,10 +637,9 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
switch (mgmt_op) {
case MGMT_OP_USER_PASSKEY_REPLY:
value = le32_to_cpu(passkey);
- memset(key, 0, sizeof(key));
+ memset(smp->tk, 0, sizeof(smp->tk));
BT_DBG("PassKey: %d", value);
- put_unaligned_le32(value, key);
- swap128(key, smp->tk);
+ put_unaligned_le32(value, smp->tk);
/* Fall Through */
case MGMT_OP_USER_CONFIRM_REPLY:
set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
@@ -745,6 +744,11 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
smp->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
+ /* Update remote key distribution in case the remote cleared
+ * some bits that we had enabled in our request.
+ */
+ smp->remote_key_dist &= rsp->resp_key_dist;
+
if ((req->auth_req & SMP_AUTH_BONDING) &&
(rsp->auth_req & SMP_AUTH_BONDING))
auth = SMP_AUTH_BONDING;
@@ -758,10 +762,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
/* Can't compose response until we have been confirmed */
- if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
- return 0;
-
- queue_work(hdev->workqueue, &smp->confirm);
+ if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
+ queue_work(hdev->workqueue, &smp->confirm);
return 0;
}
@@ -779,17 +781,13 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
skb_pull(skb, sizeof(smp->pcnf));
- if (conn->hcon->out) {
- u8 random[16];
-
- swap128(smp->prnd, random);
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
- random);
- } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
+ if (conn->hcon->out)
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
+ smp->prnd);
+ else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
queue_work(hdev->workqueue, &smp->confirm);
- } else {
+ else
set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
- }
return 0;
}
@@ -804,7 +802,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(smp->rrnd))
return SMP_UNSPECIFIED;
- swap128(skb->data, smp->rrnd);
+ memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd));
skb_pull(skb, sizeof(smp->rrnd));
queue_work(hdev->workqueue, &smp->random);
@@ -910,6 +908,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
authreq = seclevel_to_authreq(sec_level);
+ /* hcon->auth_type is set by pair_device in mgmt.c. If the MITM
+ * flag is set we should also set it for the SMP request.
+ */
+ if ((hcon->auth_type & 0x01))
+ authreq |= SMP_AUTH_MITM;
+
if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;
@@ -1065,6 +1069,41 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
return 0;
}
+static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_sign_info *rp = (void *) skb->data;
+ struct smp_chan *smp = conn->smp_chan;
+ struct hci_dev *hdev = conn->hcon->hdev;
+ struct smp_csrk *csrk;
+
+ BT_DBG("conn %p", conn);
+
+ if (skb->len < sizeof(*rp))
+ return SMP_UNSPECIFIED;
+
+ /* Ignore this PDU if it wasn't requested */
+ if (!(smp->remote_key_dist & SMP_DIST_SIGN))
+ return 0;
+
+ /* Mark the information as received */
+ smp->remote_key_dist &= ~SMP_DIST_SIGN;
+
+ skb_pull(skb, sizeof(*rp));
+
+ hci_dev_lock(hdev);
+ csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
+ if (csrk) {
+ csrk->master = 0x01;
+ memcpy(csrk->val, rp->csrk, sizeof(csrk->val));
+ }
+ smp->csrk = csrk;
+ if (!(smp->remote_key_dist & SMP_DIST_SIGN))
+ smp_distribute_keys(conn);
+ hci_dev_unlock(hdev);
+
+ return 0;
+}
+
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct hci_conn *hcon = conn->hcon;
@@ -1147,8 +1186,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
break;
case SMP_CMD_SIGN_INFO:
- /* Just ignored */
- reason = 0;
+ reason = smp_cmd_sign_info(conn, skb);
break;
default:
@@ -1172,20 +1210,40 @@ static void smp_notify_keys(struct l2cap_conn *conn)
struct smp_chan *smp = conn->smp_chan;
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
+ struct smp_cmd_pairing *req = (void *) &smp->preq[1];
+ struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1];
+ bool persistent;
if (smp->remote_irk)
mgmt_new_irk(hdev, smp->remote_irk);
+ /* The LTKs and CSRKs should be persistent only if both sides
+ * had the bonding bit set in their authentication requests.
+ */
+ persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
+
+ if (smp->csrk) {
+ smp->csrk->bdaddr_type = hcon->dst_type;
+ bacpy(&smp->csrk->bdaddr, &hcon->dst);
+ mgmt_new_csrk(hdev, smp->csrk, persistent);
+ }
+
+ if (smp->slave_csrk) {
+ smp->slave_csrk->bdaddr_type = hcon->dst_type;
+ bacpy(&smp->slave_csrk->bdaddr, &hcon->dst);
+ mgmt_new_csrk(hdev, smp->slave_csrk, persistent);
+ }
+
if (smp->ltk) {
smp->ltk->bdaddr_type = hcon->dst_type;
bacpy(&smp->ltk->bdaddr, &hcon->dst);
- mgmt_new_ltk(hdev, smp->ltk);
+ mgmt_new_ltk(hdev, smp->ltk, persistent);
}
if (smp->slave_ltk) {
smp->slave_ltk->bdaddr_type = hcon->dst_type;
bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
- mgmt_new_ltk(hdev, smp->slave_ltk);
+ mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
}
}
@@ -1274,10 +1332,18 @@ int smp_distribute_keys(struct l2cap_conn *conn)
if (*keydist & SMP_DIST_SIGN) {
struct smp_cmd_sign_info sign;
+ struct smp_csrk *csrk;
- /* Send a dummy key */
+ /* Generate a new random key */
get_random_bytes(sign.csrk, sizeof(sign.csrk));
+ csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
+ if (csrk) {
+ csrk->master = 0x00;
+ memcpy(csrk->val, sign.csrk, sizeof(csrk->val));
+ }
+ smp->slave_csrk = csrk;
+
smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
*keydist &= ~SMP_DIST_SIGN;
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index f55d83617218..b6913471815a 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -121,7 +121,7 @@ struct smp_cmd_security_req {
#define SMP_FLAG_LTK_ENCRYPT 4
#define SMP_FLAG_COMPLETE 5
-#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(250)
+#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(500)
struct smp_chan {
struct l2cap_conn *conn;
@@ -136,6 +136,8 @@ struct smp_chan {
bdaddr_t id_addr;
u8 id_addr_type;
u8 irk[16];
+ struct smp_csrk *csrk;
+ struct smp_csrk *slave_csrk;
struct smp_ltk *ltk;
struct smp_ltk *slave_ltk;
struct smp_irk *remote_irk;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1acb29109b45..aaa59d719592 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
static int ieee80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- unsigned long timeout;
int err;
mutex_lock(&local->mtx);
@@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
if (err)
goto out_unlock;
- timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
ieee80211_queue_delayed_work(&sdata->local->hw,
- &sdata->dfs_cac_timer_work, timeout);
+ &sdata->dfs_cac_timer_work,
+ msecs_to_jiffies(cac_time_ms));
out_unlock:
mutex_unlock(&local->mtx);
@@ -3089,52 +3089,11 @@ unlock:
sdata_unlock(sdata);
}
-int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_csa_settings *params)
+static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *params,
+ u32 *changed)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_chanctx *chanctx;
- struct ieee80211_if_mesh __maybe_unused *ifmsh;
- int err, num_chanctx, changed = 0;
-
- sdata_assert_lock(sdata);
-
- if (!list_empty(&local->roc_list) || local->scanning)
- return -EBUSY;
-
- if (sdata->wdev.cac_started)
- return -EBUSY;
-
- if (cfg80211_chandef_identical(&params->chandef,
- &sdata->vif.bss_conf.chandef))
- return -EINVAL;
-
- rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- rcu_read_unlock();
- return -EBUSY;
- }
-
- /* don't handle for multi-VIF cases */
- chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
- if (chanctx->refcount > 1) {
- rcu_read_unlock();
- return -EBUSY;
- }
- num_chanctx = 0;
- list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
- num_chanctx++;
- rcu_read_unlock();
-
- if (num_chanctx > 1)
- return -EBUSY;
-
- /* don't allow another channel switch if one is already active. */
- if (sdata->vif.csa_active)
- return -EBUSY;
+ int err;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
@@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
kfree(sdata->u.ap.next_beacon);
return err;
}
- changed |= err;
+ *changed |= err;
break;
case NL80211_IFTYPE_ADHOC:
@@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
err = ieee80211_ibss_csa_beacon(sdata, params);
if (err < 0)
return err;
- changed |= err;
+ *changed |= err;
}
ieee80211_send_action_csa(sdata, params);
break;
#ifdef CONFIG_MAC80211_MESH
- case NL80211_IFTYPE_MESH_POINT:
- ifmsh = &sdata->u.mesh;
+ case NL80211_IFTYPE_MESH_POINT: {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
return -EINVAL;
@@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
return err;
}
- changed |= err;
+ *changed |= err;
}
if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
ieee80211_send_action_csa(sdata, params);
break;
+ }
#endif
default:
return -EOPNOTSUPP;
}
+ return 0;
+}
+
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_csa_settings *params)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_chanctx *chanctx;
+ int err, num_chanctx, changed = 0;
+
+ sdata_assert_lock(sdata);
+
+ if (!list_empty(&local->roc_list) || local->scanning)
+ return -EBUSY;
+
+ if (sdata->wdev.cac_started)
+ return -EBUSY;
+
+ if (cfg80211_chandef_identical(&params->chandef,
+ &sdata->vif.bss_conf.chandef))
+ return -EINVAL;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf) {
+ rcu_read_unlock();
+ return -EBUSY;
+ }
+
+ /* don't handle for multi-VIF cases */
+ chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+ if (chanctx->refcount > 1) {
+ rcu_read_unlock();
+ return -EBUSY;
+ }
+ num_chanctx = 0;
+ list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
+ num_chanctx++;
+ rcu_read_unlock();
+
+ if (num_chanctx > 1)
+ return -EBUSY;
+
+ /* don't allow another channel switch if one is already active. */
+ if (sdata->vif.csa_active)
+ return -EBUSY;
+
+ err = ieee80211_set_csa_beacon(sdata, params, &changed);
+ if (err)
+ return err;
+
sdata->csa_radar_required = params->radar_required;
if (params->block_tx)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index e458ca0dffec..06d28787945b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -991,7 +991,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems)
{
struct ieee80211_local *local = sdata->local;
- int freq;
struct cfg80211_bss *cbss;
struct ieee80211_bss *bss;
struct sta_info *sta;
@@ -1003,15 +1002,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
bool rates_updated = false;
- if (elems->ds_params)
- freq = ieee80211_channel_to_frequency(elems->ds_params[0],
- band);
- else
- freq = rx_status->freq;
-
- channel = ieee80211_get_channel(local->hw.wiphy, freq);
-
- if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+ channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
+ if (!channel)
return;
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0d1a0f801b94..222c28b75315 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1391,6 +1391,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
__le16 fc, bool acked);
+void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
/* IBSS code */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 94f0af29b742..dee50aefd6e8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2783,28 +2783,20 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems)
{
struct ieee80211_local *local = sdata->local;
- int freq;
struct ieee80211_bss *bss;
struct ieee80211_channel *channel;
sdata_assert_lock(sdata);
- if (elems->ds_params)
- freq = ieee80211_channel_to_frequency(elems->ds_params[0],
- rx_status->band);
- else
- freq = rx_status->freq;
-
- channel = ieee80211_get_channel(local->hw.wiphy, freq);
-
- if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+ channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
+ if (!channel)
return;
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
channel);
if (bss) {
- ieee80211_rx_bss_put(local, bss);
sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
+ ieee80211_rx_bss_put(local, bss);
}
}
@@ -3599,6 +3591,32 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
#ifdef CONFIG_PM
+void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+ sdata_lock(sdata);
+
+ if (ifmgd->auth_data) {
+ /*
+ * If we are trying to authenticate while suspending, cfg80211
+ * won't know and won't actually abort those attempts, thus we
+ * need to do that ourselves.
+ */
+ ieee80211_send_deauth_disassoc(sdata,
+ ifmgd->auth_data->bss->bssid,
+ IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_DEAUTH_LEAVING,
+ false, frame_buf);
+ ieee80211_destroy_auth_data(sdata, false);
+ cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
+ }
+
+ sdata_unlock(sdata);
+}
+
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -4417,37 +4435,41 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
bool tx = !req->local_state_change;
- bool report_frame = false;
- sdata_info(sdata,
- "deauthenticating from %pM by local choice (Reason: %u=%s)\n",
- req->bssid, req->reason_code, ieee80211_get_reason_code_string(req->reason_code));
+ if (ifmgd->auth_data &&
+ ether_addr_equal(ifmgd->auth_data->bss->bssid, req->bssid)) {
+ sdata_info(sdata,
+ "aborting authentication with %pM by local choice (Reason: %u=%s)\n",
+ req->bssid, req->reason_code,
+ ieee80211_get_reason_code_string(req->reason_code));
- if (ifmgd->auth_data) {
drv_mgd_prepare_tx(sdata->local, sdata);
ieee80211_send_deauth_disassoc(sdata, req->bssid,
IEEE80211_STYPE_DEAUTH,
req->reason_code, tx,
frame_buf);
ieee80211_destroy_auth_data(sdata, false);
+ cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
- report_frame = true;
- goto out;
+ return 0;
}
if (ifmgd->associated &&
ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
+ sdata_info(sdata,
+ "deauthenticating from %pM by local choice (Reason: %u=%s)\n",
+ req->bssid, req->reason_code,
+ ieee80211_get_reason_code_string(req->reason_code));
+
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
req->reason_code, tx, frame_buf);
- report_frame = true;
- }
-
- out:
- if (report_frame)
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
IEEE80211_DEAUTH_FRAME_LEN);
+ return 0;
+ }
- return 0;
+ return -ENOTCONN;
}
int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index af64fb8e8add..d478b880a0af 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -100,10 +100,18 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
/* remove all interfaces that were created in the driver */
list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata) ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
- sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ if (!ieee80211_sdata_running(sdata))
continue;
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_MONITOR:
+ continue;
+ case NL80211_IFTYPE_STATION:
+ ieee80211_mgd_quiesce(sdata);
+ break;
+ default:
+ break;
+ }
drv_remove_interface(local, sdata);
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5b617660b0ba..216c45b949e5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -333,6 +333,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
/* in VHT, STBC is binary */
if (status->flag & RX_FLAG_STBC_MASK)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
+ if (status->vht_flag & RX_VHT_FLAG_BF)
+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
pos++;
/* bandwidth */
if (status->vht_flag & RX_VHT_FLAG_80MHZ)
@@ -1245,6 +1247,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag;
+ sta->last_rx_rate_vht_flag = status->vht_flag;
sta->last_rx_rate_vht_nss = status->vht_nss;
}
}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 836f500dfbf3..3ce7f2c8539a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -1055,9 +1055,11 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
/* We don't want to restart sched scan anymore. */
local->sched_scan_req = NULL;
- if (rcu_access_pointer(local->sched_scan_sdata))
+ if (rcu_access_pointer(local->sched_scan_sdata)) {
ret = drv_sched_scan_stop(local, sdata);
-
+ if (!ret)
+ rcu_assign_pointer(local->sched_scan_sdata, NULL);
+ }
out:
mutex_unlock(&local->mtx);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index cd9f80498c48..19d36d4117e0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2900,7 +2900,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
if (!ieee80211_tx_prepare(sdata, &tx, skb))
break;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index ca1e65f4b133..819b87702b70 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -280,9 +280,6 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx)
{
int i;
- if (dev->n_targets == 0)
- return NULL;
-
for (i = 0; i < dev->n_targets; i++) {
if (dev->targets[i].idx == target_idx)
return &dev->targets[i];
@@ -546,9 +543,9 @@ error:
struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx)
{
- struct nfc_se *se, *n;
+ struct nfc_se *se;
- list_for_each_entry_safe(se, n, &dev->secure_elements, list)
+ list_for_each_entry(se, &dev->secure_elements, list)
if (se->idx == se_idx)
return se;
@@ -655,9 +652,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
{
pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len);
- if (gb_len > NFC_MAX_GT_LEN)
- return -EINVAL;
-
return nfc_llcp_set_remote_gb(dev, gb, gb_len);
}
EXPORT_SYMBOL(nfc_set_remote_general_bytes);
diff --git a/net/nfc/digital.h b/net/nfc/digital.h
index 08b29b55ea63..3759add68b1b 100644
--- a/net/nfc/digital.h
+++ b/net/nfc/digital.h
@@ -72,6 +72,12 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev);
int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech);
int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech);
+int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech);
+
+int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
+ struct sk_buff *skb);
+int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
+ struct sk_buff *skb);
int digital_target_found(struct nfc_digital_dev *ddev,
struct nfc_target *target, u8 protocol);
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c
index c129d1571ca6..e01e15dbf1ab 100644
--- a/net/nfc/digital_core.c
+++ b/net/nfc/digital_core.c
@@ -25,6 +25,8 @@
#define DIGITAL_PROTO_NFCF_RF_TECH \
(NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK)
+#define DIGITAL_PROTO_ISO15693_RF_TECH NFC_PROTO_ISO15693_MASK
+
struct digital_cmd {
struct list_head queue;
@@ -331,6 +333,18 @@ int digital_target_found(struct nfc_digital_dev *ddev,
}
break;
+ case NFC_PROTO_ISO15693:
+ framing = NFC_DIGITAL_FRAMING_ISO15693_T5T;
+ check_crc = digital_skb_check_crc_b;
+ add_crc = digital_skb_add_crc_b;
+ break;
+
+ case NFC_PROTO_ISO14443:
+ framing = NFC_DIGITAL_FRAMING_NFCA_T4T;
+ check_crc = digital_skb_check_crc_a;
+ add_crc = digital_skb_add_crc_a;
+ break;
+
default:
pr_err("Invalid protocol %d\n", protocol);
return -EINVAL;
@@ -461,7 +475,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols,
digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A,
digital_in_send_sens_req);
- if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) {
+ if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) {
digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F,
digital_in_send_sensf_req);
@@ -469,7 +483,11 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols,
digital_in_send_sensf_req);
}
- if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
+ if (matching_im_protocols & DIGITAL_PROTO_ISO15693_RF_TECH)
+ digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_ISO15693,
+ digital_in_send_iso15693_inv_req);
+
+ if (matching_tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
if (ddev->ops->tg_listen_mdaa) {
digital_add_poll_tech(ddev, 0,
digital_tg_listen_mdaa);
@@ -607,20 +625,30 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg,
if (IS_ERR(resp)) {
rc = PTR_ERR(resp);
+ resp = NULL;
goto done;
}
- if (ddev->curr_protocol == NFC_PROTO_MIFARE)
+ if (ddev->curr_protocol == NFC_PROTO_MIFARE) {
rc = digital_in_recv_mifare_res(resp);
- else
- rc = ddev->skb_check_crc(resp);
+ /* crc check is done in digital_in_recv_mifare_res() */
+ goto done;
+ }
+ if (ddev->curr_protocol == NFC_PROTO_ISO14443) {
+ rc = digital_in_iso_dep_pull_sod(ddev, resp);
+ if (rc)
+ goto done;
+ }
+
+ rc = ddev->skb_check_crc(resp);
+
+done:
if (rc) {
kfree_skb(resp);
resp = NULL;
}
-done:
data_exch->cb(data_exch->cb_context, resp, rc);
kfree(data_exch);
@@ -632,6 +660,7 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target,
{
struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev);
struct digital_data_exch *data_exch;
+ int rc;
data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL);
if (!data_exch) {
@@ -642,13 +671,27 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target,
data_exch->cb = cb;
data_exch->cb_context = cb_context;
- if (ddev->curr_protocol == NFC_PROTO_NFC_DEP)
- return digital_in_send_dep_req(ddev, target, skb, data_exch);
+ if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) {
+ rc = digital_in_send_dep_req(ddev, target, skb, data_exch);
+ goto exit;
+ }
+
+ if (ddev->curr_protocol == NFC_PROTO_ISO14443) {
+ rc = digital_in_iso_dep_push_sod(ddev, skb);
+ if (rc)
+ goto exit;
+ }
ddev->skb_add_crc(skb);
- return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete,
- data_exch);
+ rc = digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete,
+ data_exch);
+
+exit:
+ if (rc)
+ kfree(data_exch);
+
+ return rc;
}
static struct nfc_ops digital_nfc_ops = {
@@ -700,6 +743,10 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops,
ddev->protocols |= NFC_PROTO_FELICA_MASK;
if (supported_protocols & NFC_PROTO_NFC_DEP_MASK)
ddev->protocols |= NFC_PROTO_NFC_DEP_MASK;
+ if (supported_protocols & NFC_PROTO_ISO15693_MASK)
+ ddev->protocols |= NFC_PROTO_ISO15693_MASK;
+ if (supported_protocols & NFC_PROTO_ISO14443_MASK)
+ ddev->protocols |= NFC_PROTO_ISO14443_MASK;
ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN;
ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN;
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index 251c8c753ebe..278c3fed27e0 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -30,6 +30,7 @@
#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
+#define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20)
#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40)
#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00)
@@ -51,6 +52,34 @@
#define DIGITAL_SENSF_REQ_RC_SC 1
#define DIGITAL_SENSF_REQ_RC_AP 2
+#define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01
+
+#define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1)
+#define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2)
+#define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5)
+#define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0)
+#define DIGITAL_ISO15693_RES_IS_VALID(flags) \
+ (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
+
+#define DIGITAL_ISO_DEP_I_PCB 0x02
+#define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01)
+
+#define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0)
+
+#define DIGITAL_ISO_DEP_I_BLOCK 0x00
+
+#define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08)
+
+static const u8 digital_ats_fsc[] = {
+ 16, 24, 32, 40, 48, 64, 96, 128,
+};
+
+#define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F)
+#define DIGITAL_ATS_MAX_FSC 256
+
+#define DIGITAL_RATS_BYTE1 0xE0
+#define DIGITAL_RATS_PARAM 0x80
+
struct digital_sdd_res {
u8 nfcid1[4];
u8 bcc;
@@ -82,9 +111,127 @@ struct digital_sensf_res {
u8 rd[2];
} __packed;
+struct digital_iso15693_inv_req {
+ u8 flags;
+ u8 cmd;
+ u8 mask_len;
+ u64 mask;
+} __packed;
+
+struct digital_iso15693_inv_res {
+ u8 flags;
+ u8 dsfid;
+ u64 uid;
+} __packed;
+
static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
struct nfc_target *target);
+int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
+ struct sk_buff *skb)
+{
+ u8 pcb;
+ u8 block_type;
+
+ if (skb->len < 1)
+ return -EIO;
+
+ pcb = *skb->data;
+ block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb);
+
+ /* No support fo R-block nor S-block */
+ if (block_type != DIGITAL_ISO_DEP_I_BLOCK) {
+ pr_err("ISO_DEP R-block and S-block not supported\n");
+ return -EIO;
+ }
+
+ if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) {
+ pr_err("DID field in ISO_DEP PCB not supported\n");
+ return -EIO;
+ }
+
+ skb_pull(skb, 1);
+
+ return 0;
+}
+
+int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
+ struct sk_buff *skb)
+{
+ /*
+ * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must
+ * not be greater than remote FSC
+ */
+ if (skb->len + 3 > ddev->target_fsc)
+ return -EIO;
+
+ skb_push(skb, 1);
+
+ *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni;
+
+ ddev->curr_nfc_dep_pni =
+ DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1);
+
+ return 0;
+}
+
+static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
+ struct sk_buff *resp)
+{
+ struct nfc_target *target = arg;
+ u8 fsdi;
+ int rc;
+
+ if (IS_ERR(resp)) {
+ rc = PTR_ERR(resp);
+ resp = NULL;
+ goto exit;
+ }
+
+ if (resp->len < 2) {
+ rc = -EIO;
+ goto exit;
+ }
+
+ fsdi = DIGITAL_ATS_FSCI(resp->data[1]);
+ if (fsdi >= 8)
+ ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
+ else
+ ddev->target_fsc = digital_ats_fsc[fsdi];
+
+ ddev->curr_nfc_dep_pni = 0;
+
+ rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443);
+
+exit:
+ dev_kfree_skb(resp);
+ kfree(target);
+
+ if (rc)
+ digital_poll_next_tech(ddev);
+}
+
+static int digital_in_send_rats(struct nfc_digital_dev *ddev,
+ struct nfc_target *target)
+{
+ int rc;
+ struct sk_buff *skb;
+
+ skb = digital_skb_alloc(ddev, 2);
+ if (!skb)
+ return -ENOMEM;
+
+ *skb_put(skb, 1) = DIGITAL_RATS_BYTE1;
+ *skb_put(skb, 1) = DIGITAL_RATS_PARAM;
+
+ rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats,
+ target);
+ if (rc)
+ kfree_skb(skb);
+
+ return rc;
+}
+
static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp)
{
@@ -122,8 +269,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
goto exit_free_skb;
}
+ target->sel_res = sel_res;
+
if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
nfc_proto = NFC_PROTO_MIFARE;
+ } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) {
+ rc = digital_in_send_rats(ddev, target);
+ if (rc)
+ goto exit;
+ /*
+ * Skip target_found and don't free it for now. This will be
+ * done when receiving the ATS
+ */
+ goto exit_free_skb;
} else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) {
nfc_proto = NFC_PROTO_NFC_DEP;
} else {
@@ -131,8 +289,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
goto exit;
}
- target->sel_res = sel_res;
-
rc = digital_target_found(ddev, target, nfc_proto);
exit:
@@ -473,6 +629,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech)
return rc;
}
+static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev,
+ void *arg, struct sk_buff *resp)
+{
+ struct digital_iso15693_inv_res *res;
+ struct nfc_target *target = NULL;
+ int rc;
+
+ if (IS_ERR(resp)) {
+ rc = PTR_ERR(resp);
+ resp = NULL;
+ goto out_free_skb;
+ }
+
+ if (resp->len != sizeof(*res)) {
+ rc = -EIO;
+ goto out_free_skb;
+ }
+
+ res = (struct digital_iso15693_inv_res *)resp->data;
+
+ if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) {
+ PROTOCOL_ERR("ISO15693 - 10.3.1");
+ rc = -EINVAL;
+ goto out_free_skb;
+ }
+
+ target = kzalloc(sizeof(*target), GFP_KERNEL);
+ if (!target) {
+ rc = -ENOMEM;
+ goto out_free_skb;
+ }
+
+ target->is_iso15693 = 1;
+ target->iso15693_dsfid = res->dsfid;
+ memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid));
+
+ rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693);
+
+ kfree(target);
+
+out_free_skb:
+ dev_kfree_skb(resp);
+
+ if (rc)
+ digital_poll_next_tech(ddev);
+}
+
+int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech)
+{
+ struct digital_iso15693_inv_req *req;
+ struct sk_buff *skb;
+ int rc;
+
+ rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
+ NFC_DIGITAL_RF_TECH_ISO15693);
+ if (rc)
+ return rc;
+
+ rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
+ NFC_DIGITAL_FRAMING_ISO15693_INVENTORY);
+ if (rc)
+ return rc;
+
+ skb = digital_skb_alloc(ddev, sizeof(*req));
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */
+ req = (struct digital_iso15693_inv_req *)skb->data;
+
+ /* Single sub-carrier, high data rate, no AFI, single slot
+ * Inventory command
+ */
+ req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE |
+ DIGITAL_ISO15693_REQ_FLAG_INVENTORY |
+ DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS;
+ req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ;
+ req->mask_len = 0;
+
+ rc = digital_in_send_cmd(ddev, skb, 30,
+ digital_in_recv_iso15693_inv_res, NULL);
+ if (rc)
+ kfree_skb(skb);
+
+ return rc;
+}
+
static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev)
{
struct sk_buff *skb;
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c
index a07d2b818487..1b90c0531852 100644
--- a/net/nfc/hci/llc.c
+++ b/net/nfc/hci/llc.c
@@ -20,14 +20,12 @@
#include "llc.h"
-static struct list_head llc_engines;
+static LIST_HEAD(llc_engines);
int nfc_llc_init(void)
{
int r;
- INIT_LIST_HEAD(&llc_engines);
-
r = nfc_llc_nop_register();
if (r)
goto exit;
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index 6184bd1fba3a..b486f12ae243 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -27,7 +27,7 @@
static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
-static struct list_head llcp_devices;
+static LIST_HEAD(llcp_devices);
static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
@@ -293,9 +293,9 @@ static void nfc_llcp_sdreq_timer(unsigned long data)
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
{
- struct nfc_llcp_local *local, *n;
+ struct nfc_llcp_local *local;
- list_for_each_entry_safe(local, n, &llcp_devices, list)
+ list_for_each_entry(local, &llcp_devices, list)
if (local->dev == dev)
return local;
@@ -609,14 +609,16 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
{
- struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
+ struct nfc_llcp_local *local;
+
+ if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
+ return -EINVAL;
+ local = nfc_llcp_find_local(dev);
if (local == NULL) {
pr_err("No LLCP device\n");
return -ENODEV;
}
- if (gb_len < 3)
- return -EINVAL;
memset(local->remote_gb, 0, NFC_MAX_GT_LEN);
memcpy(local->remote_gb, gb, gb_len);
@@ -1622,8 +1624,6 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
int __init nfc_llcp_init(void)
{
- INIT_LIST_HEAD(&llcp_devices);
-
return nfc_llcp_sock_init();
}
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 56db888b1cd5..6c34ac978501 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -74,7 +74,7 @@ static int __nci_request(struct nci_dev *ndev,
ndev->req_status = NCI_REQ_PEND;
- init_completion(&ndev->req_completion);
+ reinit_completion(&ndev->req_completion);
req(ndev, opt);
completion_rc =
wait_for_completion_interruptible_timeout(&ndev->req_completion,
@@ -709,6 +709,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
ndev->ops = ops;
ndev->tx_headroom = tx_headroom;
ndev->tx_tailroom = tx_tailroom;
+ init_completion(&ndev->req_completion);
ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops,
supported_protocols,
diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c
index f1d426f10cce..ec250e77763a 100644
--- a/net/nfc/nci/spi.c
+++ b/net/nfc/nci/spi.c
@@ -105,7 +105,7 @@ int nci_spi_send(struct nci_spi *nspi,
if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED)
goto done;
- init_completion(&nspi->req_completion);
+ reinit_completion(&nspi->req_completion);
completion_rc = wait_for_completion_interruptible_timeout(
&nspi->req_completion,
NCI_SPI_SEND_TIMEOUT);
@@ -145,6 +145,7 @@ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
nspi->spi = spi;
nspi->ndev = ndev;
+ init_completion(&nspi->req_completion);
return nspi;
}
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index ebbf6fb88b35..43cb1c17e267 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -94,6 +94,14 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
target->sensf_res))
goto nla_put_failure;
+ if (target->is_iso15693) {
+ if (nla_put_u8(msg, NFC_ATTR_TARGET_ISO15693_DSFID,
+ target->iso15693_dsfid) ||
+ nla_put(msg, NFC_ATTR_TARGET_ISO15693_UID,
+ sizeof(target->iso15693_uid), target->iso15693_uid))
+ goto nla_put_failure;
+ }
+
return genlmsg_end(msg, hdr);
nla_put_failure:
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index 68602be07cc1..3e02ade508d8 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -7,7 +7,7 @@
static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
- struct net_device *dev)
+ struct net_device *dev, bool notify)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
@@ -30,20 +30,21 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
wdev->ssid_len = 0;
rdev_set_qos_map(rdev, dev, NULL);
- nl80211_send_ap_stopped(wdev);
+ if (notify)
+ nl80211_send_ap_stopped(wdev);
}
return err;
}
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
- struct net_device *dev)
+ struct net_device *dev, bool notify)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
wdev_lock(wdev);
- err = __cfg80211_stop_ap(rdev, dev);
+ err = __cfg80211_stop_ap(rdev, dev, notify);
wdev_unlock(wdev);
return err;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index cd10c1985074..9c9501a35fb5 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
return r;
}
+static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
+ u32 center_freq,
+ u32 bandwidth)
+{
+ struct ieee80211_channel *c;
+ u32 start_freq, end_freq, freq;
+ unsigned int dfs_cac_ms = 0;
+
+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
+
+ for (freq = start_freq; freq <= end_freq; freq += 20) {
+ c = ieee80211_get_channel(wiphy, freq);
+ if (!c)
+ return 0;
+
+ if (c->flags & IEEE80211_CHAN_DISABLED)
+ return 0;
+
+ if (!(c->flags & IEEE80211_CHAN_RADAR))
+ continue;
+
+ if (c->dfs_cac_ms > dfs_cac_ms)
+ dfs_cac_ms = c->dfs_cac_ms;
+ }
+
+ return dfs_cac_ms;
+}
+
+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef)
+{
+ int width;
+ unsigned int t1 = 0, t2 = 0;
+
+ if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+ return 0;
+
+ width = cfg80211_chandef_get_width(chandef);
+ if (width < 0)
+ return 0;
+
+ t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
+ chandef->center_freq1,
+ width);
+
+ if (!chandef->center_freq2)
+ return t1;
+
+ t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
+ chandef->center_freq2,
+ width);
+
+ return max(t1, t2);
+}
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index eb7f40821c09..086cddd03ba6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -783,7 +783,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
- cfg80211_stop_ap(rdev, dev);
+ cfg80211_stop_ap(rdev, dev, true);
break;
default:
break;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 40683004d523..5b1fdcadd469 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -166,7 +166,6 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
mutex_unlock(&wdev->mtx);
}
-#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
@@ -246,10 +245,6 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs);
/* IBSS */
-int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct cfg80211_ibss_params *params,
- struct cfg80211_cached_keys *connkeys);
int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_ibss_params *params,
@@ -283,7 +278,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
/* AP */
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
- struct net_device *dev);
+ struct net_device *dev, bool notify);
/* MLME */
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
@@ -402,6 +397,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
void cfg80211_dfs_channels_update_work(struct work_struct *work);
+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef);
static inline int
cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
index fdfd3f063a9b..b35da8dc85de 100644
--- a/net/wireless/genregdb.awk
+++ b/net/wireless/genregdb.awk
@@ -66,6 +66,7 @@ function parse_reg_rule()
units = $8
sub(/\)/, "", units)
sub(/,/, "", units)
+ dfs_cac = $9
if (units == "mW") {
if (power == 100) {
power = 20
@@ -78,7 +79,12 @@ function parse_reg_rule()
} else {
print "Unknown power value in database!"
}
+ } else {
+ dfs_cac = $8
}
+ sub(/,/, "", dfs_cac)
+ sub(/\(/, "", dfs_cac)
+ sub(/\)/, "", dfs_cac)
flagstr = ""
for (i=8; i<=NF; i++)
flagstr = flagstr $i
@@ -111,7 +117,7 @@ function parse_reg_rule()
}
flags = flags "0"
- printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
+ printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
rules++
}
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 349db9ddc0d1..a6b5bdad039c 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -82,10 +82,10 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
}
EXPORT_SYMBOL(cfg80211_ibss_joined);
-int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct cfg80211_ibss_params *params,
- struct cfg80211_cached_keys *connkeys)
+static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *params,
+ struct cfg80211_cached_keys *connkeys)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct ieee80211_channel *check_chan;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index d47c9d127b1e..c52ff59a3e96 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
switch (event) {
case NL80211_RADAR_CAC_FINISHED:
timeout = wdev->cac_start_time +
- msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
+ msecs_to_jiffies(wdev->cac_time_ms);
WARN_ON(!time_after_eq(jiffies, timeout));
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2c38b28a85b9..052c1bf8ffac 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
time))
goto nla_put_failure;
+ if (nla_put_u32(msg,
+ NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
+ chan->dfs_cac_ms))
+ goto nla_put_failure;
}
}
@@ -3328,7 +3332,7 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
- return cfg80211_stop_ap(rdev, dev);
+ return cfg80211_stop_ap(rdev, dev, false);
}
static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -4614,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] =
[NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
+ [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
};
static int parse_reg_rule(struct nlattr *tb[],
@@ -4649,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[],
power_rule->max_antenna_gain =
nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
+ if (tb[NL80211_ATTR_DFS_CAC_TIME])
+ reg_rule->dfs_cac_ms =
+ nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
+
return 0;
}
@@ -5136,7 +5145,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
power_rule->max_antenna_gain) ||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
- power_rule->max_eirp))
+ power_rule->max_eirp) ||
+ nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
+ reg_rule->dfs_cac_ms))
goto nla_put_failure_rcu;
nla_nest_end(msg, nl_reg_rule);
@@ -5768,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
+ unsigned int cac_time_ms;
int err;
dfs_region = reg_get_dfs_region(wdev->wiphy);
@@ -5803,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (err)
return err;
- err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
+ cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
+ if (WARN_ON(!cac_time_ms))
+ cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+
+ err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef,
+ cac_time_ms);
if (!err) {
wdev->chandef = chandef;
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
+ wdev->cac_time_ms = cac_time_ms;
}
return err;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 90b82e08ae69..f59aaac586f8 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -91,10 +91,6 @@ static struct regulatory_request __rcu *last_request =
/* To trigger userspace events */
static struct platform_device *reg_pdev;
-static const struct device_type reg_device_type = {
- .uevent = reg_device_uevent,
-};
-
/*
* Central wireless core regulatory domains, we only need two,
* the current one and a world regulatory domain in case we have no
@@ -244,19 +240,21 @@ static char user_alpha2[2];
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
-static void reg_kfree_last_request(void)
+static void reg_free_request(struct regulatory_request *lr)
{
- struct regulatory_request *lr;
-
- lr = get_last_request();
-
if (lr != &core_request_world && lr)
kfree_rcu(lr, rcu_head);
}
static void reg_update_last_request(struct regulatory_request *request)
{
- reg_kfree_last_request();
+ struct regulatory_request *lr;
+
+ lr = get_last_request();
+ if (lr == request)
+ return;
+
+ reg_free_request(lr);
rcu_assign_pointer(last_request, request);
}
@@ -487,11 +485,16 @@ static inline void reg_regdb_query(const char *alpha2) {}
/*
* This lets us keep regulatory code which is updated on a regulatory
- * basis in userspace. Country information is filled in by
- * reg_device_uevent
+ * basis in userspace.
*/
static int call_crda(const char *alpha2)
{
+ char country[12];
+ char *env[] = { country, NULL };
+
+ snprintf(country, sizeof(country), "COUNTRY=%c%c",
+ alpha2[0], alpha2[1]);
+
if (!is_world_regdom((char *) alpha2))
pr_info("Calling CRDA for country: %c%c\n",
alpha2[0], alpha2[1]);
@@ -501,7 +504,7 @@ static int call_crda(const char *alpha2)
/* query internal regulatory database (if it exists) */
reg_regdb_query(alpha2);
- return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
+ return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
}
static enum reg_request_treatment
@@ -755,6 +758,9 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
power_rule2->max_antenna_gain);
+ intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
+ rule2->dfs_cac_ms);
+
if (!is_valid_reg_rule(intersected_rule))
return -EINVAL;
@@ -1077,6 +1083,14 @@ static void handle_channel(struct wiphy *wiphy,
min_t(int, chan->orig_mag,
MBI_TO_DBI(power_rule->max_antenna_gain));
chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+
+ if (chan->flags & IEEE80211_CHAN_RADAR) {
+ if (reg_rule->dfs_cac_ms)
+ chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
+ else
+ chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+ }
+
if (chan->orig_mpwr) {
/*
* Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
@@ -2255,9 +2269,9 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
const struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_freq_range *freq_range = NULL;
const struct ieee80211_power_rule *power_rule = NULL;
- char bw[32];
+ char bw[32], cac_time[32];
- pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
+ pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
for (i = 0; i < rd->n_reg_rules; i++) {
reg_rule = &rd->reg_rules[i];
@@ -2272,23 +2286,32 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
snprintf(bw, sizeof(bw), "%d KHz",
freq_range->max_bandwidth_khz);
+ if (reg_rule->flags & NL80211_RRF_DFS)
+ scnprintf(cac_time, sizeof(cac_time), "%u s",
+ reg_rule->dfs_cac_ms/1000);
+ else
+ scnprintf(cac_time, sizeof(cac_time), "N/A");
+
+
/*
* There may not be documentation for max antenna gain
* in certain regions
*/
if (power_rule->max_antenna_gain)
- pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
+ pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
freq_range->start_freq_khz,
freq_range->end_freq_khz,
bw,
power_rule->max_antenna_gain,
- power_rule->max_eirp);
+ power_rule->max_eirp,
+ cac_time);
else
- pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
+ pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
freq_range->start_freq_khz,
freq_range->end_freq_khz,
bw,
- power_rule->max_eirp);
+ power_rule->max_eirp,
+ cac_time);
}
}
@@ -2361,9 +2384,6 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
{
const struct ieee80211_regdomain *intersected_rd = NULL;
- if (is_world_regdom(rd->alpha2))
- return -EINVAL;
-
if (!regdom_changes(rd->alpha2))
return -EALREADY;
@@ -2552,26 +2572,6 @@ int set_regdom(const struct ieee80211_regdomain *rd)
return 0;
}
-int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct regulatory_request *lr;
- u8 alpha2[2];
- bool add = false;
-
- rcu_read_lock();
- lr = get_last_request();
- if (lr && !lr->processed) {
- memcpy(alpha2, lr->alpha2, 2);
- add = true;
- }
- rcu_read_unlock();
-
- if (add)
- return add_uevent_var(env, "COUNTRY=%c%c",
- alpha2[0], alpha2[1]);
- return 0;
-}
-
void wiphy_regulatory_register(struct wiphy *wiphy)
{
struct regulatory_request *lr;
@@ -2622,8 +2622,6 @@ int __init regulatory_init(void)
if (IS_ERR(reg_pdev))
return PTR_ERR(reg_pdev);
- reg_pdev->dev.type = &reg_device_type;
-
spin_lock_init(&reg_requests_lock);
spin_lock_init(&reg_pending_beacons_lock);
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 18524617ab62..37c180df34b7 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -26,7 +26,6 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
int regulatory_hint_user(const char *alpha2,
enum nl80211_user_reg_hint_type user_reg_hint_type);
-int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
void wiphy_regulatory_register(struct wiphy *wiphy);
void wiphy_regulatory_deregister(struct wiphy *wiphy);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d1ed4aebbbb7..7d09a712cb1f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -659,9 +659,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
continue;
if (ssidlen && ie[1] != ssidlen)
continue;
- /* that would be odd ... */
- if (bss->pub.beacon_ies)
- continue;
if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss))
continue;
if (WARN_ON_ONCE(!list_empty(&bss->hidden_list)))
@@ -680,7 +677,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
/* Returned bss is reference counted and must be cleaned up appropriately. */
static struct cfg80211_internal_bss *
cfg80211_bss_update(struct cfg80211_registered_device *dev,
- struct cfg80211_internal_bss *tmp)
+ struct cfg80211_internal_bss *tmp,
+ bool signal_valid)
{
struct cfg80211_internal_bss *found = NULL;
@@ -765,7 +763,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
}
found->pub.beacon_interval = tmp->pub.beacon_interval;
- found->pub.signal = tmp->pub.signal;
+ /*
+ * don't update the signal if beacon was heard on
+ * adjacent channel.
+ */
+ if (signal_valid)
+ found->pub.signal = tmp->pub.signal;
found->pub.capability = tmp->pub.capability;
found->ts = tmp->ts;
} else {
@@ -869,13 +872,14 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
/* Returned bss is reference counted and must be cleaned up appropriately. */
struct cfg80211_bss*
cfg80211_inform_bss_width(struct wiphy *wiphy,
- struct ieee80211_channel *channel,
+ struct ieee80211_channel *rx_channel,
enum nl80211_bss_scan_width scan_width,
const u8 *bssid, u64 tsf, u16 capability,
u16 beacon_interval, const u8 *ie, size_t ielen,
s32 signal, gfp_t gfp)
{
struct cfg80211_bss_ies *ies;
+ struct ieee80211_channel *channel;
struct cfg80211_internal_bss tmp = {}, *res;
if (WARN_ON(!wiphy))
@@ -885,7 +889,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
(signal < 0 || signal > 100)))
return NULL;
- channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel);
+ channel = cfg80211_get_bss_channel(wiphy, ie, ielen, rx_channel);
if (!channel)
return NULL;
@@ -913,7 +917,8 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
rcu_assign_pointer(tmp.pub.beacon_ies, ies);
rcu_assign_pointer(tmp.pub.ies, ies);
- res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp,
+ rx_channel == channel);
if (!res)
return NULL;
@@ -929,20 +934,21 @@ EXPORT_SYMBOL(cfg80211_inform_bss_width);
/* Returned bss is reference counted and must be cleaned up appropriately. */
struct cfg80211_bss *
cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
- struct ieee80211_channel *channel,
+ struct ieee80211_channel *rx_channel,
enum nl80211_bss_scan_width scan_width,
struct ieee80211_mgmt *mgmt, size_t len,
s32 signal, gfp_t gfp)
{
struct cfg80211_internal_bss tmp = {}, *res;
struct cfg80211_bss_ies *ies;
+ struct ieee80211_channel *channel;
size_t ielen = len - offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
offsetof(struct ieee80211_mgmt, u.beacon.variable));
- trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt,
+ trace_cfg80211_inform_bss_width_frame(wiphy, rx_channel, scan_width, mgmt,
len, signal);
if (WARN_ON(!mgmt))
@@ -959,7 +965,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
return NULL;
channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
- ielen, channel);
+ ielen, rx_channel);
if (!channel)
return NULL;
@@ -983,7 +989,8 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
- res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp,
+ rx_channel == channel);
if (!res)
return NULL;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f04d4c32e96e..acdcb4a81817 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -64,7 +64,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
int n_channels, err;
ASSERT_RTNL();
- ASSERT_RDEV_LOCK(rdev);
ASSERT_WDEV_LOCK(wdev);
if (rdev->scan_req || rdev->scan_msg)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 2bb685f3e8fc..e5872ff2c27c 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -854,7 +854,6 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
struct wireless_dev *wdev;
ASSERT_RTNL();
- ASSERT_RDEV_LOCK(rdev);
list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev);
@@ -867,7 +866,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
int err;
enum nl80211_iftype otype = dev->ieee80211_ptr->iftype;
- ASSERT_RDEV_LOCK(rdev);
+ ASSERT_RTNL();
/* don't support changing VLANs, you just re-create them */
if (otype == NL80211_IFTYPE_AP_VLAN)
@@ -902,7 +901,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
switch (otype) {
case NL80211_IFTYPE_AP:
- cfg80211_stop_ap(rdev, dev);
+ cfg80211_stop_ap(rdev, dev, true);
break;
case NL80211_IFTYPE_ADHOC:
cfg80211_leave_ibss(rdev, dev, false);
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 14c9a2583ba0..86c331a65664 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -21,7 +21,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
const u8 *prev_bssid = NULL;
int err, i;
- ASSERT_RDEV_LOCK(rdev);
+ ASSERT_RTNL();
ASSERT_WDEV_LOCK(wdev);
if (!netif_running(wdev->netdev))