From c1cc2217c24cbc419a642d896cf27d43038856a6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 28 May 2015 10:39:11 +0000 Subject: [PATCH] mac80211: backport today's brcmfmac changes MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This fixes various problems with parsing platform NVRAM. It's required to get BCM43602 working in most cases. Signed-off-by: Rafał Miłecki SVN-Revision: 45802 --- ...ull-pointer-access-when-brcmf_msgbuf.patch | 102 ++++++++++++++++++ ...alid-access-to-struct-acpi_device-fi.patch | 63 +++++++++++ ...ac-simplify-check-stripping-v2-NVRAM.patch | 56 ++++++++++ ...y-check-finding-NVRAM-v1-device-path.patch | 57 ++++++++++ ...-as-end-of-comment-when-parsing-NVRA.patch | 45 ++++++++ 5 files changed, 323 insertions(+) create mode 100644 package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch create mode 100644 package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch create mode 100644 package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch create mode 100644 package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch create mode 100644 package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch diff --git a/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch b/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch new file mode 100644 index 0000000000..28408d2b4f --- /dev/null +++ b/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch @@ -0,0 +1,102 @@ +From: Arend van Spriel +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: [] 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:[] [] 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: + [] ? brcmf_msgbuf_process_rx+0x404/0x480 [brcmfmac] + [] ? irq_finalize_oneshot.part.30+0xf0/0xf0 + [] brcmf_proto_msgbuf_rx_trigger+0x35/0xf0 [brcmfmac] + [] brcmf_pcie_isr_thread_v2+0x8a/0x130 [brcmfmac] + [] irq_thread_fn+0x20/0x50 + [] irq_thread+0x13f/0x170 + [] ? wake_threads_waitq+0x30/0x30 + [] ? irq_thread_dtor+0xb0/0xb0 + [] kthread+0xd8/0xf0 + [] ? kthread_create_on_node+0x1c0/0x1c0 + [] ret_from_fork+0x58/0x90 + [] ? 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 [] skb_pull+0x5/0x50 + RSP +CR2: 0000000000000080 +---[ end trace b074c0f90e7c997d ]--- + +[1] http://mid.gmane.org/20150430193259.GA5630@googlemail.com + +Cc: # v3.18, v3.19, v4.0, v4.1 +Reported-by: Michael Hornung +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Signed-off-by: Arend van Spriel +--- + +--- 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); diff --git a/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch b/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch new file mode 100644 index 0000000000..f0230347ef --- /dev/null +++ b/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch @@ -0,0 +1,63 @@ +From: Arend van Spriel +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 +Reported-by: Stephen Rothwell +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + +--- 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) diff --git a/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch b/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch new file mode 100644 index 0000000000..2bfd44f998 --- /dev/null +++ b/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch @@ -0,0 +1,56 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +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 +Signed-off-by: Kalle Valo +--- + +--- 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++; diff --git a/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch b/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch new file mode 100644 index 0000000000..0e65114f86 --- /dev/null +++ b/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch @@ -0,0 +1,57 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +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 +Signed-off-by: Kalle Valo +--- + +--- 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++; diff --git a/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch b/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch new file mode 100644 index 0000000000..dc174e5a3d --- /dev/null +++ b/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch @@ -0,0 +1,45 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +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 +Signed-off-by: Kalle Valo +--- + +--- 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; + } + -- 2.30.2