lkml.org 
[lkml]   [2022]   [Sep]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.19 095/192] wifi: wilc1000: fix DMA on stack objects
    Date
    From: Ajay.Kathat@microchip.com <Ajay.Kathat@microchip.com>

    [ Upstream commit 40b717bfcefab28a0656b8caa5e43d5449e5a671 ]

    Sometimes 'wilc_sdio_cmd53' is called with addresses pointing to an
    object on the stack. Use dynamically allocated memory for cmd53 instead
    of stack address which is not DMA'able.

    Fixes: 5625f965d764 ("wilc1000: move wilc driver out of staging")
    Reported-by: Michael Walle <mwalle@kernel.org>
    Suggested-by: Michael Walle <mwalle@kernel.org>
    Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
    Reviewed-by: Michael Walle <mwalle@kernel.org>
    Tested-by: Michael Walle <mwalle@kernel.org>
    Signed-off-by: Kalle Valo <kvalo@kernel.org>
    Link: https://lore.kernel.org/r/20220809075749.62752-1-ajay.kathat@microchip.com
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    .../net/wireless/microchip/wilc1000/netdev.h | 1 +
    .../net/wireless/microchip/wilc1000/sdio.c | 39 ++++++++++++++++---
    .../net/wireless/microchip/wilc1000/wlan.c | 15 ++++++-
    3 files changed, 47 insertions(+), 8 deletions(-)

    diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h
    index a067274c20144..bf001e9def6aa 100644
    --- a/drivers/net/wireless/microchip/wilc1000/netdev.h
    +++ b/drivers/net/wireless/microchip/wilc1000/netdev.h
    @@ -254,6 +254,7 @@ struct wilc {
    u8 *rx_buffer;
    u32 rx_buffer_offset;
    u8 *tx_buffer;
    + u32 *vmm_table;

    struct txq_handle txq[NQUEUES];
    int txq_entries;
    diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
    index 7962c11cfe848..56f924a31bc66 100644
    --- a/drivers/net/wireless/microchip/wilc1000/sdio.c
    +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
    @@ -27,6 +27,7 @@ struct wilc_sdio {
    bool irq_gpio;
    u32 block_size;
    int has_thrpt_enh3;
    + u8 *cmd53_buf;
    };

    struct sdio_cmd52 {
    @@ -46,6 +47,7 @@ struct sdio_cmd53 {
    u32 count: 9;
    u8 *buffer;
    u32 block_size;
    + bool use_global_buf;
    };

    static const struct wilc_hif_func wilc_hif_sdio;
    @@ -90,6 +92,8 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
    {
    struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
    int size, ret;
    + struct wilc_sdio *sdio_priv = wilc->bus_data;
    + u8 *buf = cmd->buffer;

    sdio_claim_host(func);

    @@ -100,12 +104,23 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
    else
    size = cmd->count;

    + if (cmd->use_global_buf) {
    + if (size > sizeof(u32))
    + return -EINVAL;
    +
    + buf = sdio_priv->cmd53_buf;
    + }
    +
    if (cmd->read_write) { /* write */
    - ret = sdio_memcpy_toio(func, cmd->address,
    - (void *)cmd->buffer, size);
    + if (cmd->use_global_buf)
    + memcpy(buf, cmd->buffer, size);
    +
    + ret = sdio_memcpy_toio(func, cmd->address, buf, size);
    } else { /* read */
    - ret = sdio_memcpy_fromio(func, (void *)cmd->buffer,
    - cmd->address, size);
    + ret = sdio_memcpy_fromio(func, buf, cmd->address, size);
    +
    + if (cmd->use_global_buf)
    + memcpy(cmd->buffer, buf, size);
    }

    sdio_release_host(func);
    @@ -127,6 +142,12 @@ static int wilc_sdio_probe(struct sdio_func *func,
    if (!sdio_priv)
    return -ENOMEM;

    + sdio_priv->cmd53_buf = kzalloc(sizeof(u32), GFP_KERNEL);
    + if (!sdio_priv->cmd53_buf) {
    + ret = -ENOMEM;
    + goto free;
    + }
    +
    ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
    &wilc_hif_sdio);
    if (ret)
    @@ -160,6 +181,7 @@ static int wilc_sdio_probe(struct sdio_func *func,
    irq_dispose_mapping(wilc->dev_irq_num);
    wilc_netdev_cleanup(wilc);
    free:
    + kfree(sdio_priv->cmd53_buf);
    kfree(sdio_priv);
    return ret;
    }
    @@ -171,6 +193,7 @@ static void wilc_sdio_remove(struct sdio_func *func)

    clk_disable_unprepare(wilc->rtc_clk);
    wilc_netdev_cleanup(wilc);
    + kfree(sdio_priv->cmd53_buf);
    kfree(sdio_priv);
    }

    @@ -367,8 +390,9 @@ static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
    cmd.address = WILC_SDIO_FBR_DATA_REG;
    cmd.block_mode = 0;
    cmd.increment = 1;
    - cmd.count = 4;
    + cmd.count = sizeof(u32);
    cmd.buffer = (u8 *)&data;
    + cmd.use_global_buf = true;
    cmd.block_size = sdio_priv->block_size;
    ret = wilc_sdio_cmd53(wilc, &cmd);
    if (ret)
    @@ -406,6 +430,7 @@ static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
    nblk = size / block_size;
    nleft = size % block_size;

    + cmd.use_global_buf = false;
    if (nblk > 0) {
    cmd.block_mode = 1;
    cmd.increment = 1;
    @@ -484,8 +509,9 @@ static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
    cmd.address = WILC_SDIO_FBR_DATA_REG;
    cmd.block_mode = 0;
    cmd.increment = 1;
    - cmd.count = 4;
    + cmd.count = sizeof(u32);
    cmd.buffer = (u8 *)data;
    + cmd.use_global_buf = true;

    cmd.block_size = sdio_priv->block_size;
    ret = wilc_sdio_cmd53(wilc, &cmd);
    @@ -527,6 +553,7 @@ static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
    nblk = size / block_size;
    nleft = size % block_size;

    + cmd.use_global_buf = false;
    if (nblk > 0) {
    cmd.block_mode = 1;
    cmd.increment = 1;
    diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
    index 48441f0389ca1..0c8a571486d25 100644
    --- a/drivers/net/wireless/microchip/wilc1000/wlan.c
    +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
    @@ -714,7 +714,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
    int ret = 0;
    int counter;
    int timeout;
    - u32 vmm_table[WILC_VMM_TBL_SIZE];
    + u32 *vmm_table = wilc->vmm_table;
    u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};
    const struct wilc_hif_func *func;
    int srcu_idx;
    @@ -1251,6 +1251,8 @@ void wilc_wlan_cleanup(struct net_device *dev)
    while ((rqe = wilc_wlan_rxq_remove(wilc)))
    kfree(rqe);

    + kfree(wilc->vmm_table);
    + wilc->vmm_table = NULL;
    kfree(wilc->rx_buffer);
    wilc->rx_buffer = NULL;
    kfree(wilc->tx_buffer);
    @@ -1485,6 +1487,14 @@ int wilc_wlan_init(struct net_device *dev)
    goto fail;
    }

    + if (!wilc->vmm_table)
    + wilc->vmm_table = kzalloc(WILC_VMM_TBL_SIZE, GFP_KERNEL);
    +
    + if (!wilc->vmm_table) {
    + ret = -ENOBUFS;
    + goto fail;
    + }
    +
    if (!wilc->tx_buffer)
    wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);

    @@ -1509,7 +1519,8 @@ int wilc_wlan_init(struct net_device *dev)
    return 0;

    fail:
    -
    + kfree(wilc->vmm_table);
    + wilc->vmm_table = NULL;
    kfree(wilc->rx_buffer);
    wilc->rx_buffer = NULL;
    kfree(wilc->tx_buffer);
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-09-13 16:21    [W:4.106 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site