a92118a19ab8a674b0e3e3c15a8c8b1efcafe515
[oweals/openwrt.git] /
1 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
2 Date: Mon, 18 Nov 2019 11:52:41 +0100
3 Subject: [PATCH FIX] brcmfmac: disable PCIe interrupts before bus reset
4 MIME-Version: 1.0
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
7
8 Keeping interrupts on could result in brcmfmac freeing some resources
9 and then IRQ handlers trying to use them. That was obviously a straight
10 path for crashing a kernel.
11
12 Example:
13 CPU0                           CPU1
14 ----                           ----
15 brcmf_pcie_reset
16   brcmf_pcie_bus_console_read
17   brcmf_detach
18     ...
19     brcmf_fweh_detach
20     brcmf_proto_detach
21                                brcmf_pcie_isr_thread
22                                  ...
23                                  brcmf_proto_msgbuf_rx_trigger
24                                    ...
25                                    drvr->proto->pd
26     brcmf_pcie_release_irq
27
28 [  363.789218] Unable to handle kernel NULL pointer dereference at virtual address 00000038
29 [  363.797339] pgd = c0004000
30 [  363.800050] [00000038] *pgd=00000000
31 [  363.803635] Internal error: Oops: 17 [#1] SMP ARM
32 (...)
33 [  364.029209] Backtrace:
34 [  364.031725] [<bf243838>] (brcmf_proto_msgbuf_rx_trigger [brcmfmac]) from [<bf2471dc>] (brcmf_pcie_isr_thread+0x228/0x274 [brcmfmac])
35 [  364.043662]  r7:00000001 r6:c8ca0000 r5:00010000 r4:c7b4f800
36
37 Fixes: 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash")
38 Cc: stable@vger.kernel.org # v5.2+
39 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
40 ---
41  drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 2 ++
42  1 file changed, 2 insertions(+)
43
44 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
45 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
46 @@ -1427,6 +1427,8 @@ static int brcmf_pcie_reset(struct devic
47         struct brcmf_fw_request *fwreq;
48         int err;
49  
50 +       brcmf_pcie_intr_disable(devinfo);
51 +
52         brcmf_pcie_bus_console_read(devinfo, true);
53  
54         brcmf_detach(dev);