You've already forked linux-t2-patches
mirror of
https://github.com/t2linux/linux-t2-patches.git
synced 2026-04-30 13:52:11 -07:00
1391 lines
47 KiB
Diff
1391 lines
47 KiB
Diff
From ed1538275a45a22dbabf3a72551a4f1c34322bbb Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:14 +0900
|
|
Subject: [PATCH 01/10] brcmfmac: chip: Only disable D11 cores; handle an
|
|
arbitrary number
|
|
|
|
At least on BCM4387, the D11 cores are held in reset on cold startup and
|
|
firmware expects to release reset itself. Just assert reset here and let
|
|
firmware deassert it. Premature deassertion results in the firmware
|
|
failing to initialize properly some of the time, with strange AXI bus
|
|
errors.
|
|
|
|
Also, BCM4387 has 3 cores, up from 2. The logic for handling that is in
|
|
brcmf_chip_ai_resetcore(), but since we aren't using that any more, just
|
|
handle it here.
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 13 ++++++++-----
|
|
1 file changed, 8 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
index 8073f31be..a62390514 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
@@ -1292,15 +1292,18 @@ static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)
|
|
static inline void
|
|
brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
|
|
{
|
|
+ int i;
|
|
struct brcmf_core *core;
|
|
|
|
brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
|
|
|
|
- core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
|
|
- brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
|
|
- D11_BCMA_IOCTL_PHYCLOCKEN,
|
|
- D11_BCMA_IOCTL_PHYCLOCKEN,
|
|
- D11_BCMA_IOCTL_PHYCLOCKEN);
|
|
+ /* Disable the cores only and let the firmware enable them.
|
|
+ * Releasing reset ourselves breaks BCM4387 in weird ways.
|
|
+ */
|
|
+ for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++)
|
|
+ brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET |
|
|
+ D11_BCMA_IOCTL_PHYCLOCKEN,
|
|
+ D11_BCMA_IOCTL_PHYCLOCKEN);
|
|
}
|
|
|
|
static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From 92e6da67e2aa52030bd5a1a03012586615ad1c53 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:15 +0900
|
|
Subject: [PATCH 02/10] brcmfmac: chip: Handle 1024-unit sizes for TCM blocks
|
|
|
|
BCM4387 has trailing odd-sized blocks as part of TCM which have
|
|
their size described as a multiple of 1024 instead of 8192. Handle this
|
|
so we can compute the TCM size properly.
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 10 ++++++++--
|
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
index a62390514..50e0c015c 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
@@ -212,8 +212,9 @@ struct sbsocramregs {
|
|
#define ARMCR4_TCBANB_MASK 0xf
|
|
#define ARMCR4_TCBANB_SHIFT 0
|
|
|
|
-#define ARMCR4_BSZ_MASK 0x3f
|
|
+#define ARMCR4_BSZ_MASK 0x7f
|
|
#define ARMCR4_BSZ_MULT 8192
|
|
+#define ARMCR4_BLK_1K_MASK 0x200
|
|
|
|
struct brcmf_core_priv {
|
|
struct brcmf_core pub;
|
|
@@ -684,6 +685,7 @@ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
|
|
u32 nbb;
|
|
u32 totb;
|
|
u32 bxinfo;
|
|
+ u32 blksize;
|
|
u32 idx;
|
|
|
|
corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);
|
|
@@ -695,7 +697,11 @@ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
|
|
for (idx = 0; idx < totb; idx++) {
|
|
brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);
|
|
bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);
|
|
- memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
|
|
+ blksize = ARMCR4_BSZ_MULT;
|
|
+ if (bxinfo & ARMCR4_BLK_1K_MASK)
|
|
+ blksize >>= 3;
|
|
+
|
|
+ memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * blksize;
|
|
}
|
|
|
|
return memsize;
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From 214d9c113cb9a46ba6fea5edb53cecdc4d675749 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:16 +0900
|
|
Subject: [PATCH 03/10] brcmfmac: cfg80211: Add support for scan params v2
|
|
|
|
This new API version is required for at least the BCM4387 firmware. Add
|
|
support for it, with a fallback to the v1 API.
|
|
|
|
Acked-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 245 +++++++++++-------
|
|
.../broadcom/brcm80211/brcmfmac/feature.c | 1 +
|
|
.../broadcom/brcm80211/brcmfmac/feature.h | 4 +-
|
|
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 49 +++-
|
|
4 files changed, 209 insertions(+), 90 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
index b115902eb..aa7e78cd5 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
@@ -1039,12 +1039,134 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
|
|
}
|
|
}
|
|
|
|
+static void brcmf_scan_params_v2_to_v1(struct brcmf_scan_params_v2_le *params_v2_le,
|
|
+ struct brcmf_scan_params_le *params_le)
|
|
+{
|
|
+ size_t params_size;
|
|
+ u32 ch;
|
|
+ int n_channels, n_ssids;
|
|
+
|
|
+ memcpy(¶ms_le->ssid_le, ¶ms_v2_le->ssid_le,
|
|
+ sizeof(params_le->ssid_le));
|
|
+ memcpy(¶ms_le->bssid, ¶ms_v2_le->bssid,
|
|
+ sizeof(params_le->bssid));
|
|
+
|
|
+ params_le->bss_type = params_v2_le->bss_type;
|
|
+ params_le->scan_type = le32_to_cpu(params_v2_le->scan_type);
|
|
+ params_le->nprobes = params_v2_le->nprobes;
|
|
+ params_le->active_time = params_v2_le->active_time;
|
|
+ params_le->passive_time = params_v2_le->passive_time;
|
|
+ params_le->home_time = params_v2_le->home_time;
|
|
+ params_le->channel_num = params_v2_le->channel_num;
|
|
+
|
|
+ ch = le32_to_cpu(params_v2_le->channel_num);
|
|
+ n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK;
|
|
+ n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT;
|
|
+
|
|
+ params_size = sizeof(u16) * n_channels;
|
|
+ if (n_ssids > 0) {
|
|
+ params_size = roundup(params_size, sizeof(u32));
|
|
+ params_size += sizeof(struct brcmf_ssid_le) * n_ssids;
|
|
+ }
|
|
+
|
|
+ memcpy(¶ms_le->channel_list[0],
|
|
+ ¶ms_v2_le->channel_list[0], params_size);
|
|
+}
|
|
+
|
|
+static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
|
|
+ struct brcmf_scan_params_v2_le *params_le,
|
|
+ struct cfg80211_scan_request *request)
|
|
+{
|
|
+ u32 n_ssids;
|
|
+ u32 n_channels;
|
|
+ s32 i;
|
|
+ s32 offset;
|
|
+ u16 chanspec;
|
|
+ char *ptr;
|
|
+ int length;
|
|
+ struct brcmf_ssid_le ssid_le;
|
|
+
|
|
+ eth_broadcast_addr(params_le->bssid);
|
|
+
|
|
+ length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
|
|
+
|
|
+ params_le->version = cpu_to_le16(BRCMF_SCAN_PARAMS_VERSION_V2);
|
|
+ params_le->bss_type = DOT11_BSSTYPE_ANY;
|
|
+ params_le->scan_type = cpu_to_le32(BRCMF_SCANTYPE_ACTIVE);
|
|
+ params_le->channel_num = 0;
|
|
+ params_le->nprobes = cpu_to_le32(-1);
|
|
+ params_le->active_time = cpu_to_le32(-1);
|
|
+ params_le->passive_time = cpu_to_le32(-1);
|
|
+ params_le->home_time = cpu_to_le32(-1);
|
|
+ memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le));
|
|
+
|
|
+ /* Scan abort */
|
|
+ if (!request) {
|
|
+ length += sizeof(u16);
|
|
+ params_le->channel_num = cpu_to_le32(1);
|
|
+ params_le->channel_list[0] = cpu_to_le16(-1);
|
|
+ params_le->length = cpu_to_le16(length);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ n_ssids = request->n_ssids;
|
|
+ n_channels = request->n_channels;
|
|
+
|
|
+ /* Copy channel array if applicable */
|
|
+ brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
|
|
+ n_channels);
|
|
+ if (n_channels > 0) {
|
|
+ length += roundup(sizeof(u16) * n_channels, sizeof(u32));
|
|
+ for (i = 0; i < n_channels; i++) {
|
|
+ chanspec = channel_to_chanspec(&cfg->d11inf,
|
|
+ request->channels[i]);
|
|
+ brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
|
|
+ request->channels[i]->hw_value, chanspec);
|
|
+ params_le->channel_list[i] = cpu_to_le16(chanspec);
|
|
+ }
|
|
+ } else {
|
|
+ brcmf_dbg(SCAN, "Scanning all channels\n");
|
|
+ }
|
|
+
|
|
+ /* Copy ssid array if applicable */
|
|
+ brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
|
|
+ if (n_ssids > 0) {
|
|
+ offset = offsetof(struct brcmf_scan_params_v2_le, channel_list) +
|
|
+ n_channels * sizeof(u16);
|
|
+ offset = roundup(offset, sizeof(u32));
|
|
+ length += sizeof(ssid_le) * n_ssids,
|
|
+ ptr = (char *)params_le + offset;
|
|
+ for (i = 0; i < n_ssids; i++) {
|
|
+ memset(&ssid_le, 0, sizeof(ssid_le));
|
|
+ ssid_le.SSID_len =
|
|
+ cpu_to_le32(request->ssids[i].ssid_len);
|
|
+ memcpy(ssid_le.SSID, request->ssids[i].ssid,
|
|
+ request->ssids[i].ssid_len);
|
|
+ if (!ssid_le.SSID_len)
|
|
+ brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
|
|
+ else
|
|
+ brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
|
|
+ i, ssid_le.SSID, ssid_le.SSID_len);
|
|
+ memcpy(ptr, &ssid_le, sizeof(ssid_le));
|
|
+ ptr += sizeof(ssid_le);
|
|
+ }
|
|
+ } else {
|
|
+ brcmf_dbg(SCAN, "Performing passive scan\n");
|
|
+ params_le->scan_type = cpu_to_le32(BRCMF_SCANTYPE_PASSIVE);
|
|
+ }
|
|
+ params_le->length = cpu_to_le16(length);
|
|
+ /* Adding mask to channel numbers */
|
|
+ params_le->channel_num =
|
|
+ cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
|
|
+ (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
|
|
+}
|
|
+
|
|
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
|
struct brcmf_if *ifp, bool aborted,
|
|
bool fw_abort)
|
|
{
|
|
struct brcmf_pub *drvr = cfg->pub;
|
|
- struct brcmf_scan_params_le params_le;
|
|
+ struct brcmf_scan_params_v2_le params_v2_le;
|
|
struct cfg80211_scan_request *scan_request;
|
|
u64 reqid;
|
|
u32 bucket;
|
|
@@ -1063,20 +1185,23 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
|
if (fw_abort) {
|
|
/* Do a scan abort to stop the driver's scan engine */
|
|
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
|
|
- memset(¶ms_le, 0, sizeof(params_le));
|
|
- eth_broadcast_addr(params_le.bssid);
|
|
- params_le.bss_type = DOT11_BSSTYPE_ANY;
|
|
- params_le.scan_type = 0;
|
|
- params_le.channel_num = cpu_to_le32(1);
|
|
- params_le.nprobes = cpu_to_le32(1);
|
|
- params_le.active_time = cpu_to_le32(-1);
|
|
- params_le.passive_time = cpu_to_le32(-1);
|
|
- params_le.home_time = cpu_to_le32(-1);
|
|
- /* Scan is aborted by setting channel_list[0] to -1 */
|
|
- params_le.channel_list[0] = cpu_to_le16(-1);
|
|
+
|
|
+ brcmf_escan_prep(cfg, ¶ms_v2_le, NULL);
|
|
+
|
|
/* E-Scan (or anyother type) can be aborted by SCAN */
|
|
- err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
|
- ¶ms_le, sizeof(params_le));
|
|
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
|
|
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
|
+ ¶ms_v2_le,
|
|
+ sizeof(params_v2_le));
|
|
+ } else {
|
|
+ struct brcmf_scan_params_le params_le;
|
|
+
|
|
+ brcmf_scan_params_v2_to_v1(¶ms_v2_le, ¶ms_le);
|
|
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
|
+ ¶ms_le,
|
|
+ sizeof(params_le));
|
|
+ }
|
|
+
|
|
if (err)
|
|
bphy_err(drvr, "Scan abort failed\n");
|
|
}
|
|
@@ -1295,83 +1420,13 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
|
|
return err;
|
|
}
|
|
|
|
-static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
|
|
- struct brcmf_scan_params_le *params_le,
|
|
- struct cfg80211_scan_request *request)
|
|
-{
|
|
- u32 n_ssids;
|
|
- u32 n_channels;
|
|
- s32 i;
|
|
- s32 offset;
|
|
- u16 chanspec;
|
|
- char *ptr;
|
|
- struct brcmf_ssid_le ssid_le;
|
|
-
|
|
- eth_broadcast_addr(params_le->bssid);
|
|
- params_le->bss_type = DOT11_BSSTYPE_ANY;
|
|
- params_le->scan_type = BRCMF_SCANTYPE_ACTIVE;
|
|
- params_le->channel_num = 0;
|
|
- params_le->nprobes = cpu_to_le32(-1);
|
|
- params_le->active_time = cpu_to_le32(-1);
|
|
- params_le->passive_time = cpu_to_le32(-1);
|
|
- params_le->home_time = cpu_to_le32(-1);
|
|
- memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le));
|
|
-
|
|
- n_ssids = request->n_ssids;
|
|
- n_channels = request->n_channels;
|
|
-
|
|
- /* Copy channel array if applicable */
|
|
- brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
|
|
- n_channels);
|
|
- if (n_channels > 0) {
|
|
- for (i = 0; i < n_channels; i++) {
|
|
- chanspec = channel_to_chanspec(&cfg->d11inf,
|
|
- request->channels[i]);
|
|
- brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
|
|
- request->channels[i]->hw_value, chanspec);
|
|
- params_le->channel_list[i] = cpu_to_le16(chanspec);
|
|
- }
|
|
- } else {
|
|
- brcmf_dbg(SCAN, "Scanning all channels\n");
|
|
- }
|
|
- /* Copy ssid array if applicable */
|
|
- brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
|
|
- if (n_ssids > 0) {
|
|
- offset = offsetof(struct brcmf_scan_params_le, channel_list) +
|
|
- n_channels * sizeof(u16);
|
|
- offset = roundup(offset, sizeof(u32));
|
|
- ptr = (char *)params_le + offset;
|
|
- for (i = 0; i < n_ssids; i++) {
|
|
- memset(&ssid_le, 0, sizeof(ssid_le));
|
|
- ssid_le.SSID_len =
|
|
- cpu_to_le32(request->ssids[i].ssid_len);
|
|
- memcpy(ssid_le.SSID, request->ssids[i].ssid,
|
|
- request->ssids[i].ssid_len);
|
|
- if (!ssid_le.SSID_len)
|
|
- brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
|
|
- else
|
|
- brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
|
|
- i, ssid_le.SSID, ssid_le.SSID_len);
|
|
- memcpy(ptr, &ssid_le, sizeof(ssid_le));
|
|
- ptr += sizeof(ssid_le);
|
|
- }
|
|
- } else {
|
|
- brcmf_dbg(SCAN, "Performing passive scan\n");
|
|
- params_le->scan_type = BRCMF_SCANTYPE_PASSIVE;
|
|
- }
|
|
- /* Adding mask to channel numbers */
|
|
- params_le->channel_num =
|
|
- cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
|
|
- (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
|
|
-}
|
|
-
|
|
static s32
|
|
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
|
struct cfg80211_scan_request *request)
|
|
{
|
|
struct brcmf_pub *drvr = cfg->pub;
|
|
- s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
|
|
- offsetof(struct brcmf_escan_params_le, params_le);
|
|
+ s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
|
|
+ offsetof(struct brcmf_escan_params_le, params_v2_le);
|
|
struct brcmf_escan_params_le *params;
|
|
s32 err = 0;
|
|
|
|
@@ -1391,8 +1446,22 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
|
goto exit;
|
|
}
|
|
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
|
|
- brcmf_escan_prep(cfg, ¶ms->params_le, request);
|
|
- params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
|
|
+ brcmf_escan_prep(cfg, ¶ms->params_v2_le, request);
|
|
+
|
|
+ params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V2);
|
|
+
|
|
+ if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
|
|
+ struct brcmf_escan_params_le *params_v1;
|
|
+
|
|
+ params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
|
|
+ params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
|
|
+ params_v1 = kzalloc(params_size, GFP_KERNEL);
|
|
+ params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
|
|
+ brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le);
|
|
+ kfree(params);
|
|
+ params = params_v1;
|
|
+ }
|
|
+
|
|
params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
|
|
params->sync_id = cpu_to_le16(0x1234);
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
index 10bac865d..b6797f800 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
@@ -290,6 +290,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|
ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
|
|
|
|
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
|
|
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_SCAN_V2, "scan_ver");
|
|
|
|
if (drvr->settings->feature_disable) {
|
|
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
|
|
index f1b086a69..549298c55 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
|
|
@@ -30,6 +30,7 @@
|
|
* SAE: simultaneous authentication of equals
|
|
* FWAUTH: Firmware authenticator
|
|
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
|
|
+ * SCAN_V2: Version 2 scan params
|
|
*/
|
|
#define BRCMF_FEAT_LIST \
|
|
BRCMF_FEAT_DEF(MBSS) \
|
|
@@ -53,7 +54,8 @@
|
|
BRCMF_FEAT_DEF(DOT11H) \
|
|
BRCMF_FEAT_DEF(SAE) \
|
|
BRCMF_FEAT_DEF(FWAUTH) \
|
|
- BRCMF_FEAT_DEF(DUMP_OBSS)
|
|
+ BRCMF_FEAT_DEF(DUMP_OBSS) \
|
|
+ BRCMF_FEAT_DEF(SCAN_V2)
|
|
|
|
/*
|
|
* Quirks:
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
index 04e1beedf..b3844d0d1 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
@@ -48,6 +48,10 @@
|
|
|
|
/* size of brcmf_scan_params not including variable length array */
|
|
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
|
+#define BRCMF_SCAN_PARAMS_V2_FIXED_SIZE 72
|
|
+
|
|
+/* version of brcmf_scan_params structure */
|
|
+#define BRCMF_SCAN_PARAMS_VERSION_V2 2
|
|
|
|
/* masks for channel and ssid count */
|
|
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
|
|
@@ -67,6 +71,7 @@
|
|
#define BRCMF_PRIMARY_KEY (1 << 1)
|
|
#define DOT11_BSSTYPE_ANY 2
|
|
#define BRCMF_ESCAN_REQ_VERSION 1
|
|
+#define BRCMF_ESCAN_REQ_VERSION_V2 2
|
|
|
|
#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
|
|
|
|
@@ -386,6 +391,45 @@ struct brcmf_scan_params_le {
|
|
__le16 channel_list[1]; /* list of chanspecs */
|
|
};
|
|
|
|
+struct brcmf_scan_params_v2_le {
|
|
+ __le16 version; /* structure version */
|
|
+ __le16 length; /* structure length */
|
|
+ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
|
|
+ u8 bssid[ETH_ALEN]; /* default: bcast */
|
|
+ s8 bss_type; /* default: any,
|
|
+ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
|
|
+ */
|
|
+ u8 pad;
|
|
+ __le32 scan_type; /* flags, 0 use default */
|
|
+ __le32 nprobes; /* -1 use default, number of probes per channel */
|
|
+ __le32 active_time; /* -1 use default, dwell time per channel for
|
|
+ * active scanning
|
|
+ */
|
|
+ __le32 passive_time; /* -1 use default, dwell time per channel
|
|
+ * for passive scanning
|
|
+ */
|
|
+ __le32 home_time; /* -1 use default, dwell time for the
|
|
+ * home channel between channel scans
|
|
+ */
|
|
+ __le32 channel_num; /* count of channels and ssids that follow
|
|
+ *
|
|
+ * low half is count of channels in
|
|
+ * channel_list, 0 means default (use all
|
|
+ * available channels)
|
|
+ *
|
|
+ * high half is entries in struct brcmf_ssid
|
|
+ * array that follows channel_list, aligned for
|
|
+ * s32 (4 bytes) meaning an odd channel count
|
|
+ * implies a 2-byte pad between end of
|
|
+ * channel_list and first ssid
|
|
+ *
|
|
+ * if ssid count is zero, single ssid in the
|
|
+ * fixed parameter portion is assumed, otherwise
|
|
+ * ssid in the fixed portion is ignored
|
|
+ */
|
|
+ __le16 channel_list[1]; /* list of chanspecs */
|
|
+};
|
|
+
|
|
struct brcmf_scan_results {
|
|
u32 buflen;
|
|
u32 version;
|
|
@@ -397,7 +441,10 @@ struct brcmf_escan_params_le {
|
|
__le32 version;
|
|
__le16 action;
|
|
__le16 sync_id;
|
|
- struct brcmf_scan_params_le params_le;
|
|
+ union {
|
|
+ struct brcmf_scan_params_le params_le;
|
|
+ struct brcmf_scan_params_v2_le params_v2_le;
|
|
+ };
|
|
};
|
|
|
|
struct brcmf_escan_result_le {
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From ec0d970a23ec71d7b0c00d8969e10a3639404bb6 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:17 +0900
|
|
Subject: [PATCH 04/10] brcmfmac: feature: Add support for setting feats based
|
|
on WLC version
|
|
|
|
The "wlc_ver" iovar returns information on the WLC and EPI versions.
|
|
This can be used to determine whether the PMKID_V2 and _V3 features are
|
|
supported.
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/feature.c | 48 +++++++++++++++++++
|
|
.../broadcom/brcm80211/brcmfmac/feature.h | 4 +-
|
|
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 25 ++++++++++
|
|
3 files changed, 76 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
index b6797f800..6d10c9efb 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
@@ -126,6 +126,53 @@ static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
|
|
drv->feat_flags |= feat_flags;
|
|
}
|
|
|
|
+struct brcmf_feat_wlcfeat {
|
|
+ u16 min_ver_major;
|
|
+ u16 min_ver_minor;
|
|
+ u32 feat_flags;
|
|
+};
|
|
+
|
|
+static const struct brcmf_feat_wlcfeat brcmf_feat_wlcfeat_map[] = {
|
|
+ { 12, 0, BIT(BRCMF_FEAT_PMKID_V2) },
|
|
+ { 13, 0, BIT(BRCMF_FEAT_PMKID_V3) },
|
|
+};
|
|
+
|
|
+static void brcmf_feat_wlc_version_overrides(struct brcmf_pub *drv)
|
|
+{
|
|
+ struct brcmf_if *ifp = brcmf_get_ifp(drv, 0);
|
|
+ const struct brcmf_feat_wlcfeat *e;
|
|
+ struct brcmf_wlc_version_le ver;
|
|
+ u32 feat_flags = 0;
|
|
+ int i, err, major, minor;
|
|
+
|
|
+ err = brcmf_fil_iovar_data_get(ifp, "wlc_ver", &ver, sizeof(ver));
|
|
+ if (err)
|
|
+ return;
|
|
+
|
|
+ major = le16_to_cpu(ver.wlc_ver_major);
|
|
+ minor = le16_to_cpu(ver.wlc_ver_minor);
|
|
+
|
|
+ brcmf_dbg(INFO, "WLC version: %d.%d\n", major, minor);
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(brcmf_feat_wlcfeat_map); i++) {
|
|
+ e = &brcmf_feat_wlcfeat_map[i];
|
|
+ if (major > e->min_ver_major ||
|
|
+ (major == e->min_ver_major &&
|
|
+ minor >= e->min_ver_minor)) {
|
|
+ feat_flags |= e->feat_flags;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!feat_flags)
|
|
+ return;
|
|
+
|
|
+ for (i = 0; i < BRCMF_FEAT_LAST; i++)
|
|
+ if (feat_flags & BIT(i))
|
|
+ brcmf_dbg(INFO, "enabling firmware feature: %s\n",
|
|
+ brcmf_feat_names[i]);
|
|
+ drv->feat_flags |= feat_flags;
|
|
+}
|
|
+
|
|
/**
|
|
* brcmf_feat_iovar_int_get() - determine feature through iovar query.
|
|
*
|
|
@@ -299,6 +346,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|
ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
|
|
}
|
|
|
|
+ brcmf_feat_wlc_version_overrides(drvr);
|
|
brcmf_feat_firmware_overrides(drvr);
|
|
|
|
/* set chip related quirks */
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
|
|
index 549298c55..7f4f0b3e4 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
|
|
@@ -55,7 +55,9 @@
|
|
BRCMF_FEAT_DEF(SAE) \
|
|
BRCMF_FEAT_DEF(FWAUTH) \
|
|
BRCMF_FEAT_DEF(DUMP_OBSS) \
|
|
- BRCMF_FEAT_DEF(SCAN_V2)
|
|
+ BRCMF_FEAT_DEF(SCAN_V2) \
|
|
+ BRCMF_FEAT_DEF(PMKID_V2) \
|
|
+ BRCMF_FEAT_DEF(PMKID_V3)
|
|
|
|
/*
|
|
* Quirks:
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
index b3844d0d1..801709c26 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
@@ -788,6 +788,31 @@ struct brcmf_rev_info_le {
|
|
__le32 nvramrev;
|
|
};
|
|
|
|
+/**
|
|
+ * struct brcmf_wlc_version_le - firmware revision info.
|
|
+ *
|
|
+ * @version: structure version.
|
|
+ * @length: structure length.
|
|
+ * @epi_ver_major: EPI major version
|
|
+ * @epi_ver_minor: EPI minor version
|
|
+ * @epi_ver_rc: EPI rc version
|
|
+ * @epi_ver_incr: EPI increment version
|
|
+ * @wlc_ver_major: WLC major version
|
|
+ * @wlc_ver_minor: WLC minor version
|
|
+ */
|
|
+struct brcmf_wlc_version_le {
|
|
+ __le16 version;
|
|
+ __le16 length;
|
|
+
|
|
+ __le16 epi_ver_major;
|
|
+ __le16 epi_ver_minor;
|
|
+ __le16 epi_ver_rc;
|
|
+ __le16 epi_ver_incr;
|
|
+
|
|
+ __le16 wlc_ver_major;
|
|
+ __le16 wlc_ver_minor;
|
|
+};
|
|
+
|
|
/**
|
|
* struct brcmf_assoclist_le - request assoc list.
|
|
*
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From 5f3efecef2913587bfe0b934b8104c8764112e23 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:18 +0900
|
|
Subject: [PATCH 05/10] brcmfmac: cfg80211: Add support for PMKID_V3 operations
|
|
|
|
Add support for the new PMKID_V3 API, which allows performing PMKID
|
|
mutations individually, instead of requiring the driver to keep track of
|
|
the full list. This new API is required by at least BCM4387.
|
|
|
|
Note that PMKID_V2 is not implemented yet.
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 52 +++++++++++-
|
|
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 83 +++++++++++++++++++
|
|
2 files changed, 132 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
index aa7e78cd5..f06c2c8ff 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
@@ -4306,6 +4306,37 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
|
|
return 0;
|
|
}
|
|
|
|
+static s32
|
|
+brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,
|
|
+ bool alive)
|
|
+{
|
|
+ struct brcmf_pmk_op_v3_le *pmk_op;
|
|
+ int length = offsetof(struct brcmf_pmk_op_v3_le, pmk);
|
|
+ int ret;
|
|
+
|
|
+ pmk_op = kzalloc(sizeof(*pmk_op), GFP_KERNEL);
|
|
+ pmk_op->version = cpu_to_le16(BRCMF_PMKSA_VER_3);
|
|
+
|
|
+ if (!pmksa) {
|
|
+ /* Flush operation, operate on entire list */
|
|
+ pmk_op->count = cpu_to_le16(0);
|
|
+ } else {
|
|
+ /* Single PMK operation */
|
|
+ pmk_op->count = cpu_to_le16(1);
|
|
+ length += sizeof(struct brcmf_pmksa_v3);
|
|
+ memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);
|
|
+ memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
|
|
+ pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;
|
|
+ pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0);
|
|
+ }
|
|
+
|
|
+ pmk_op->length = cpu_to_le16(length);
|
|
+
|
|
+ ret = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_op, sizeof(*pmk_op));
|
|
+ kfree(pmk_op);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static __used s32
|
|
brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
|
|
{
|
|
@@ -4339,6 +4370,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
|
|
if (!check_vif_up(ifp->vif))
|
|
return -EIO;
|
|
|
|
+ brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmksa->bssid);
|
|
+ brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmksa->pmkid);
|
|
+
|
|
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
|
|
+ return brcmf_pmksa_v3_op(ifp, pmksa, true);
|
|
+
|
|
+ /* TODO: implement PMKID_V2 */
|
|
+
|
|
npmk = le32_to_cpu(cfg->pmk_list.npmk);
|
|
for (i = 0; i < npmk; i++)
|
|
if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
|
|
@@ -4355,9 +4394,6 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmk[npmk].bssid);
|
|
- brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmk[npmk].pmkid);
|
|
-
|
|
err = brcmf_update_pmklist(cfg, ifp);
|
|
|
|
brcmf_dbg(TRACE, "Exit\n");
|
|
@@ -4381,6 +4417,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
|
brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid);
|
|
|
|
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
|
|
+ return brcmf_pmksa_v3_op(ifp, pmksa, false);
|
|
+
|
|
+ /* TODO: implement PMKID_V2 */
|
|
+
|
|
npmk = le32_to_cpu(cfg->pmk_list.npmk);
|
|
for (i = 0; i < npmk; i++)
|
|
if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
|
|
@@ -4417,6 +4458,11 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
|
|
if (!check_vif_up(ifp->vif))
|
|
return -EIO;
|
|
|
|
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
|
|
+ return brcmf_pmksa_v3_op(ifp, NULL, false);
|
|
+
|
|
+ /* TODO: implement PMKID_V2 */
|
|
+
|
|
memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));
|
|
err = brcmf_update_pmklist(cfg, ifp);
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
index 801709c26..792adaf88 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
|
@@ -174,6 +174,10 @@
|
|
|
|
#define BRCMF_HE_CAP_MCS_MAP_NSS_MAX 8
|
|
|
|
+#define BRCMF_PMKSA_VER_2 2
|
|
+#define BRCMF_PMKSA_VER_3 3
|
|
+#define BRCMF_PMKSA_NO_EXPIRY 0xffffffff
|
|
+
|
|
/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
|
|
* ioctl. It is relatively small because firmware has small maximum size input
|
|
* playload restriction for ioctls.
|
|
@@ -355,6 +359,12 @@ struct brcmf_ssid_le {
|
|
unsigned char SSID[IEEE80211_MAX_SSID_LEN];
|
|
};
|
|
|
|
+/* Alternate SSID structure used in some places... */
|
|
+struct brcmf_ssid8_le {
|
|
+ u8 SSID_len;
|
|
+ unsigned char SSID[IEEE80211_MAX_SSID_LEN];
|
|
+};
|
|
+
|
|
struct brcmf_scan_params_le {
|
|
struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
|
|
u8 bssid[ETH_ALEN]; /* default: bcast */
|
|
@@ -875,6 +885,51 @@ struct brcmf_pmksa {
|
|
u8 pmkid[WLAN_PMKID_LEN];
|
|
};
|
|
|
|
+/**
|
|
+ * struct brcmf_pmksa_v2 - PMK Security Association
|
|
+ *
|
|
+ * @length: Length of the structure.
|
|
+ * @bssid: The AP's BSSID.
|
|
+ * @pmkid: The PMK ID.
|
|
+ * @pmk: PMK material for FILS key derivation.
|
|
+ * @pmk_len: Length of PMK data.
|
|
+ * @ssid: The AP's SSID.
|
|
+ * @fils_cache_id: FILS cache identifier
|
|
+ */
|
|
+struct brcmf_pmksa_v2 {
|
|
+ __le16 length;
|
|
+ u8 bssid[ETH_ALEN];
|
|
+ u8 pmkid[WLAN_PMKID_LEN];
|
|
+ u8 pmk[WLAN_PMK_LEN_SUITE_B_192];
|
|
+ __le16 pmk_len;
|
|
+ struct brcmf_ssid8_le ssid;
|
|
+ u16 fils_cache_id;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct brcmf_pmksa_v3 - PMK Security Association
|
|
+ *
|
|
+ * @bssid: The AP's BSSID.
|
|
+ * @pmkid: The PMK ID.
|
|
+ * @pmkid_len: The length of the PMK ID.
|
|
+ * @pmk: PMK material for FILS key derivation.
|
|
+ * @pmk_len: Length of PMK data.
|
|
+ * @fils_cache_id: FILS cache identifier
|
|
+ * @ssid: The AP's SSID.
|
|
+ * @time_left: Remaining time until expiry. 0 = expired, ~0 = no expiry.
|
|
+ */
|
|
+struct brcmf_pmksa_v3 {
|
|
+ u8 bssid[ETH_ALEN];
|
|
+ u8 pmkid[WLAN_PMKID_LEN];
|
|
+ u8 pmkid_len;
|
|
+ u8 pmk[WLAN_PMK_LEN_SUITE_B_192];
|
|
+ u8 pmk_len;
|
|
+ __le16 fils_cache_id;
|
|
+ u8 pad;
|
|
+ struct brcmf_ssid8_le ssid;
|
|
+ __le32 time_left;
|
|
+};
|
|
+
|
|
/**
|
|
* struct brcmf_pmk_list_le - List of pmksa's.
|
|
*
|
|
@@ -886,6 +941,34 @@ struct brcmf_pmk_list_le {
|
|
struct brcmf_pmksa pmk[BRCMF_MAXPMKID];
|
|
};
|
|
|
|
+/**
|
|
+ * struct brcmf_pmk_list_v2_le - List of pmksa's.
|
|
+ *
|
|
+ * @version: Request version.
|
|
+ * @length: Length of this structure.
|
|
+ * @pmk: PMK SA information.
|
|
+ */
|
|
+struct brcmf_pmk_list_v2_le {
|
|
+ __le16 version;
|
|
+ __le16 length;
|
|
+ struct brcmf_pmksa_v2 pmk[BRCMF_MAXPMKID];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct brcmf_pmk_op_v3_le - Operation on PMKSA list.
|
|
+ *
|
|
+ * @version: Request version.
|
|
+ * @length: Length of this structure.
|
|
+ * @pmk: PMK SA information.
|
|
+ */
|
|
+struct brcmf_pmk_op_v3_le {
|
|
+ __le16 version;
|
|
+ __le16 length;
|
|
+ __le16 count;
|
|
+ __le16 pad;
|
|
+ struct brcmf_pmksa_v3 pmk[BRCMF_MAXPMKID];
|
|
+};
|
|
+
|
|
/**
|
|
* struct brcmf_pno_param_le - PNO scan configuration parameters
|
|
*
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From 0bcbbe3fe191f9b09f90fe8c33f3e20f0ec2ab52 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:20 +0900
|
|
Subject: [PATCH 07/10] brcmfmac: pcie: Add IDs/properties for BCM4387
|
|
|
|
This chip is present on Apple M1 Pro/Max (t600x) platforms:
|
|
|
|
* maldives (apple,j314s): MacBook Pro (14-inch, M1 Pro, 2021)
|
|
* maldives (apple,j314c): MacBook Pro (14-inch, M1 Max, 2021)
|
|
* madagascar (apple,j316s): MacBook Pro (16-inch, M1 Pro, 2021)
|
|
* madagascar (apple,j316c): MacBook Pro (16-inch, M1 Max, 2021)
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 ++
|
|
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++++
|
|
.../net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++
|
|
3 files changed, 12 insertions(+)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
index 50e0c015c..9f9bf08a7 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
|
@@ -743,6 +743,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
|
|
return 0x170000;
|
|
case BRCM_CC_4378_CHIP_ID:
|
|
return 0x352000;
|
|
+ case BRCM_CC_4387_CHIP_ID:
|
|
+ return 0x740000;
|
|
default:
|
|
brcmf_err("unknown chip: %s\n", ci->pub.name);
|
|
break;
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
index 2835ef4ed..d2dad5414 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
@@ -67,6 +67,7 @@ BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
|
|
BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
|
|
BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
|
|
BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
|
|
+BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");
|
|
|
|
/* firmware config files */
|
|
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
|
|
@@ -101,6 +102,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
|
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
|
|
BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */
|
|
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* revision ID 3 */
|
|
+ BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* revision ID 7 */
|
|
};
|
|
|
|
#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */
|
|
@@ -2048,6 +2050,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
|
|
base = 0x1120;
|
|
words = 0x170;
|
|
break;
|
|
+ case BRCM_CC_4387_CHIP_ID:
|
|
+ coreid = BCMA_CORE_GCI;
|
|
+ base = 0x113c;
|
|
+ words = 0x170;
|
|
+ break;
|
|
default:
|
|
/* OTP not supported on this chip */
|
|
return 0;
|
|
@@ -2662,6 +2669,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
|
|
BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW),
|
|
BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC),
|
|
BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
|
|
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC),
|
|
|
|
{ /* end: all zeroes */ }
|
|
};
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
|
|
index 896615f57..44684bf1b 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
|
|
@@ -54,6 +54,7 @@
|
|
#define BRCM_CC_4371_CHIP_ID 0x4371
|
|
#define BRCM_CC_4377_CHIP_ID 0x4377
|
|
#define BRCM_CC_4378_CHIP_ID 0x4378
|
|
+#define BRCM_CC_4387_CHIP_ID 0x4387
|
|
#define CY_CC_4373_CHIP_ID 0x4373
|
|
#define CY_CC_43012_CHIP_ID 43012
|
|
#define CY_CC_43439_CHIP_ID 43439
|
|
@@ -95,6 +96,7 @@
|
|
#define BRCM_PCIE_43596_DEVICE_ID 0x4415
|
|
#define BRCM_PCIE_4377_DEVICE_ID 0x4488
|
|
#define BRCM_PCIE_4378_DEVICE_ID 0x4425
|
|
+#define BRCM_PCIE_4387_DEVICE_ID 0x4433
|
|
|
|
/* brcmsmac IDs */
|
|
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From 6476bdb033ad7eb9bea5b7804467543664755da1 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:21 +0900
|
|
Subject: [PATCH 08/10] brcmfmac: common: Add support for downloading TxCap
|
|
blobs
|
|
|
|
The TxCap blobs are additional data blobs used on Apple devices, and
|
|
are uploaded analogously to CLM blobs. Add core support for doing this.
|
|
|
|
Acked-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/bus.h | 1 +
|
|
.../broadcom/brcm80211/brcmfmac/common.c | 93 ++++++++++++++-----
|
|
2 files changed, 70 insertions(+), 24 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
|
index 501136e01..fe31051a9 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
|
@@ -55,6 +55,7 @@ enum brcmf_bus_protocol_type {
|
|
/* Firmware blobs that may be available */
|
|
enum brcmf_blob_type {
|
|
BRCMF_BLOB_CLM,
|
|
+ BRCMF_BLOB_TXCAP,
|
|
};
|
|
|
|
struct brcmf_mp_device;
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
|
index b977e5013..91b46992f 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
|
@@ -101,7 +101,7 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
|
|
|
|
static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
|
|
struct brcmf_dload_data_le *dload_buf,
|
|
- u32 len)
|
|
+ u32 len, const char *var)
|
|
{
|
|
s32 err;
|
|
|
|
@@ -111,18 +111,18 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
|
|
dload_buf->len = cpu_to_le32(len);
|
|
dload_buf->crc = cpu_to_le32(0);
|
|
|
|
- err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf,
|
|
+ err = brcmf_fil_iovar_data_set(ifp, var, dload_buf,
|
|
struct_size(dload_buf, data, len));
|
|
|
|
return err;
|
|
}
|
|
|
|
-static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|
+static int brcmf_c_download_blob(struct brcmf_if *ifp,
|
|
+ const void *data, size_t size,
|
|
+ const char *loadvar, const char *statvar)
|
|
{
|
|
struct brcmf_pub *drvr = ifp->drvr;
|
|
- struct brcmf_bus *bus = drvr->bus_if;
|
|
struct brcmf_dload_data_le *chunk_buf;
|
|
- const struct firmware *clm = NULL;
|
|
u32 chunk_len;
|
|
u32 datalen;
|
|
u32 cumulative_len;
|
|
@@ -132,21 +132,14 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|
|
|
brcmf_dbg(TRACE, "Enter\n");
|
|
|
|
- err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
|
|
- if (err || !clm) {
|
|
- brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
|
|
- err);
|
|
- return 0;
|
|
- }
|
|
-
|
|
chunk_buf = kzalloc(struct_size(chunk_buf, data, MAX_CHUNK_LEN),
|
|
GFP_KERNEL);
|
|
if (!chunk_buf) {
|
|
err = -ENOMEM;
|
|
- goto done;
|
|
+ return -ENOMEM;
|
|
}
|
|
|
|
- datalen = clm->size;
|
|
+ datalen = size;
|
|
cumulative_len = 0;
|
|
do {
|
|
if (datalen > MAX_CHUNK_LEN) {
|
|
@@ -155,9 +148,10 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|
chunk_len = datalen;
|
|
dl_flag |= DL_END;
|
|
}
|
|
- memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
|
|
+ memcpy(chunk_buf->data, data + cumulative_len, chunk_len);
|
|
|
|
- err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
|
|
+ err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len,
|
|
+ loadvar);
|
|
|
|
dl_flag &= ~DL_BEGIN;
|
|
|
|
@@ -166,20 +160,64 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|
} while ((datalen > 0) && (err == 0));
|
|
|
|
if (err) {
|
|
- bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n",
|
|
- clm->size, err);
|
|
- /* Retrieve clmload_status and print */
|
|
- err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
|
|
+ bphy_err(drvr, "%s (%zu byte file) failed (%d)\n",
|
|
+ loadvar, size, err);
|
|
+ /* Retrieve status and print */
|
|
+ err = brcmf_fil_iovar_int_get(ifp, statvar, &status);
|
|
if (err)
|
|
- bphy_err(drvr, "get clmload_status failed (%d)\n", err);
|
|
+ bphy_err(drvr, "get %s failed (%d)\n", statvar, err);
|
|
else
|
|
- brcmf_dbg(INFO, "clmload_status=%d\n", status);
|
|
+ brcmf_dbg(INFO, "%s=%d\n", statvar, status);
|
|
err = -EIO;
|
|
}
|
|
|
|
kfree(chunk_buf);
|
|
-done:
|
|
- release_firmware(clm);
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|
+{
|
|
+ struct brcmf_pub *drvr = ifp->drvr;
|
|
+ struct brcmf_bus *bus = drvr->bus_if;
|
|
+ const struct firmware *fw = NULL;
|
|
+ s32 err;
|
|
+
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
+
|
|
+ err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_CLM);
|
|
+ if (err || !fw) {
|
|
+ brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
|
|
+ err);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ err = brcmf_c_download_blob(ifp, fw->data, fw->size,
|
|
+ "clmload", "clmload_status");
|
|
+
|
|
+ release_firmware(fw);
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp)
|
|
+{
|
|
+ struct brcmf_pub *drvr = ifp->drvr;
|
|
+ struct brcmf_bus *bus = drvr->bus_if;
|
|
+ const struct firmware *fw = NULL;
|
|
+ s32 err;
|
|
+
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
+
|
|
+ err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_TXCAP);
|
|
+ if (err || !fw) {
|
|
+ brcmf_info("no txcap_blob available (err=%d)\n", err);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ brcmf_info("TxCap blob found, loading\n");
|
|
+ err = brcmf_c_download_blob(ifp, fw->data, fw->size,
|
|
+ "txcapload", "txcapload_status");
|
|
+
|
|
+ release_firmware(fw);
|
|
return err;
|
|
}
|
|
|
|
@@ -291,6 +329,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|
goto done;
|
|
}
|
|
|
|
+ /* Do TxCap downloading, if needed */
|
|
+ err = brcmf_c_process_txcap_blob(ifp);
|
|
+ if (err < 0) {
|
|
+ bphy_err(drvr, "download TxCap blob file failed, %d\n", err);
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
/* query for 'ver' to get version info from firmware */
|
|
memset(buf, 0, sizeof(buf));
|
|
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From 6142509362d128fd60dc21459f25ca41c6e1df22 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:22 +0900
|
|
Subject: [PATCH 09/10] brcmfmac: pcie: Load and provide TxCap blobs
|
|
|
|
These blobs are named .txcap_blob, and exist alongside the existing
|
|
.clm_blob files. Use the existing firmware machinery to provide them to
|
|
the core.
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 13 +++++++++++++
|
|
1 file changed, 13 insertions(+)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
index d2dad5414..0fcdd84bb 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
@@ -76,6 +76,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
|
|
/* per-board firmware binaries */
|
|
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
|
|
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");
|
|
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txcap_blob");
|
|
|
|
static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
|
BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
|
|
@@ -329,7 +330,9 @@ struct brcmf_pciedev_info {
|
|
char fw_name[BRCMF_FW_NAME_LEN];
|
|
char nvram_name[BRCMF_FW_NAME_LEN];
|
|
char clm_name[BRCMF_FW_NAME_LEN];
|
|
+ char txcap_name[BRCMF_FW_NAME_LEN];
|
|
const struct firmware *clm_fw;
|
|
+ const struct firmware *txcap_fw;
|
|
const struct brcmf_pcie_reginfo *reginfo;
|
|
void __iomem *regs;
|
|
void __iomem *tcm;
|
|
@@ -1520,6 +1523,10 @@ static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
|
|
*fw = devinfo->clm_fw;
|
|
devinfo->clm_fw = NULL;
|
|
break;
|
|
+ case BRCMF_BLOB_TXCAP:
|
|
+ *fw = devinfo->txcap_fw;
|
|
+ devinfo->txcap_fw = NULL;
|
|
+ break;
|
|
default:
|
|
return -ENOENT;
|
|
}
|
|
@@ -2112,6 +2119,7 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
|
|
#define BRCMF_PCIE_FW_CODE 0
|
|
#define BRCMF_PCIE_FW_NVRAM 1
|
|
#define BRCMF_PCIE_FW_CLM 2
|
|
+#define BRCMF_PCIE_FW_TXCAP 3
|
|
|
|
static void brcmf_pcie_setup(struct device *dev, int ret,
|
|
struct brcmf_fw_request *fwreq)
|
|
@@ -2138,6 +2146,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
|
|
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
|
|
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
|
|
devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
|
|
+ devinfo->txcap_fw = fwreq->items[BRCMF_PCIE_FW_TXCAP].binary;
|
|
kfree(fwreq);
|
|
|
|
ret = brcmf_chip_get_raminfo(devinfo->ci);
|
|
@@ -2219,6 +2228,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
|
{ ".bin", devinfo->fw_name },
|
|
{ ".txt", devinfo->nvram_name },
|
|
{ ".clm_blob", devinfo->clm_name },
|
|
+ { ".txcap_blob", devinfo->txcap_name },
|
|
};
|
|
|
|
fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
|
|
@@ -2233,6 +2243,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
|
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
|
|
fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
|
|
fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
|
|
+ fwreq->items[BRCMF_PCIE_FW_TXCAP].type = BRCMF_FW_TYPE_BINARY;
|
|
+ fwreq->items[BRCMF_PCIE_FW_TXCAP].flags = BRCMF_FW_REQF_OPTIONAL;
|
|
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
|
|
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
|
|
fwreq->bus_nr = devinfo->pdev->bus->number;
|
|
@@ -2530,6 +2542,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
|
brcmf_pcie_reset_device(devinfo);
|
|
brcmf_pcie_release_resource(devinfo);
|
|
release_firmware(devinfo->clm_fw);
|
|
+ release_firmware(devinfo->txcap_fw);
|
|
|
|
if (devinfo->ci)
|
|
brcmf_chip_detach(devinfo->ci);
|
|
--
|
|
2.37.2
|
|
|
|
|
|
From ffe36f60423b9b6294dce635cd524123ee449029 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Tue, 14 Feb 2023 18:24:23 +0900
|
|
Subject: [PATCH 10/10] brcmfmac: common: Add support for external calibration
|
|
blobs
|
|
|
|
The calibration blob for a chip is normally stored in SROM and loaded
|
|
internally by the firmware. However, Apple ARM64 platforms instead store
|
|
it as part of platform configuration data, and provide it via the Apple
|
|
Device Tree. We forward this into the Linux DT in the bootloader.
|
|
|
|
Add support for taking this blob from the DT and loading it into the
|
|
dongle. The loading mechanism is the same as used for the CLM and TxCap
|
|
blobs.
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/common.c | 24 +++++++++++++++++++
|
|
.../broadcom/brcm80211/brcmfmac/common.h | 2 ++
|
|
.../wireless/broadcom/brcm80211/brcmfmac/of.c | 7 ++++++
|
|
3 files changed, 33 insertions(+)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
|
index 91b46992f..9746cde20 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
|
@@ -246,6 +246,23 @@ static const u8 brcmf_default_mac_address[ETH_ALEN] = {
|
|
0x00, 0x90, 0x4c, 0xc5, 0x12, 0x38
|
|
};
|
|
|
|
+static int brcmf_c_process_cal_blob(struct brcmf_if *ifp)
|
|
+{
|
|
+ struct brcmf_pub *drvr = ifp->drvr;
|
|
+ struct brcmf_mp_device *settings = drvr->settings;
|
|
+ s32 err;
|
|
+
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
+
|
|
+ if (!settings->cal_blob || !settings->cal_size)
|
|
+ return 0;
|
|
+
|
|
+ brcmf_info("Calibration blob provided by platform, loading\n");
|
|
+ err = brcmf_c_download_blob(ifp, settings->cal_blob, settings->cal_size,
|
|
+ "calload", "calload_status");
|
|
+ return err;
|
|
+}
|
|
+
|
|
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|
{
|
|
struct brcmf_pub *drvr = ifp->drvr;
|
|
@@ -336,6 +353,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|
goto done;
|
|
}
|
|
|
|
+ /* Download external calibration blob, if available */
|
|
+ err = brcmf_c_process_cal_blob(ifp);
|
|
+ if (err < 0) {
|
|
+ bphy_err(drvr, "download calibration blob file failed, %d\n", err);
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
/* query for 'ver' to get version info from firmware */
|
|
memset(buf, 0, sizeof(buf));
|
|
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
|
index 7167fd4f8..2be2986d2 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
|
@@ -54,6 +54,8 @@ struct brcmf_mp_device {
|
|
const char *board_type;
|
|
unsigned char mac[ETH_ALEN];
|
|
const char *antenna_sku;
|
|
+ const void *cal_blob;
|
|
+ int cal_size;
|
|
union {
|
|
struct brcmfmac_sdio_pd sdio;
|
|
} bus;
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
|
index fdd0c9abc..52527b613 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
|
@@ -86,6 +86,13 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
|
if (!of_property_read_string(np, "apple,antenna-sku", &prop))
|
|
settings->antenna_sku = prop;
|
|
|
|
+ /* The WLAN calibration blob is normally stored in SROM, but Apple
|
|
+ * ARM64 platforms pass it via the DT instead.
|
|
+ */
|
|
+ prop = of_get_property(np, "brcm,cal-blob", &settings->cal_size);
|
|
+ if (prop && settings->cal_size)
|
|
+ settings->cal_blob = prop;
|
|
+
|
|
/* Set board-type to the first string of the machine compatible prop */
|
|
root = of_find_node_by_path("/");
|
|
if (root && err) {
|
|
--
|
|
2.37.2
|
|
|