Skip to content

Commit

Permalink
brcmfmac: fix sdio sg table alloc crash
Browse files Browse the repository at this point in the history
With commit 7d34b05 ("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: 7d34b05 ("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>
  • Loading branch information
Hante Meuleman authored and Kalle Valo committed Jan 19, 2016
1 parent b7e2d19 commit e0045bf
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 25 deletions.
40 changes: 15 additions & 25 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,11 +879,24 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
return 0;
}

static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
{
struct sdio_func *func;
struct mmc_host *host;
uint max_blocks;
uint nents;
int err;

func = sdiodev->func[2];
host = func->card->host;
sdiodev->sg_support = host->max_segs > 1;
max_blocks = min_t(uint, host->max_blk_count, 511u);
sdiodev->max_request_size = min_t(uint, host->max_req_size,
max_blocks * func->cur_blksize);
sdiodev->max_segment_count = min_t(uint, host->max_segs,
SG_MAX_SINGLE_ALLOC);
sdiodev->max_segment_size = host->max_seg_size;

if (!sdiodev->sg_support)
return;

Expand Down Expand Up @@ -1021,9 +1034,6 @@ static void brcmf_sdiod_host_fixup(struct mmc_host *host)

static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
{
struct sdio_func *func;
struct mmc_host *host;
uint max_blocks;
int ret = 0;

sdiodev->num_funcs = 2;
Expand Down Expand Up @@ -1054,26 +1064,6 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
goto out;
}

/*
* determine host related variables after brcmf_sdiod_probe()
* as func->cur_blksize is properly set and F2 init has been
* completed successfully.
*/
func = sdiodev->func[2];
host = func->card->host;
sdiodev->sg_support = host->max_segs > 1;
max_blocks = min_t(uint, host->max_blk_count, 511u);
sdiodev->max_request_size = min_t(uint, host->max_req_size,
max_blocks * func->cur_blksize);
sdiodev->max_segment_count = min_t(uint, host->max_segs,
SG_MAX_SINGLE_ALLOC);
sdiodev->max_segment_size = host->max_seg_size;

/* allocate scatter-gather table. sg support
* will be disabled upon allocation failure.
*/
brcmf_sdiod_sgtable_alloc(sdiodev);

ret = brcmf_sdiod_freezer_attach(sdiodev);
if (ret)
goto out;
Expand All @@ -1084,7 +1074,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
ret = -ENODEV;
goto out;
}
brcmf_sdiod_host_fixup(host);
brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host);
out:
if (ret)
brcmf_sdiod_remove(sdiodev);
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -4114,6 +4114,11 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
goto fail;
}

/* allocate scatter-gather table. sg support
* will be disabled upon allocation failure.
*/
brcmf_sdiod_sgtable_alloc(bus->sdiodev);

/* Query the F2 block size, set roundup accordingly */
bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
bus->roundup = min(max_roundup, bus->blocksize);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,

/* Issue an abort to the specified function */
int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
enum brcmf_sdiod_state state);
#ifdef CONFIG_PM_SLEEP
Expand Down

0 comments on commit e0045bf

Please sign in to comment.