summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/ath3k.c29
-rw-r--r--drivers/bluetooth/btmrvl_drv.h1
-rw-r--r--drivers/bluetooth/btmrvl_main.c24
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c16
-rw-r--r--drivers/bluetooth/btusb.c34
-rw-r--r--drivers/net/wireless/b43/main.c50
-rw-r--r--drivers/net/wireless/b43/phy_n.c347
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c1
-rw-r--r--include/net/bluetooth/hci.h6
-rw-r--r--include/net/bluetooth/hci_core.h20
-rw-r--r--include/net/bluetooth/l2cap.h2
-rw-r--r--net/bluetooth/amp.c6
-rw-r--r--net/bluetooth/hci_conn.c41
-rw-r--r--net/bluetooth/hci_core.c28
-rw-r--r--net/bluetooth/hci_event.c110
-rw-r--r--net/bluetooth/l2cap_core.c32
-rw-r--r--net/bluetooth/l2cap_sock.c7
-rw-r--r--net/bluetooth/mgmt.c6
-rw-r--r--net/bluetooth/rfcomm/core.c3
-rw-r--r--net/bluetooth/rfcomm/sock.c3
-rw-r--r--net/bluetooth/sco.c6
-rw-r--r--net/bluetooth/smp.c24
22 files changed, 524 insertions, 272 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 230c552daf91..a0d7355ef127 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -27,6 +27,7 @@
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/usb.h>
+#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#define VERSION "1.0"
@@ -50,12 +51,12 @@
#define ATH3K_NAME_LEN 0xFF
struct ath3k_version {
- unsigned int rom_version;
- unsigned int build_version;
- unsigned int ram_version;
- unsigned char ref_clock;
- unsigned char reserved[0x07];
-};
+ __le32 rom_version;
+ __le32 build_version;
+ __le32 ram_version;
+ __u8 ref_clock;
+ __u8 reserved[7];
+} __packed;
static const struct usb_device_id ath3k_table[] = {
/* Atheros AR3011 */
@@ -349,7 +350,8 @@ static int ath3k_load_patch(struct usb_device *udev)
unsigned char fw_state;
char filename[ATH3K_NAME_LEN] = {0};
const struct firmware *firmware;
- struct ath3k_version fw_version, pt_version;
+ struct ath3k_version fw_version;
+ __u32 pt_rom_version, pt_build_version;
int ret;
ret = ath3k_get_state(udev, &fw_state);
@@ -370,7 +372,7 @@ static int ath3k_load_patch(struct usb_device *udev)
}
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
- le32_to_cpu(fw_version.rom_version));
+ le32_to_cpu(fw_version.rom_version));
ret = request_firmware(&firmware, filename, &udev->dev);
if (ret < 0) {
@@ -378,12 +380,13 @@ static int ath3k_load_patch(struct usb_device *udev)
return ret;
}
- pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
- pt_version.build_version = *(int *)
- (firmware->data + firmware->size - 4);
+ pt_rom_version = get_unaligned_le32(firmware->data +
+ firmware->size - 8);
+ pt_build_version = get_unaligned_le32(firmware->data +
+ firmware->size - 4);
- if ((pt_version.rom_version != fw_version.rom_version) ||
- (pt_version.build_version <= fw_version.build_version)) {
+ if (pt_rom_version != le32_to_cpu(fw_version.rom_version) ||
+ pt_build_version <= le32_to_cpu(fw_version.build_version)) {
BT_ERR("Patch file version did not match with firmware");
release_firmware(firmware);
return -EINVAL;
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index caf684119a4e..38ad66289ad6 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -91,6 +91,7 @@ struct btmrvl_private {
/* Vendor specific Bluetooth commands */
#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03
+#define BT_CMD_SET_BDADDR 0xFC22
#define BT_CMD_AUTO_SLEEP_MODE 0xFC23
#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59
#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index cc65fd2fe856..bae8e6a0ecf6 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -539,6 +539,29 @@ static int btmrvl_setup(struct hci_dev *hdev)
return 0;
}
+static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ long ret;
+ u8 buf[8];
+
+ buf[0] = MRVL_VENDOR_PKT;
+ buf[1] = sizeof(bdaddr_t);
+ memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, sizeof(buf), buf,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: changing btmrvl device address failed (%ld)",
+ hdev->name, ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
/*
* This function handles the event generated by firmware, rx data
* received from firmware, and tx data sent from kernel.
@@ -632,6 +655,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
hdev->flush = btmrvl_flush;
hdev->send = btmrvl_send_frame;
hdev->setup = btmrvl_setup;
+ hdev->set_bdaddr = btmrvl_set_bdaddr;
hdev->dev_type = priv->btmrvl_dev.dev_type;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index efff06438b02..3e683b153259 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1169,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
priv = card->priv;
+ hcidev = priv->btmrvl_dev.hcidev;
+ BT_DBG("%s: SDIO suspend", hcidev->name);
+ hci_suspend_dev(hcidev);
+ skb_queue_purge(&priv->adapter->tx_queue);
if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
@@ -1176,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct device *dev)
return -EBUSY;
}
}
- hcidev = priv->btmrvl_dev.hcidev;
- BT_DBG("%s: SDIO suspend", hcidev->name);
- hci_suspend_dev(hcidev);
- skb_queue_purge(&priv->adapter->tx_queue);
priv->adapter->is_suspended = true;
@@ -1221,13 +1221,13 @@ static int btmrvl_sdio_resume(struct device *dev)
return 0;
}
- priv->adapter->is_suspended = false;
- hcidev = priv->btmrvl_dev.hcidev;
- BT_DBG("%s: SDIO resume", hcidev->name);
- hci_resume_dev(hcidev);
priv->hw_wakeup_firmware(priv);
priv->adapter->hs_state = HS_DEACTIVATED;
+ hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
+ priv->adapter->is_suspended = false;
+ BT_DBG("%s: SDIO resume", hcidev->name);
+ hci_resume_dev(hcidev);
return 0;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ed7b33b06b43..292c38e8aa17 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -48,6 +48,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_INTEL 0x100
#define BTUSB_INTEL_BOOT 0x200
#define BTUSB_BCM_PATCHRAM 0x400
+#define BTUSB_MARVELL 0x800
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -113,6 +114,9 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
+ /* ASUSTek Computer - Broadcom based */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) },
+
/* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
@@ -242,6 +246,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
+ /* Marvell device */
+ { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
+ { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
+
{ } /* Terminating entry */
};
@@ -1455,6 +1463,29 @@ static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
return 0;
}
+static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
+ const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ u8 buf[8];
+ long ret;
+
+ buf[0] = 0xfe;
+ buf[1] = sizeof(bdaddr_t);
+ memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: changing Marvell device address failed (%ld)",
+ hdev->name, ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
@@ -1766,6 +1797,9 @@ static int btusb_probe(struct usb_interface *intf,
hdev->set_bdaddr = btusb_set_bdaddr_intel;
}
+ if (id->driver_info & BTUSB_MARVELL)
+ hdev->set_bdaddr = btusb_set_bdaddr_marvell;
+
if (id->driver_info & BTUSB_INTEL_BOOT)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 3e127be06bfb..47b6fa5fa5b2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4385,8 +4385,9 @@ static int b43_phy_versioning(struct b43_wldev *dev)
u8 phy_type;
u8 phy_rev;
u16 radio_manuf;
- u16 radio_ver;
+ u16 radio_id;
u16 radio_rev;
+ u8 radio_ver;
int unsupported = 0;
/* Get PHY versioning */
@@ -4452,7 +4453,9 @@ static int b43_phy_versioning(struct b43_wldev *dev)
radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
- radio_ver = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+ radio_ver = 0; /* Is there version somewhere? */
} else if (core_rev >= 24) {
u16 radio24[3];
@@ -4461,12 +4464,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
- /* Broadcom uses "id" for our "ver" and has separated "ver" */
- /* radio_ver = (radio24[0] & 0xF0) >> 4; */
-
radio_manuf = 0x17F;
- radio_ver = (radio24[2] << 8) | radio24[1];
+ radio_id = (radio24[2] << 8) | radio24[1];
radio_rev = (radio24[0] & 0xF);
+ radio_ver = (radio24[0] & 0xF0) >> 4;
} else {
if (dev->dev->chip_id == 0x4317) {
if (dev->dev->chip_rev == 0)
@@ -4485,15 +4486,16 @@ static int b43_phy_versioning(struct b43_wldev *dev)
<< 16;
}
radio_manuf = (tmp & 0x00000FFF);
- radio_ver = (tmp & 0x0FFFF000) >> 12;
+ radio_id = (tmp & 0x0FFFF000) >> 12;
radio_rev = (tmp & 0xF0000000) >> 28;
+ radio_ver = 0; /* Probably not available on old hw */
}
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
case B43_PHYTYPE_A:
- if (radio_ver != 0x2060)
+ if (radio_id != 0x2060)
unsupported = 1;
if (radio_rev != 1)
unsupported = 1;
@@ -4501,30 +4503,31 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
case B43_PHYTYPE_B:
- if ((radio_ver & 0xFFF0) != 0x2050)
+ if ((radio_id & 0xFFF0) != 0x2050)
unsupported = 1;
break;
case B43_PHYTYPE_G:
- if (radio_ver != 0x2050)
+ if (radio_id != 0x2050)
unsupported = 1;
break;
case B43_PHYTYPE_N:
- if (radio_ver != 0x2055 && radio_ver != 0x2056 &&
- radio_ver != 0x2057)
+ if (radio_id != 0x2055 && radio_id != 0x2056 &&
+ radio_id != 0x2057)
unsupported = 1;
- if (radio_ver == 0x2057 && !(radio_rev == 9))
+ if (radio_id == 0x2057 &&
+ !(radio_rev == 9 || radio_rev == 14))
unsupported = 1;
break;
case B43_PHYTYPE_LP:
- if (radio_ver != 0x2062 && radio_ver != 0x2063)
+ if (radio_id != 0x2062 && radio_id != 0x2063)
unsupported = 1;
break;
case B43_PHYTYPE_HT:
- if (radio_ver != 0x2059)
+ if (radio_id != 0x2059)
unsupported = 1;
break;
case B43_PHYTYPE_LCN:
- if (radio_ver != 0x2064)
+ if (radio_id != 0x2064)
unsupported = 1;
break;
default:
@@ -4532,15 +4535,17 @@ static int b43_phy_versioning(struct b43_wldev *dev)
}
if (unsupported) {
b43err(dev->wl,
- "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u)\n",
- radio_manuf, radio_ver, radio_rev);
+ "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n",
+ radio_manuf, radio_id, radio_rev, radio_ver);
return -EOPNOTSUPP;
}
- b43info(dev->wl, "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u\n",
- radio_manuf, radio_ver, radio_rev);
+ b43info(dev->wl,
+ "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n",
+ radio_manuf, radio_id, radio_rev, radio_ver);
+ /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */
phy->radio_manuf = radio_manuf;
- phy->radio_ver = radio_ver;
+ phy->radio_ver = radio_id;
phy->radio_rev = radio_rev;
phy->analog = analog_type;
@@ -5152,7 +5157,8 @@ static int b43_setup_bands(struct b43_wldev *dev,
bool limited_2g;
/* We don't support all 2 GHz channels on some devices */
- limited_2g = phy->radio_ver == 0x2057 && phy->radio_rev == 9;
+ limited_2g = phy->radio_ver == 0x2057 &&
+ (phy->radio_rev == 9 || phy->radio_rev == 14);
if (have_2ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ?
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 92bfe352ba08..11d754360d71 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -2708,25 +2708,39 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
+ /* TX to RX */
+ u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
+ u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
+ /* RX to TX */
u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
0x1F };
u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
+ static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
u8 ntab7_138_146[] = { 0x11, 0x11 };
u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
- u16 lpf_20, lpf_40, lpf_11b;
- u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
- u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
+ u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
+ u16 bcap_val;
+ s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
+ u16 scap_val;
+ s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
bool rccal_ovrd = false;
- u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
u16 bias, conv, filt;
+ u32 noise_tbl[2];
+
u32 tmp32;
u8 core;
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
if (phy->rev == 7) {
b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
@@ -2746,11 +2760,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
}
- if (phy->rev <= 8) {
+
+ if (phy->rev >= 16) {
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
+ } else if (phy->rev <= 8) {
b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
}
- if (phy->rev >= 8)
+
+ if (phy->rev >= 16)
+ b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
+ else if (phy->rev >= 8)
b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
@@ -2758,9 +2779,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
tmp32 &= 0xffffff;
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
+ b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
+ ARRAY_SIZE(tx2rx_events));
if (b43_nphy_ipa(dev))
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
@@ -2768,84 +2791,176 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
- lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
- lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
- lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
+ for (core = 0; core < 2; core++) {
+ lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
+ lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
+ lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
+ }
+
+ bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
+ scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
+
if (b43_nphy_ipa(dev)) {
- if ((phy->radio_rev == 5 && b43_is_40mhz(dev)) ||
- phy->radio_rev == 7 || phy->radio_rev == 8) {
- bcap_val = b43_radio_read(dev, 0x16b);
- scap_val = b43_radio_read(dev, 0x16a);
- scap_val_11b = scap_val;
- bcap_val_11b = bcap_val;
- if (phy->radio_rev == 5 && b43_is_40mhz(dev)) {
- scap_val_11n_20 = scap_val;
- bcap_val_11n_20 = bcap_val;
- scap_val_11n_40 = bcap_val_11n_40 = 0xc;
+ bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ;
+
+ switch (phy->radio_rev) {
+ case 5:
+ /* Check radio version (to be 0) by PHY rev for now */
+ if (phy->rev == 8 && b43_is_40mhz(dev)) {
+ for (core = 0; core < 2; core++) {
+ scap_val_11b[core] = scap_val;
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11n_20[core] = scap_val;
+ bcap_val_11n_20[core] = bcap_val;
+ scap_val_11n_40[core] = 0xc;
+ bcap_val_11n_40[core] = 0xc;
+ }
+
rccal_ovrd = true;
- } else { /* Rev 7/8 */
- lpf_20 = 4;
- lpf_11b = 1;
+ }
+ if (phy->rev == 9) {
+ /* TODO: Radio version 1 (e.g. BCM5357B0) */
+ }
+ break;
+ case 7:
+ case 8:
+ for (core = 0; core < 2; core++) {
+ scap_val_11b[core] = scap_val;
+ bcap_val_11b[core] = bcap_val;
+ lpf_ofdm_20mhz[core] = 4;
+ lpf_11b[core] = 1;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- scap_val_11n_20 = 0xc;
- bcap_val_11n_20 = 0xc;
- scap_val_11n_40 = 0xa;
- bcap_val_11n_40 = 0xa;
+ scap_val_11n_20[core] = 0xc;
+ bcap_val_11n_20[core] = 0xc;
+ scap_val_11n_40[core] = 0xa;
+ bcap_val_11n_40[core] = 0xa;
} else {
- scap_val_11n_20 = 0x14;
- bcap_val_11n_20 = 0x14;
- scap_val_11n_40 = 0xf;
- bcap_val_11n_40 = 0xf;
+ scap_val_11n_20[core] = 0x14;
+ bcap_val_11n_20[core] = 0x14;
+ scap_val_11n_40[core] = 0xf;
+ bcap_val_11n_40[core] = 0xf;
}
- rccal_ovrd = true;
}
+
+ rccal_ovrd = true;
+ break;
+ case 9:
+ for (core = 0; core < 2; core++) {
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11b[core] = scap_val;
+ lpf_11b[core] = 1;
+
+ if (ghz2) {
+ bcap_val_11n_20[core] = bcap_val + 13;
+ scap_val_11n_20[core] = scap_val + 15;
+ } else {
+ bcap_val_11n_20[core] = bcap_val + 14;
+ scap_val_11n_20[core] = scap_val + 15;
+ }
+ lpf_ofdm_20mhz[core] = 4;
+
+ if (ghz2) {
+ bcap_val_11n_40[core] = bcap_val - 7;
+ scap_val_11n_40[core] = scap_val - 5;
+ } else {
+ bcap_val_11n_40[core] = bcap_val + 2;
+ scap_val_11n_40[core] = scap_val + 4;
+ }
+ lpf_ofdm_40mhz[core] = 4;
+ }
+
+ rccal_ovrd = true;
+ break;
+ case 14:
+ for (core = 0; core < 2; core++) {
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11b[core] = scap_val;
+ lpf_11b[core] = 1;
+ }
+
+ bcap_val_11n_20[0] = bcap_val + 20;
+ scap_val_11n_20[0] = scap_val + 20;
+ lpf_ofdm_20mhz[0] = 3;
+
+ bcap_val_11n_20[1] = bcap_val + 16;
+ scap_val_11n_20[1] = scap_val + 16;
+ lpf_ofdm_20mhz[1] = 3;
+
+ bcap_val_11n_40[0] = bcap_val + 20;
+ scap_val_11n_40[0] = scap_val + 20;
+ lpf_ofdm_40mhz[0] = 4;
+
+ bcap_val_11n_40[1] = bcap_val + 10;
+ scap_val_11n_40[1] = scap_val + 10;
+ lpf_ofdm_40mhz[1] = 4;
+
+ rccal_ovrd = true;
+ break;
}
} else {
if (phy->radio_rev == 5) {
- lpf_20 = 1;
- lpf_40 = 3;
- bcap_val = b43_radio_read(dev, 0x16b);
- scap_val = b43_radio_read(dev, 0x16a);
- scap_val_11b = scap_val;
- bcap_val_11b = bcap_val;
- scap_val_11n_20 = 0x11;
- scap_val_11n_40 = 0x11;
- bcap_val_11n_20 = 0x13;
- bcap_val_11n_40 = 0x13;
+ for (core = 0; core < 2; core++) {
+ lpf_ofdm_20mhz[core] = 1;
+ lpf_ofdm_40mhz[core] = 3;
+ scap_val_11b[core] = scap_val;
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11n_20[core] = 0x11;
+ scap_val_11n_40[core] = 0x11;
+ bcap_val_11n_20[core] = 0x13;
+ bcap_val_11n_40[core] = 0x13;
+ }
+
rccal_ovrd = true;
}
}
if (rccal_ovrd) {
- rx2tx_lut_20_11b = (bcap_val_11b << 8) |
- (scap_val_11b << 3) |
- lpf_11b;
- rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
- (scap_val_11n_20 << 3) |
- lpf_20;
- rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
- (scap_val_11n_40 << 3) |
- lpf_40;
+ u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
+ u8 rx2tx_lut_extra = 1;
+
+ for (core = 0; core < 2; core++) {
+ bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
+ scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
+ bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
+ scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
+ bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
+ scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
+
+ rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
+ (bcap_val_11b[core] << 8) |
+ (scap_val_11b[core] << 3) |
+ lpf_11b[core];
+ rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
+ (bcap_val_11n_20[core] << 8) |
+ (scap_val_11n_20[core] << 3) |
+ lpf_ofdm_20mhz[core];
+ rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
+ (bcap_val_11n_40[core] << 8) |
+ (scap_val_11n_40[core] << 3) |
+ lpf_ofdm_40mhz[core];
+ }
+
for (core = 0; core < 2; core++) {
b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
- rx2tx_lut_20_11b);
+ rx2tx_lut_20_11b[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
- rx2tx_lut_20_11n);
+ rx2tx_lut_20_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
- rx2tx_lut_20_11n);
+ rx2tx_lut_20_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
}
- b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
}
+
b43_phy_write(dev, 0x32F, 0x3);
+
if (phy->radio_rev == 4 || phy->radio_rev == 6)
b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
@@ -2893,7 +3008,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
0x7f);
}
}
- if (phy->radio_rev == 3) {
+ switch (phy->radio_rev) {
+ case 3:
for (core = 0; core < 2; core++) {
if (core == 0) {
b43_radio_write(dev, 0x64,
@@ -2919,7 +3035,9 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
0x3E);
}
}
- } else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
+ break;
+ case 7:
+ case 8:
if (!b43_is_40mhz(dev)) {
b43_radio_write(dev, 0x5F, 0x14);
b43_radio_write(dev, 0xE8, 0x12);
@@ -2927,6 +3045,21 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_radio_write(dev, 0x5F, 0x16);
b43_radio_write(dev, 0xE8, 0x16);
}
+ break;
+ case 14:
+ for (core = 0; core < 2; core++) {
+ int o = core ? 0x85 : 0;
+
+ b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
+ b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
+ b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
+ b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
+ b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
+ b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
+ b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
+ b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
+ }
+ break;
}
} else {
u16 freq = phy->chandef->chan->center_freq;
@@ -2974,8 +3107,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
- b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
- b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
@@ -2986,20 +3119,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146);
+ b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
+ b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
+ b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
- if (!b43_is_40mhz(dev)) {
- b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
- b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
- } else {
- b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
- b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
- }
+ b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
+ noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+ b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
+
+ b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
+ noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+ b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
b43_nphy_gain_ctl_workarounds(dev);
@@ -4809,41 +4942,61 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
}
}
+static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
+ const s16 *filter)
+{
+ int i;
+
+ offset = B43_PHY_N(offset);
+
+ for (i = 0; i < 15; i++, offset++)
+ b43_phy_write(dev, offset, filter[i]);
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
{
- int i;
- for (i = 0; i < 15; i++)
- b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
- tbl_tx_filter_coef_rev4[2][i]);
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
+ tbl_tx_filter_coef_rev4[2]);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
{
- int i, j;
/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
+ static const s16 dig_filter_phy_rev16[] = {
+ -375, 136, -407, 208, -1527,
+ 956, 93, 186, 93, 230,
+ -44, 230, 201, -191, 201,
+ };
+ int i;
for (i = 0; i < 3; i++)
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[i] + j),
- tbl_tx_filter_coef_rev4[i][j]);
+ b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
+ tbl_tx_filter_coef_rev4[i]);
+
+ /* Verified with BCM43227 and BCM43228 */
+ if (dev->phy.rev == 16)
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+
+ if (dev->dev->chip_id == BCMA_CHIP_ID_BCM43217) {
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
+ tbl_tx_filter_coef_rev4[1]);
+ }
if (b43_is_40mhz(dev)) {
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[3][j]);
- } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[5][j]);
- }
-
- if (dev->phy.channel == 14)
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[6][j]);
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+ tbl_tx_filter_coef_rev4[3]);
+ } else {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+ tbl_tx_filter_coef_rev4[5]);
+ if (dev->phy.channel == 14)
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+ tbl_tx_filter_coef_rev4[6]);
+ }
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 3e48ef5ca53c..1770fa3fc1e6 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1954,6 +1954,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
mmc_remove_host(target);
/* 20ms delay is based on experiment with sdhci controller */
mdelay(20);
+ target->rescan_entered = 0; /* rescan non-removable cards */
mmc_add_host(target);
}
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 2fee852816ee..f0a3d8890760 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -401,6 +401,9 @@ enum {
/* The core spec defines 127 as the "not available" value */
#define HCI_TX_POWER_INVALID 127
+#define HCI_ROLE_MASTER 0x00
+#define HCI_ROLE_SLAVE 0x01
+
/* Extended Inquiry Response field types */
#define EIR_FLAGS 0x01 /* flags */
#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
@@ -1713,9 +1716,6 @@ struct hci_ev_sync_train_complete {
#define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54
-/* Low energy meta events */
-#define LE_CONN_ROLE_MASTER 0x00
-
#define HCI_EV_LE_CONN_COMPLETE 0x01
struct hci_ev_le_conn_complete {
__u8 status;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b52c2ef3f56d..996ed065b6c2 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -83,6 +83,7 @@ struct hci_conn_hash {
unsigned int amp_num;
unsigned int sco_num;
unsigned int le_num;
+ unsigned int le_num_slave;
};
struct bdaddr_list {
@@ -371,6 +372,7 @@ struct hci_conn {
__u16 state;
__u8 mode;
__u8 type;
+ __u8 role;
bool out;
__u8 attempt;
__u8 dev_class[3];
@@ -540,12 +542,12 @@ enum {
HCI_CONN_POWER_SAVE,
HCI_CONN_REMOTE_OOB,
HCI_CONN_FLUSH_KEY,
- HCI_CONN_MASTER,
HCI_CONN_ENCRYPT,
HCI_CONN_AUTH,
HCI_CONN_SECURE,
HCI_CONN_FIPS,
HCI_CONN_STK_ENCRYPT,
+ HCI_CONN_AUTH_INITIATOR,
};
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -575,6 +577,8 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
break;
case LE_LINK:
h->le_num++;
+ if (c->role == HCI_ROLE_SLAVE)
+ h->le_num_slave++;
break;
case SCO_LINK:
case ESCO_LINK:
@@ -599,6 +603,8 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
break;
case LE_LINK:
h->le_num--;
+ if (c->role == HCI_ROLE_SLAVE)
+ h->le_num_slave--;
break;
case SCO_LINK:
case ESCO_LINK:
@@ -695,7 +701,8 @@ void hci_disconnect(struct hci_conn *conn, __u8 reason);
bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
void hci_sco_setup(struct hci_conn *conn, __u8 status);
-struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ u8 role);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
@@ -707,14 +714,15 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u16 conn_timeout,
- bool master);
+ u8 role);
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
u8 sec_level, u8 auth_type);
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u16 setting);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
-int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
+ bool initiator);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
@@ -881,12 +889,12 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
bdaddr_t *bdaddr, u8 *val, u8 type,
u8 pin_len, bool *persistent);
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
- bool master);
+ u8 role);
struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 type, u8 authenticated,
u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, bool master);
+ u8 addr_type, u8 role);
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
void hci_smp_ltks_clear(struct hci_dev *hdev);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 1fffd92808b0..8df15ad0d43f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -905,7 +905,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type);
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
-int l2cap_chan_check_security(struct l2cap_chan *chan);
+int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index bb39509b3f06..016cdb66df6c 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -113,8 +113,9 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
{
bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst;
struct hci_conn *hcon;
+ u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
- hcon = hci_conn_add(hdev, AMP_LINK, dst);
+ hcon = hci_conn_add(hdev, AMP_LINK, dst, role);
if (!hcon)
return NULL;
@@ -125,7 +126,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
hcon->handle = __next_handle(mgr);
hcon->remote_id = remote_id;
hcon->amp_mgr = amp_mgr_get(mgr);
- hcon->out = out;
return hcon;
}
@@ -133,8 +133,8 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
/* AMP crypto key generation interface */
static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
{
- int ret = 0;
struct crypto_shash *tfm;
+ int ret;
if (!ksize)
return -EINVAL;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 490ee8846d9e..b50dabb3f86a 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -66,8 +66,7 @@ static void hci_acl_create_connection(struct hci_conn *conn)
conn->state = BT_CONNECT;
conn->out = true;
-
- set_bit(HCI_CONN_MASTER, &conn->flags);
+ conn->role = HCI_ROLE_MASTER;
conn->attempt++;
@@ -335,7 +334,7 @@ static void hci_conn_timeout(struct work_struct *work)
* event handling and hci_clock_offset_evt function.
*/
if (conn->type == ACL_LINK &&
- test_bit(HCI_CONN_MASTER, &conn->flags)) {
+ conn->role == HCI_ROLE_MASTER) {
struct hci_dev *hdev = conn->hdev;
struct hci_cp_read_clock_offset cp;
@@ -422,13 +421,14 @@ static void le_conn_timeout(struct work_struct *work)
hci_le_create_connection_cancel(conn);
}
-struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ u8 role)
{
struct hci_conn *conn;
BT_DBG("%s dst %pMR", hdev->name, dst);
- conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn)
return NULL;
@@ -436,6 +436,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
bacpy(&conn->src, &hdev->bdaddr);
conn->hdev = hdev;
conn->type = type;
+ conn->role = role;
conn->mode = HCI_CM_ACTIVE;
conn->state = BT_OPEN;
conn->auth_type = HCI_AT_GENERAL_BONDING;
@@ -448,6 +449,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+ if (conn->role == HCI_ROLE_MASTER)
+ conn->out = true;
+
switch (type) {
case ACL_LINK:
conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
@@ -698,7 +702,7 @@ static void hci_req_directed_advertising(struct hci_request *req,
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u16 conn_timeout,
- bool master)
+ u8 role)
{
struct hci_conn_params *params;
struct hci_conn *conn;
@@ -747,7 +751,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
dst_type = ADDR_LE_DEV_RANDOM;
}
- conn = hci_conn_add(hdev, LE_LINK, dst);
+ conn = hci_conn_add(hdev, LE_LINK, dst, role);
if (!conn)
return ERR_PTR(-ENOMEM);
@@ -771,7 +775,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
}
/* If requested to connect as slave use directed advertising */
- if (!master) {
+ if (conn->role == HCI_ROLE_SLAVE) {
/* If we're active scanning most controllers are unable
* to initiate advertising. Simply reject the attempt.
*/
@@ -786,9 +790,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
goto create_conn;
}
- conn->out = true;
- set_bit(HCI_CONN_MASTER, &conn->flags);
-
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) {
conn->le_conn_min_interval = params->conn_min_interval;
@@ -833,11 +834,11 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
struct hci_conn *acl;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
- return ERR_PTR(-ENOTSUPP);
+ return ERR_PTR(-EOPNOTSUPP);
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
- acl = hci_conn_add(hdev, ACL_LINK, dst);
+ acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
if (!acl)
return ERR_PTR(-ENOMEM);
}
@@ -866,7 +867,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
if (!sco) {
- sco = hci_conn_add(hdev, type, dst);
+ sco = hci_conn_add(hdev, type, dst, HCI_ROLE_MASTER);
if (!sco) {
hci_conn_drop(acl);
return ERR_PTR(-ENOMEM);
@@ -972,7 +973,8 @@ static void hci_conn_encrypt(struct hci_conn *conn)
}
/* Enable security */
-int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
+ bool initiator)
{
BT_DBG("hcon %p", conn);
@@ -1025,6 +1027,9 @@ auth:
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
return 0;
+ if (initiator)
+ set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
+
if (!hci_conn_auth(conn, sec_level, auth_type))
return 0;
@@ -1076,7 +1081,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
{
BT_DBG("hcon %p", conn);
- if (!role && test_bit(HCI_CONN_MASTER, &conn->flags))
+ if (role == conn->role)
return 1;
if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) {
@@ -1151,7 +1156,7 @@ static u32 get_link_mode(struct hci_conn *conn)
{
u32 link_mode = 0;
- if (test_bit(HCI_CONN_MASTER, &conn->flags))
+ if (conn->role == HCI_ROLE_MASTER)
link_mode |= HCI_LM_MASTER;
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
@@ -1277,7 +1282,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
BT_DBG("%s hcon %p", hdev->name, conn);
- chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL);
+ chan = kzalloc(sizeof(*chan), GFP_KERNEL);
if (!chan)
return NULL;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 172041e2b15a..cfcb6055ced8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2088,7 +2088,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
}
/* Entry not in the cache. Add new one. */
- ie = kzalloc(sizeof(struct inquiry_entry), GFP_KERNEL);
+ ie = kzalloc(sizeof(*ie), GFP_KERNEL);
if (!ie) {
flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
goto done;
@@ -3121,13 +3121,16 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
return false;
}
-static bool ltk_type_master(u8 type)
+static u8 ltk_role(u8 type)
{
- return (type == SMP_LTK);
+ if (type == SMP_LTK)
+ return HCI_ROLE_MASTER;
+
+ return HCI_ROLE_SLAVE;
}
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
- bool master)
+ u8 role)
{
struct smp_ltk *k;
@@ -3135,7 +3138,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
if (k->ediv != ediv || k->rand != rand)
continue;
- if (ltk_type_master(k->type) != master)
+ if (ltk_role(k->type) != role)
continue;
return k;
@@ -3145,14 +3148,14 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
}
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, bool master)
+ u8 addr_type, u8 role)
{
struct smp_ltk *k;
list_for_each_entry(k, &hdev->long_term_keys, list)
if (addr_type == k->bdaddr_type &&
bacmp(bdaddr, &k->bdaddr) == 0 &&
- ltk_type_master(k->type) == master)
+ ltk_role(k->type) == role)
return k;
return NULL;
@@ -3247,9 +3250,9 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand)
{
struct smp_ltk *key, *old_key;
- bool master = ltk_type_master(type);
+ u8 role = ltk_role(type);
- old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, master);
+ old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role);
if (old_key)
key = old_key;
else {
@@ -3489,7 +3492,7 @@ int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type)
if (hci_bdaddr_list_lookup(list, bdaddr, type))
return -EEXIST;
- entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
@@ -3894,7 +3897,7 @@ struct hci_dev *hci_alloc_dev(void)
{
struct hci_dev *hdev;
- hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL);
+ hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
if (!hdev)
return NULL;
@@ -5462,8 +5465,7 @@ void hci_update_background_scan(struct hci_dev *hdev)
hci_req_init(&req, hdev);
- if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) &&
- list_empty(&hdev->pend_le_conns) &&
+ if (list_empty(&hdev->pend_le_conns) &&
list_empty(&hdev->pend_le_reports)) {
/* If there is no pending LE connections or devices
* to be scanned for, we should stop the background
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8980bd24b8c0..4c41774aa556 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -101,12 +101,8 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
- if (conn) {
- if (rp->role)
- clear_bit(HCI_CONN_MASTER, &conn->flags);
- else
- set_bit(HCI_CONN_MASTER, &conn->flags);
- }
+ if (conn)
+ conn->role = rp->role;
hci_dev_unlock(hdev);
}
@@ -1418,11 +1414,9 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
}
} else {
if (!conn) {
- conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
- if (conn) {
- conn->out = true;
- set_bit(HCI_CONN_MASTER, &conn->flags);
- } else
+ conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
+ HCI_ROLE_MASTER);
+ if (!conn)
BT_ERR("No memory for new connection");
}
}
@@ -1651,6 +1645,8 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
struct hci_cp_auth_requested auth_cp;
+ set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
+
auth_cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
sizeof(auth_cp), &auth_cp);
@@ -2135,18 +2131,17 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
return;
}
- if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
- if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
- BDADDR_BREDR)) {
- hci_reject_conn(hdev, &ev->bdaddr);
- return;
- }
- } else {
- if (!hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
- BDADDR_BREDR)) {
- hci_reject_conn(hdev, &ev->bdaddr);
- return;
- }
+ if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
+ BDADDR_BREDR)) {
+ hci_reject_conn(hdev, &ev->bdaddr);
+ return;
+ }
+
+ if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) &&
+ !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
+ BDADDR_BREDR)) {
+ hci_reject_conn(hdev, &ev->bdaddr);
+ return;
}
/* Connection accepted */
@@ -2160,7 +2155,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
&ev->bdaddr);
if (!conn) {
- conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
+ conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
+ HCI_ROLE_SLAVE);
if (!conn) {
BT_ERR("No memory for new connection");
hci_dev_unlock(hdev);
@@ -2393,6 +2389,9 @@ check_auth:
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
struct hci_cp_auth_requested cp;
+
+ set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
+
cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
@@ -2924,12 +2923,8 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
- if (!ev->status) {
- if (ev->role)
- clear_bit(HCI_CONN_MASTER, &conn->flags);
- else
- set_bit(HCI_CONN_MASTER, &conn->flags);
- }
+ if (!ev->status)
+ conn->role = ev->role;
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
@@ -3123,10 +3118,11 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_conn_drop(conn);
}
- if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
+ if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags) &&
+ !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
sizeof(ev->bdaddr), &ev->bdaddr);
- else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
+ } else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
u8 secure;
if (conn->pending_sec_level == BT_SECURITY_HIGH)
@@ -3652,7 +3648,11 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
goto unlock;
+ /* Allow pairing if we're pairable, the initiators of the
+ * pairing or if the remote is not requesting bonding.
+ */
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
+ test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
struct hci_cp_io_capability_reply cp;
@@ -3668,7 +3668,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
* except for the no-bonding case.
*/
if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
- cp.authentication != HCI_AT_NO_BONDING)
+ conn->auth_type != HCI_AT_NO_BONDING)
conn->auth_type |= 0x01;
cp.authentication = conn->auth_type;
@@ -3762,9 +3762,11 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
/* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with
* confirm_hint set to 1). The exception is if neither
- * side had MITM in which case we do auto-accept.
+ * side had MITM or if the local IO capability is
+ * NoInputNoOutput, in which case we do auto-accept
*/
if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
+ conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
(loc_mitm || rem_mitm)) {
BT_DBG("Confirming auto-accept as acceptor");
confirm_hint = 1;
@@ -3878,6 +3880,9 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
if (!conn)
goto unlock;
+ /* Reset the authentication requirement to unknown */
+ conn->remote_auth = 0xff;
+
/* To avoid duplicate auth_failed events to user space we check
* the HCI_CONN_AUTH_PEND flag which will be set if we
* initiated the authentication. A traditional auth_complete
@@ -4108,7 +4113,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
if (!conn) {
- conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
+ conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role);
if (!conn) {
BT_ERR("No memory for new connection");
goto unlock;
@@ -4116,11 +4121,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->dst_type = ev->bdaddr_type;
- if (ev->role == LE_CONN_ROLE_MASTER) {
- conn->out = true;
- set_bit(HCI_CONN_MASTER, &conn->flags);
- }
-
/* If we didn't have a hci_conn object previously
* but we're in master role this must be something
* initiated using a white list. Since white list based
@@ -4187,14 +4187,14 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
else
addr_type = BDADDR_LE_RANDOM;
- /* Drop the connection if he device is blocked */
- if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
- hci_conn_drop(conn);
+ if (ev->status) {
+ hci_le_conn_failed(conn, ev->status);
goto unlock;
}
- if (ev->status) {
- hci_le_conn_failed(conn, ev->status);
+ /* Drop the connection if the device is blocked */
+ if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
+ hci_conn_drop(conn);
goto unlock;
}
@@ -4260,6 +4260,12 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
return;
+ /* Most controller will fail if we try to create new connections
+ * while we have an existing one in slave role.
+ */
+ if (hdev->conn_hash.le_num_slave > 0)
+ return;
+
/* If we're connectable, always connect any ADV_DIRECT_IND event */
if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) &&
adv_type == LE_ADV_DIRECT_IND)
@@ -4272,9 +4278,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
return;
connect:
- /* Request connection in master = true role */
conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
- HCI_LE_AUTOCONN_TIMEOUT, true);
+ HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
if (!IS_ERR(conn))
return;
@@ -4314,14 +4319,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
* device found events.
*/
if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
- struct hci_conn_params *param;
-
if (type == LE_ADV_DIRECT_IND)
return;
- param = hci_pend_le_action_lookup(&hdev->pend_le_reports,
- bdaddr, bdaddr_type);
- if (!param)
+ if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
+ bdaddr, bdaddr_type))
return;
if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
@@ -4455,7 +4457,7 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn == NULL)
goto not_found;
- ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out);
+ ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
if (ltk == NULL)
goto not_found;
@@ -4530,7 +4532,7 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_INVALID_LL_PARAMS);
- if (test_bit(HCI_CONN_MASTER, &hcon->flags)) {
+ if (hcon->role == HCI_ROLE_MASTER) {
struct hci_conn_params *params;
u8 store_hint;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8538cb07b0c0..46547b920f88 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -775,7 +775,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
}
/* Service level security */
-int l2cap_chan_check_security(struct l2cap_chan *chan)
+int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
{
struct l2cap_conn *conn = chan->conn;
__u8 auth_type;
@@ -785,7 +785,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan)
auth_type = l2cap_get_auth_type(chan);
- return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
+ return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
+ initiator);
}
static u8 l2cap_get_ident(struct l2cap_conn *conn)
@@ -1278,7 +1279,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
return;
- if (l2cap_chan_check_security(chan) &&
+ if (l2cap_chan_check_security(chan, true) &&
__l2cap_no_conn_pending(chan)) {
l2cap_start_connection(chan);
}
@@ -1357,7 +1358,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
if (chan->state == BT_CONNECT) {
- if (!l2cap_chan_check_security(chan) ||
+ if (!l2cap_chan_check_security(chan, true) ||
!__l2cap_no_conn_pending(chan)) {
l2cap_chan_unlock(chan);
continue;
@@ -1379,7 +1380,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
- if (l2cap_chan_check_security(chan)) {
+ if (l2cap_chan_check_security(chan, false)) {
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
rsp.result = cpu_to_le16(L2CAP_CR_PEND);
rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
@@ -1487,7 +1488,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
* been configured for this connection. If not, then trigger
* the connection update procedure.
*/
- if (!test_bit(HCI_CONN_MASTER, &hcon->flags) &&
+ if (hcon->role == HCI_ROLE_SLAVE &&
(hcon->le_conn_interval < hcon->le_conn_min_interval ||
hcon->le_conn_interval > hcon->le_conn_max_interval)) {
struct l2cap_conn_param_update_req req;
@@ -3849,7 +3850,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
chan->ident = cmd->ident;
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
- if (l2cap_chan_check_security(chan)) {
+ if (l2cap_chan_check_security(chan, false)) {
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
@@ -5227,7 +5228,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
u16 min, max, latency, to_multiplier;
int err;
- if (!test_bit(HCI_CONN_MASTER, &hcon->flags))
+ if (hcon->role != HCI_ROLE_MASTER)
return -EINVAL;
if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
@@ -6984,7 +6985,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
if (!hchan)
return NULL;
- conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn) {
hci_chan_del(hchan);
return NULL;
@@ -7093,7 +7094,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
break;
/* fall through */
default:
- err = -ENOTSUPP;
+ err = -EOPNOTSUPP;
goto done;
}
@@ -7128,7 +7129,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
chan->dcid = cid;
if (bdaddr_type_is_le(dst_type)) {
- bool master;
+ u8 role;
/* Convert from L2CAP channel address type to HCI address type
*/
@@ -7137,10 +7138,13 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
else
dst_type = ADDR_LE_DEV_RANDOM;
- master = !test_bit(HCI_ADVERTISING, &hdev->dev_flags);
+ if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
+ role = HCI_ROLE_SLAVE;
+ else
+ role = HCI_ROLE_MASTER;
hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level,
- HCI_LE_CONN_TIMEOUT, master);
+ HCI_LE_CONN_TIMEOUT, role);
} else {
u8 auth_type = l2cap_get_auth_type(chan);
hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
@@ -7188,7 +7192,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
if (hcon->state == BT_CONNECTED) {
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
__clear_chan_timer(chan);
- if (l2cap_chan_check_security(chan))
+ if (l2cap_chan_check_security(chan, true))
l2cap_state_change(chan, BT_CONNECTED);
} else
l2cap_do_start(chan);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 9bb4d1b3a483..1884f72083c2 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -279,7 +279,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
break;
/* fall through */
default:
- err = -ENOTSUPP;
+ err = -EOPNOTSUPP;
goto done;
}
@@ -797,7 +797,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
} else if ((sk->sk_state == BT_CONNECT2 &&
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
sk->sk_state == BT_CONNECTED) {
- if (!l2cap_chan_check_security(chan))
+ if (!l2cap_chan_check_security(chan, true))
set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
else
sk->sk_state_change(sk);
@@ -1112,7 +1112,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
l2cap_chan_close(chan, 0);
lock_sock(sk);
- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+ !(current->flags & PF_EXITING))
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7703b72653ff..190668367e42 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3154,9 +3154,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
*/
hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
- /* Request a connection with master = true role */
conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
- sec_level, HCI_LE_CONN_TIMEOUT, true);
+ sec_level, HCI_LE_CONN_TIMEOUT,
+ HCI_ROLE_MASTER);
}
if (IS_ERR(conn)) {
@@ -3202,7 +3202,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
cmd->user_data = conn;
if (conn->state == BT_CONNECTED &&
- hci_conn_security(conn, sec_level, auth_type))
+ hci_conn_security(conn, sec_level, auth_type, true))
pairing_complete(cmd, 0);
err = 0;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 754b6fe4f742..a0690a84f3e9 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -227,7 +227,8 @@ static int rfcomm_check_security(struct rfcomm_dlc *d)
break;
}
- return hci_conn_security(conn->hcon, d->sec_level, auth_type);
+ return hci_conn_security(conn->hcon, d->sec_level, auth_type,
+ d->out);
}
static void rfcomm_session_timeout(unsigned long arg)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index c603a5eb4720..8bbbb5ec468c 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -918,7 +918,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how)
sk->sk_shutdown = SHUTDOWN_MASK;
__rfcomm_sock_close(sk);
- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+ !(current->flags & PF_EXITING))
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
}
release_sock(sk);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index ebf7ee6a446c..7ee9e4ab00f8 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -970,7 +970,8 @@ static int sco_sock_shutdown(struct socket *sock, int how)
sco_sock_clear_timer(sk);
__sco_sock_close(sk);
- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+ !(current->flags & PF_EXITING))
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
}
@@ -990,7 +991,8 @@ static int sco_sock_release(struct socket *sock)
sco_sock_close(sk);
- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
+ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+ !(current->flags & PF_EXITING)) {
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
release_sock(sk);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 8339d6b0f2b8..e49c83d8b957 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -431,6 +431,10 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
method = JUST_WORKS;
+ /* Don't bother user space with no IO capabilities */
+ if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
+ method = JUST_WORKS;
+
/* If Just Works, Continue with Zero TK */
if (method == JUST_WORKS) {
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
@@ -445,7 +449,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
* Confirms and the slave Enters the passkey.
*/
if (method == OVERLAP) {
- if (test_bit(HCI_CONN_MASTER, &hcon->flags))
+ if (hcon->role == HCI_ROLE_MASTER)
method = CFM_PASSKEY;
else
method = REQ_PASSKEY;
@@ -686,7 +690,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*req))
return SMP_INVALID_PARAMS;
- if (test_bit(HCI_CONN_MASTER, &conn->hcon->flags))
+ if (conn->hcon->role != HCI_ROLE_SLAVE)
return SMP_CMD_NOTSUPP;
if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
@@ -755,7 +759,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*rsp))
return SMP_INVALID_PARAMS;
- if (!test_bit(HCI_CONN_MASTER, &conn->hcon->flags))
+ if (conn->hcon->role != HCI_ROLE_MASTER)
return SMP_CMD_NOTSUPP;
skb_pull(skb, sizeof(*rsp));
@@ -849,7 +853,7 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
struct hci_conn *hcon = conn->hcon;
key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
- hcon->out);
+ hcon->role);
if (!key)
return false;
@@ -881,7 +885,7 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
*/
if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
- hcon->out))
+ hcon->role))
return false;
if (hcon->sec_level >= sec_level)
@@ -903,7 +907,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*rp))
return SMP_INVALID_PARAMS;
- if (!test_bit(HCI_CONN_MASTER, &conn->hcon->flags))
+ if (hcon->role != HCI_ROLE_MASTER)
return SMP_CMD_NOTSUPP;
sec_level = authreq_to_seclevel(rp->auth_req);
@@ -961,7 +965,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
if (sec_level > hcon->pending_sec_level)
hcon->pending_sec_level = sec_level;
- if (test_bit(HCI_CONN_MASTER, &hcon->flags))
+ if (hcon->role == HCI_ROLE_MASTER)
if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
return 0;
@@ -981,7 +985,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
hcon->pending_sec_level > BT_SECURITY_MEDIUM)
authreq |= SMP_AUTH_MITM;
- if (test_bit(HCI_CONN_MASTER, &hcon->flags)) {
+ if (hcon->role == HCI_ROLE_MASTER) {
struct smp_cmd_pairing cp;
build_pairing_cmd(conn, &cp, NULL, authreq);
@@ -1185,7 +1189,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
}
if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
- err = -ENOTSUPP;
+ err = -EOPNOTSUPP;
reason = SMP_PAIRING_NOTSUPP;
goto done;
}
@@ -1203,7 +1207,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
!conn->smp_chan) {
BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
kfree_skb(skb);
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
}
switch (code) {