summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2016-01-19 06:39:24 -0500
committerKalle Valo <kvalo@codeaurora.org>2016-01-19 14:27:22 -0500
commite0045bf80f62779ba75ba04513020d60e59f5298 (patch)
tree72f7bf06e3501073a34c4aa1cd0f0d19c38dbb2d
parentb7e2d195cc523bd92ed7a64aac089421dbab2a2d (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>
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c40
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h1
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
882static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) 882void 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
1022static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) 1035static 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);
1088out: 1078out:
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 */
344int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); 344int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
345void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
345void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, 346void 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