mac80211: backport today's brcmfmac changes
This fixes various problems with parsing platform NVRAM. It's required to get BCM43602 working in most cases. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 45802
This commit is contained in:
parent
597d2060c5
commit
c1cc2217c2
5 changed files with 323 additions and 0 deletions
|
@ -0,0 +1,102 @@
|
||||||
|
From: Arend van Spriel <arend@broadcom.com>
|
||||||
|
Date: Tue, 26 May 2015 13:19:46 +0200
|
||||||
|
Subject: [PATCH] brcmfmac: avoid null pointer access when
|
||||||
|
brcmf_msgbuf_get_pktid() fails
|
||||||
|
|
||||||
|
The function brcmf_msgbuf_get_pktid() may return a NULL pointer so
|
||||||
|
the callers should check the return pointer before accessing it to
|
||||||
|
avoid the crash below (see [1]):
|
||||||
|
|
||||||
|
brcmfmac: brcmf_msgbuf_get_pktid: Invalid packet id 273 (not in use)
|
||||||
|
BUG: unable to handle kernel NULL pointer dereference at 0000000000000080
|
||||||
|
IP: [<ffffffff8145b225>] skb_pull+0x5/0x50
|
||||||
|
PGD 0
|
||||||
|
Oops: 0000 [#1] PREEMPT SMP
|
||||||
|
Modules linked in: pci_stub vboxpci(O) vboxnetflt(O) vboxnetadp(O) vboxdrv(O)
|
||||||
|
snd_hda_codec_hdmi bnep mousedev hid_generic ushwmon msr ext4 crc16 mbcache
|
||||||
|
jbd2 sd_mod uas usb_storage ahci libahci libata scsi_mod xhci_pci xhci_hcd
|
||||||
|
usbcore usb_common
|
||||||
|
CPU: 0 PID: 1661 Comm: irq/61-brcmf_pc Tainted: G O 4.0.1-MacbookPro-ARCH #1
|
||||||
|
Hardware name: Apple Inc. MacBookPro12,1/Mac-E43C1C25D4880AD6,
|
||||||
|
BIOS MBP121.88Z.0167.B02.1503241251 03/24/2015
|
||||||
|
task: ffff880264203cc0 ti: ffff88025ffe4000 task.ti: ffff88025ffe4000
|
||||||
|
RIP: 0010:[<ffffffff8145b225>] [<ffffffff8145b225>] skb_pull+0x5/0x50
|
||||||
|
RSP: 0018:ffff88025ffe7d40 EFLAGS: 00010202
|
||||||
|
RAX: 0000000000000000 RBX: ffff88008a33c000 RCX: 0000000000000044
|
||||||
|
RDX: 0000000000000000 RSI: 000000000000004a RDI: 0000000000000000
|
||||||
|
RBP: ffff88025ffe7da8 R08: 0000000000000096 R09: 000000000000004a
|
||||||
|
R10: 0000000000000000 R11: 000000000000048e R12: ffff88025ff14f00
|
||||||
|
R13: 0000000000000000 R14: ffff880263b48200 R15: ffff88008a33c000
|
||||||
|
FS: 0000000000000000(0000) GS:ffff88026ec00000(0000) knlGS:0000000000000000
|
||||||
|
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
|
||||||
|
CR2: 0000000000000080 CR3: 000000000180b000 CR4: 00000000003407f0
|
||||||
|
Stack:
|
||||||
|
ffffffffa06aed74 ffff88025ffe7dc8 ffff880263b48270 ffff880263b48278
|
||||||
|
05ea88020000004a 0002ffff81014635 000000001720b2f6 ffff88026ec116c0
|
||||||
|
ffff880263b48200 0000000000010000 ffff880263b4ae00 ffff880264203cc0
|
||||||
|
Call Trace:
|
||||||
|
[<ffffffffa06aed74>] ? brcmf_msgbuf_process_rx+0x404/0x480 [brcmfmac]
|
||||||
|
[<ffffffff810cea60>] ? irq_finalize_oneshot.part.30+0xf0/0xf0
|
||||||
|
[<ffffffffa06afb55>] brcmf_proto_msgbuf_rx_trigger+0x35/0xf0 [brcmfmac]
|
||||||
|
[<ffffffffa06baf2a>] brcmf_pcie_isr_thread_v2+0x8a/0x130 [brcmfmac]
|
||||||
|
[<ffffffff810cea80>] irq_thread_fn+0x20/0x50
|
||||||
|
[<ffffffff810ceddf>] irq_thread+0x13f/0x170
|
||||||
|
[<ffffffff810cebf0>] ? wake_threads_waitq+0x30/0x30
|
||||||
|
[<ffffffff810ceca0>] ? irq_thread_dtor+0xb0/0xb0
|
||||||
|
[<ffffffff81092a08>] kthread+0xd8/0xf0
|
||||||
|
[<ffffffff81092930>] ? kthread_create_on_node+0x1c0/0x1c0
|
||||||
|
[<ffffffff8156d898>] ret_from_fork+0x58/0x90
|
||||||
|
[<ffffffff81092930>] ? kthread_create_on_node+0x1c0/0x1c0
|
||||||
|
Code: 01 83 e2 f7 88 50 01 48 83 c4 08 5b 5d f3 c3 0f 1f 80 00 00 00 00 83 e2
|
||||||
|
f7 88 50 01 c3 66 0f 1f 84 00 00 00 00 00 0f 1f
|
||||||
|
RIP [<ffffffff8145b225>] skb_pull+0x5/0x50
|
||||||
|
RSP <ffff88025ffe7d40>
|
||||||
|
CR2: 0000000000000080
|
||||||
|
---[ end trace b074c0f90e7c997d ]---
|
||||||
|
|
||||||
|
[1] http://mid.gmane.org/20150430193259.GA5630@googlemail.com
|
||||||
|
|
||||||
|
Cc: <stable@vger.kernel.org> # v3.18, v3.19, v4.0, v4.1
|
||||||
|
Reported-by: Michael Hornung <mhornung.linux@gmail.com>
|
||||||
|
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||||
|
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||||
|
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||||
|
@@ -500,11 +500,9 @@ static int brcmf_msgbuf_query_dcmd(struc
|
||||||
|
msgbuf->rx_pktids,
|
||||||
|
msgbuf->ioctl_resp_pktid);
|
||||||
|
if (msgbuf->ioctl_resp_ret_len != 0) {
|
||||||
|
- if (!skb) {
|
||||||
|
- brcmf_err("Invalid packet id idx recv'd %d\n",
|
||||||
|
- msgbuf->ioctl_resp_pktid);
|
||||||
|
+ if (!skb)
|
||||||
|
return -EBADF;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
|
||||||
|
len : msgbuf->ioctl_resp_ret_len);
|
||||||
|
}
|
||||||
|
@@ -866,10 +864,8 @@ brcmf_msgbuf_process_txstatus(struct brc
|
||||||
|
flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||||
|
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
|
||||||
|
msgbuf->tx_pktids, idx);
|
||||||
|
- if (!skb) {
|
||||||
|
- brcmf_err("Invalid packet id idx recv'd %d\n", idx);
|
||||||
|
+ if (!skb)
|
||||||
|
return;
|
||||||
|
- }
|
||||||
|
|
||||||
|
set_bit(flowid, msgbuf->txstatus_done_map);
|
||||||
|
commonring = msgbuf->flowrings[flowid];
|
||||||
|
@@ -1148,6 +1144,8 @@ brcmf_msgbuf_process_rx_complete(struct
|
||||||
|
|
||||||
|
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
|
||||||
|
msgbuf->rx_pktids, idx);
|
||||||
|
+ if (!skb)
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
if (data_offset)
|
||||||
|
skb_pull(skb, data_offset);
|
|
@ -0,0 +1,63 @@
|
||||||
|
From: Arend van Spriel <arend@broadcom.com>
|
||||||
|
Date: Wed, 27 May 2015 19:31:41 +0200
|
||||||
|
Subject: [PATCH] brcmfmac: fix invalid access to struct acpi_device fields
|
||||||
|
|
||||||
|
The fields of struct acpi_device are only known when CONFIG_ACPI is
|
||||||
|
defined. Fix this by using a helper function. This will resolve the
|
||||||
|
issue found in linux-next:
|
||||||
|
|
||||||
|
../brcmfmac/bcmsdh.c: In function 'brcmf_ops_sdio_probe':
|
||||||
|
../brcmfmac/bcmsdh.c:1139:7: error: dereferencing pointer to incomplete type
|
||||||
|
adev->flags.power_manageable = 0;
|
||||||
|
^
|
||||||
|
|
||||||
|
Fixes: f0992ace680c ("brcmfmac: prohibit ACPI power management ...")
|
||||||
|
Cc: Fu, Zhonghui <zhonghui.fu@linux.intel.com>
|
||||||
|
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
|
||||||
|
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
|
||||||
|
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
|
||||||
|
@@ -1117,6 +1117,18 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_id
|
||||||
|
static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
|
||||||
|
|
||||||
|
|
||||||
|
+static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
|
||||||
|
+ int val)
|
||||||
|
+{
|
||||||
|
+#if IS_ENABLED(CONFIG_ACPI)
|
||||||
|
+ struct acpi_device *adev;
|
||||||
|
+
|
||||||
|
+ adev = ACPI_COMPANION(dev);
|
||||||
|
+ if (adev)
|
||||||
|
+ adev->flags.power_manageable = 0;
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||||
|
const struct sdio_device_id *id)
|
||||||
|
{
|
||||||
|
@@ -1124,7 +1136,6 @@ static int brcmf_ops_sdio_probe(struct s
|
||||||
|
struct brcmf_sdio_dev *sdiodev;
|
||||||
|
struct brcmf_bus *bus_if;
|
||||||
|
struct device *dev;
|
||||||
|
- struct acpi_device *adev;
|
||||||
|
|
||||||
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
brcmf_dbg(SDIO, "Class=%x\n", func->class);
|
||||||
|
@@ -1132,11 +1143,9 @@ static int brcmf_ops_sdio_probe(struct s
|
||||||
|
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
||||||
|
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
|
||||||
|
|
||||||
|
- /* prohibit ACPI power management for this device */
|
||||||
|
dev = &func->dev;
|
||||||
|
- adev = ACPI_COMPANION(dev);
|
||||||
|
- if (adev)
|
||||||
|
- adev->flags.power_manageable = 0;
|
||||||
|
+ /* prohibit ACPI power management for this device */
|
||||||
|
+ brcmf_sdiod_acpi_set_power_manageable(dev, 0);
|
||||||
|
|
||||||
|
/* Consume func num 1 but dont do anything with it. */
|
||||||
|
if (func->num == 1)
|
|
@ -0,0 +1,56 @@
|
||||||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||||
|
Date: Wed, 20 May 2015 09:34:21 +0200
|
||||||
|
Subject: [PATCH] brcmfmac: simplify check stripping v2 NVRAM
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Comparing NVRAM entry with a full filtering string is simpler than
|
||||||
|
comparing it with a short prefix and then checking random chars at magic
|
||||||
|
offsets. The cost of snprintf relatively low, we execute it just once.
|
||||||
|
Tested on BCM43602 with NVRAM hacked to use V2 format.
|
||||||
|
|
||||||
|
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||||
|
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||||
|
@@ -25,7 +25,7 @@
|
||||||
|
|
||||||
|
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
|
||||||
|
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||||
|
-#define BRCMF_FW_NVRAM_PCIEDEV_LEN 9 /* pcie/1/4/ */
|
||||||
|
+#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||||
|
|
||||||
|
char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
|
||||||
|
module_param_string(firmware_path, brcmf_firmware_path,
|
||||||
|
@@ -297,6 +297,8 @@ fail:
|
||||||
|
static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
|
||||||
|
u16 bus_nr)
|
||||||
|
{
|
||||||
|
+ char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
|
||||||
|
+ size_t len;
|
||||||
|
u32 i, j;
|
||||||
|
u8 *nvram;
|
||||||
|
|
||||||
|
@@ -308,14 +310,13 @@ static void brcmf_fw_strip_multi_v2(stru
|
||||||
|
* Valid entries are of type pcie/X/Y/ where X = domain_nr and
|
||||||
|
* Y = bus_nr.
|
||||||
|
*/
|
||||||
|
+ snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
|
||||||
|
+ len = strlen(prefix);
|
||||||
|
i = 0;
|
||||||
|
j = 0;
|
||||||
|
- while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) {
|
||||||
|
- if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) &&
|
||||||
|
- (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') &&
|
||||||
|
- ((nvp->nvram[i + 5] - '0') == domain_nr) &&
|
||||||
|
- ((nvp->nvram[i + 7] - '0') == bus_nr)) {
|
||||||
|
- i += BRCMF_FW_NVRAM_PCIEDEV_LEN;
|
||||||
|
+ while (i < nvp->nvram_len - len) {
|
||||||
|
+ if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
|
||||||
|
+ i += len;
|
||||||
|
while (nvp->nvram[i] != 0) {
|
||||||
|
nvram[j] = nvp->nvram[i];
|
||||||
|
i++;
|
|
@ -0,0 +1,57 @@
|
||||||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||||
|
Date: Wed, 20 May 2015 11:01:08 +0200
|
||||||
|
Subject: [PATCH] brcmfmac: simplify check finding NVRAM v1 device path
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
With a simple use of snprintf and small buffer we can compare NVRAM
|
||||||
|
entry value with a full string. This way we avoid checking random chars
|
||||||
|
at magic offsets.
|
||||||
|
Tested on BCM43602 with NVRAM hacked to use v1 format.
|
||||||
|
|
||||||
|
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||||
|
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||||
|
@@ -222,6 +222,10 @@ static int brcmf_init_nvram_parser(struc
|
||||||
|
static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||||
|
u16 bus_nr)
|
||||||
|
{
|
||||||
|
+ /* Device path with a leading '=' key-value separator */
|
||||||
|
+ char pcie_path[] = "=pcie/?/?";
|
||||||
|
+ size_t pcie_len;
|
||||||
|
+
|
||||||
|
u32 i, j;
|
||||||
|
bool found;
|
||||||
|
u8 *nvram;
|
||||||
|
@@ -238,6 +242,9 @@ static void brcmf_fw_strip_multi_v1(stru
|
||||||
|
/* First search for the devpathX and see if it is the configuration
|
||||||
|
* for domain_nr/bus_nr. Search complete nvp
|
||||||
|
*/
|
||||||
|
+ snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
|
||||||
|
+ bus_nr);
|
||||||
|
+ pcie_len = strlen(pcie_path);
|
||||||
|
found = false;
|
||||||
|
i = 0;
|
||||||
|
while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
|
||||||
|
@@ -245,13 +252,10 @@ static void brcmf_fw_strip_multi_v1(stru
|
||||||
|
* Y = domain_nr, Z = bus_nr, X = virtual ID
|
||||||
|
*/
|
||||||
|
if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
|
||||||
|
- (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) {
|
||||||
|
- if (((nvp->nvram[i + 14] - '0') == domain_nr) &&
|
||||||
|
- ((nvp->nvram[i + 16] - '0') == bus_nr)) {
|
||||||
|
- id = nvp->nvram[i + 7] - '0';
|
||||||
|
- found = true;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+ (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
|
||||||
|
+ id = nvp->nvram[i + 7] - '0';
|
||||||
|
+ found = true;
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
while (nvp->nvram[i] != 0)
|
||||||
|
i++;
|
|
@ -0,0 +1,45 @@
|
||||||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||||
|
Date: Wed, 20 May 2015 13:59:54 +0200
|
||||||
|
Subject: [PATCH] brcmfmac: treat \0 as end of comment when parsing NVRAM
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
This fixes brcmfmac dealing with NVRAM coming from platform e.g. from a
|
||||||
|
flash MTD partition. In such cases entries are separated by \0 instead
|
||||||
|
of \n which caused ignoring whole content after the first "comment".
|
||||||
|
While platform NVRAM doesn't usually contain comments, we switch to
|
||||||
|
COMMENT state after e.g. finding an unexpected char in key name.
|
||||||
|
|
||||||
|
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||||
|
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||||
|
@@ -162,17 +162,20 @@ brcmf_nvram_handle_value(struct nvram_pa
|
||||||
|
static enum nvram_parser_state
|
||||||
|
brcmf_nvram_handle_comment(struct nvram_parser *nvp)
|
||||||
|
{
|
||||||
|
- char *eol, *sol;
|
||||||
|
+ char *eoc, *sol;
|
||||||
|
|
||||||
|
sol = (char *)&nvp->fwnv->data[nvp->pos];
|
||||||
|
- eol = strchr(sol, '\n');
|
||||||
|
- if (eol == NULL)
|
||||||
|
- return END;
|
||||||
|
+ eoc = strchr(sol, '\n');
|
||||||
|
+ if (!eoc) {
|
||||||
|
+ eoc = strchr(sol, '\0');
|
||||||
|
+ if (!eoc)
|
||||||
|
+ return END;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* eat all moving to next line */
|
||||||
|
nvp->line++;
|
||||||
|
nvp->column = 1;
|
||||||
|
- nvp->pos += (eol - sol) + 1;
|
||||||
|
+ nvp->pos += (eoc - sol) + 1;
|
||||||
|
return IDLE;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue