1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Tue, 19 Jan 2016 12:39:24 +0100
3 Subject: [PATCH] brcmfmac: fix sdio sg table alloc crash
5 With commit 7d34b0560567 ("brcmfmac: Move all module parameters to
6 one place") a bug was introduced causing a null pointer exception.
7 This patch fixes the bug by initializing the sg table till after
8 the settings have been initialized.
10 Fixes: 7d34b0560567 ("brcmfmac: Move all module parameters to one place")
11 Reported-by: Marc Zyngier <marc.zyngier@arm.com>
12 Tested-by: Marc Zyngier <marc.zyngier@arm.com>
13 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
14 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
15 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
16 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
17 Signed-off-by: Arend van Spriel <arend@broadcom.com>
18 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
21 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
22 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
23 @@ -879,11 +879,24 @@ int brcmf_sdiod_abort(struct brcmf_sdio_
27 -static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
28 +void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
30 + struct sdio_func *func;
31 + struct mmc_host *host;
36 + func = sdiodev->func[2];
37 + host = func->card->host;
38 + sdiodev->sg_support = host->max_segs > 1;
39 + max_blocks = min_t(uint, host->max_blk_count, 511u);
40 + sdiodev->max_request_size = min_t(uint, host->max_req_size,
41 + max_blocks * func->cur_blksize);
42 + sdiodev->max_segment_count = min_t(uint, host->max_segs,
43 + SG_MAX_SINGLE_ALLOC);
44 + sdiodev->max_segment_size = host->max_seg_size;
46 if (!sdiodev->sg_support)
49 @@ -1021,9 +1034,6 @@ static void brcmf_sdiod_host_fixup(struc
51 static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
53 - struct sdio_func *func;
54 - struct mmc_host *host;
58 sdiodev->num_funcs = 2;
59 @@ -1054,26 +1064,6 @@ static int brcmf_sdiod_probe(struct brcm
64 - * determine host related variables after brcmf_sdiod_probe()
65 - * as func->cur_blksize is properly set and F2 init has been
66 - * completed successfully.
68 - func = sdiodev->func[2];
69 - host = func->card->host;
70 - sdiodev->sg_support = host->max_segs > 1;
71 - max_blocks = min_t(uint, host->max_blk_count, 511u);
72 - sdiodev->max_request_size = min_t(uint, host->max_req_size,
73 - max_blocks * func->cur_blksize);
74 - sdiodev->max_segment_count = min_t(uint, host->max_segs,
75 - SG_MAX_SINGLE_ALLOC);
76 - sdiodev->max_segment_size = host->max_seg_size;
78 - /* allocate scatter-gather table. sg support
79 - * will be disabled upon allocation failure.
81 - brcmf_sdiod_sgtable_alloc(sdiodev);
83 ret = brcmf_sdiod_freezer_attach(sdiodev);
86 @@ -1084,7 +1074,7 @@ static int brcmf_sdiod_probe(struct brcm
90 - brcmf_sdiod_host_fixup(host);
91 + brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host);
94 brcmf_sdiod_remove(sdiodev);
95 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
96 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
97 @@ -4114,6 +4114,11 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
101 + /* allocate scatter-gather table. sg support
102 + * will be disabled upon allocation failure.
104 + brcmf_sdiod_sgtable_alloc(bus->sdiodev);
106 /* Query the F2 block size, set roundup accordingly */
107 bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
108 bus->roundup = min(max_roundup, bus->blocksize);
109 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
110 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
111 @@ -342,6 +342,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
113 /* Issue an abort to the specified function */
114 int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
115 +void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
116 void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
117 enum brcmf_sdiod_state state);
118 #ifdef CONFIG_PM_SLEEP