diff options
author | Hante Meuleman <meuleman@broadcom.com> | 2016-01-19 06:39:24 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2016-01-19 14:27:22 -0500 |
commit | e0045bf80f62779ba75ba04513020d60e59f5298 (patch) | |
tree | 72f7bf06e3501073a34c4aa1cd0f0d19c38dbb2d | |
parent | b7e2d195cc523bd92ed7a64aac089421dbab2a2d (diff) |
brcmfmac: fix sdio sg table alloc crash
With commit 7d34b0560567 ("brcmfmac: Move all module parameters to
one place") a bug was introduced causing a null pointer exception.
This patch fixes the bug by initializing the sg table till after
the settings have been initialized.
Fixes: 7d34b0560567 ("brcmfmac: Move all module parameters to one place")
Reported-by: Marc Zyngier <marc.zyngier@arm.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
3 files changed, 21 insertions, 25 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 53637399bb99..b98db8a0a069 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -879,11 +879,24 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | |||
879 | return 0; | 879 | return 0; |
880 | } | 880 | } |
881 | 881 | ||
882 | static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) | 882 | void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) |
883 | { | 883 | { |
884 | struct sdio_func *func; | ||
885 | struct mmc_host *host; | ||
886 | uint max_blocks; | ||
884 | uint nents; | 887 | uint nents; |
885 | int err; | 888 | int err; |
886 | 889 | ||
890 | func = sdiodev->func[2]; | ||
891 | host = func->card->host; | ||
892 | sdiodev->sg_support = host->max_segs > 1; | ||
893 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
894 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
895 | max_blocks * func->cur_blksize); | ||
896 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
897 | SG_MAX_SINGLE_ALLOC); | ||
898 | sdiodev->max_segment_size = host->max_seg_size; | ||
899 | |||
887 | if (!sdiodev->sg_support) | 900 | if (!sdiodev->sg_support) |
888 | return; | 901 | return; |
889 | 902 | ||
@@ -1021,9 +1034,6 @@ static void brcmf_sdiod_host_fixup(struct mmc_host *host) | |||
1021 | 1034 | ||
1022 | static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | 1035 | static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) |
1023 | { | 1036 | { |
1024 | struct sdio_func *func; | ||
1025 | struct mmc_host *host; | ||
1026 | uint max_blocks; | ||
1027 | int ret = 0; | 1037 | int ret = 0; |
1028 | 1038 | ||
1029 | sdiodev->num_funcs = 2; | 1039 | sdiodev->num_funcs = 2; |
@@ -1054,26 +1064,6 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | |||
1054 | goto out; | 1064 | goto out; |
1055 | } | 1065 | } |
1056 | 1066 | ||
1057 | /* | ||
1058 | * determine host related variables after brcmf_sdiod_probe() | ||
1059 | * as func->cur_blksize is properly set and F2 init has been | ||
1060 | * completed successfully. | ||
1061 | */ | ||
1062 | func = sdiodev->func[2]; | ||
1063 | host = func->card->host; | ||
1064 | sdiodev->sg_support = host->max_segs > 1; | ||
1065 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
1066 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
1067 | max_blocks * func->cur_blksize); | ||
1068 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
1069 | SG_MAX_SINGLE_ALLOC); | ||
1070 | sdiodev->max_segment_size = host->max_seg_size; | ||
1071 | |||
1072 | /* allocate scatter-gather table. sg support | ||
1073 | * will be disabled upon allocation failure. | ||
1074 | */ | ||
1075 | brcmf_sdiod_sgtable_alloc(sdiodev); | ||
1076 | |||
1077 | ret = brcmf_sdiod_freezer_attach(sdiodev); | 1067 | ret = brcmf_sdiod_freezer_attach(sdiodev); |
1078 | if (ret) | 1068 | if (ret) |
1079 | goto out; | 1069 | goto out; |
@@ -1084,7 +1074,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | |||
1084 | ret = -ENODEV; | 1074 | ret = -ENODEV; |
1085 | goto out; | 1075 | goto out; |
1086 | } | 1076 | } |
1087 | brcmf_sdiod_host_fixup(host); | 1077 | brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host); |
1088 | out: | 1078 | out: |
1089 | if (ret) | 1079 | if (ret) |
1090 | brcmf_sdiod_remove(sdiodev); | 1080 | brcmf_sdiod_remove(sdiodev); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index dd6614332836..a14d9d9da094 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | |||
@@ -4114,6 +4114,11 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4114 | goto fail; | 4114 | goto fail; |
4115 | } | 4115 | } |
4116 | 4116 | ||
4117 | /* allocate scatter-gather table. sg support | ||
4118 | * will be disabled upon allocation failure. | ||
4119 | */ | ||
4120 | brcmf_sdiod_sgtable_alloc(bus->sdiodev); | ||
4121 | |||
4117 | /* Query the F2 block size, set roundup accordingly */ | 4122 | /* Query the F2 block size, set roundup accordingly */ |
4118 | bus->blocksize = bus->sdiodev->func[2]->cur_blksize; | 4123 | bus->blocksize = bus->sdiodev->func[2]->cur_blksize; |
4119 | bus->roundup = min(max_roundup, bus->blocksize); | 4124 | bus->roundup = min(max_roundup, bus->blocksize); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h index 5ec7a6d87672..23f223150cef 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | |||
@@ -342,6 +342,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
342 | 342 | ||
343 | /* Issue an abort to the specified function */ | 343 | /* Issue an abort to the specified function */ |
344 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); | 344 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); |
345 | void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev); | ||
345 | void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, | 346 | void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, |
346 | enum brcmf_sdiod_state state); | 347 | enum brcmf_sdiod_state state); |
347 | #ifdef CONFIG_PM_SLEEP | 348 | #ifdef CONFIG_PM_SLEEP |