wifi: wilc1000: fix DMA on stack objects
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
This commit is contained in:
parent
fa3fbe6403
commit
40b717bfce
@ -245,6 +245,7 @@ struct wilc {
|
|||||||
u8 *rx_buffer;
|
u8 *rx_buffer;
|
||||||
u32 rx_buffer_offset;
|
u32 rx_buffer_offset;
|
||||||
u8 *tx_buffer;
|
u8 *tx_buffer;
|
||||||
|
u32 *vmm_table;
|
||||||
|
|
||||||
struct txq_handle txq[NQUEUES];
|
struct txq_handle txq[NQUEUES];
|
||||||
int txq_entries;
|
int txq_entries;
|
||||||
|
@ -28,6 +28,7 @@ struct wilc_sdio {
|
|||||||
u32 block_size;
|
u32 block_size;
|
||||||
bool isinit;
|
bool isinit;
|
||||||
int has_thrpt_enh3;
|
int has_thrpt_enh3;
|
||||||
|
u8 *cmd53_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sdio_cmd52 {
|
struct sdio_cmd52 {
|
||||||
@ -47,6 +48,7 @@ struct sdio_cmd53 {
|
|||||||
u32 count: 9;
|
u32 count: 9;
|
||||||
u8 *buffer;
|
u8 *buffer;
|
||||||
u32 block_size;
|
u32 block_size;
|
||||||
|
bool use_global_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct wilc_hif_func wilc_hif_sdio;
|
static const struct wilc_hif_func wilc_hif_sdio;
|
||||||
@ -91,6 +93,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);
|
struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
|
||||||
int size, ret;
|
int size, ret;
|
||||||
|
struct wilc_sdio *sdio_priv = wilc->bus_data;
|
||||||
|
u8 *buf = cmd->buffer;
|
||||||
|
|
||||||
sdio_claim_host(func);
|
sdio_claim_host(func);
|
||||||
|
|
||||||
@ -101,12 +105,23 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
|
|||||||
else
|
else
|
||||||
size = cmd->count;
|
size = cmd->count;
|
||||||
|
|
||||||
|
if (cmd->use_global_buf) {
|
||||||
|
if (size > sizeof(u32))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
buf = sdio_priv->cmd53_buf;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->read_write) { /* write */
|
if (cmd->read_write) { /* write */
|
||||||
ret = sdio_memcpy_toio(func, cmd->address,
|
if (cmd->use_global_buf)
|
||||||
(void *)cmd->buffer, size);
|
memcpy(buf, cmd->buffer, size);
|
||||||
|
|
||||||
|
ret = sdio_memcpy_toio(func, cmd->address, buf, size);
|
||||||
} else { /* read */
|
} else { /* read */
|
||||||
ret = sdio_memcpy_fromio(func, (void *)cmd->buffer,
|
ret = sdio_memcpy_fromio(func, buf, cmd->address, size);
|
||||||
cmd->address, size);
|
|
||||||
|
if (cmd->use_global_buf)
|
||||||
|
memcpy(cmd->buffer, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
sdio_release_host(func);
|
sdio_release_host(func);
|
||||||
@ -128,6 +143,12 @@ static int wilc_sdio_probe(struct sdio_func *func,
|
|||||||
if (!sdio_priv)
|
if (!sdio_priv)
|
||||||
return -ENOMEM;
|
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,
|
ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
|
||||||
&wilc_hif_sdio);
|
&wilc_hif_sdio);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -161,6 +182,7 @@ dispose_irq:
|
|||||||
irq_dispose_mapping(wilc->dev_irq_num);
|
irq_dispose_mapping(wilc->dev_irq_num);
|
||||||
wilc_netdev_cleanup(wilc);
|
wilc_netdev_cleanup(wilc);
|
||||||
free:
|
free:
|
||||||
|
kfree(sdio_priv->cmd53_buf);
|
||||||
kfree(sdio_priv);
|
kfree(sdio_priv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -172,6 +194,7 @@ static void wilc_sdio_remove(struct sdio_func *func)
|
|||||||
|
|
||||||
clk_disable_unprepare(wilc->rtc_clk);
|
clk_disable_unprepare(wilc->rtc_clk);
|
||||||
wilc_netdev_cleanup(wilc);
|
wilc_netdev_cleanup(wilc);
|
||||||
|
kfree(sdio_priv->cmd53_buf);
|
||||||
kfree(sdio_priv);
|
kfree(sdio_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,8 +398,9 @@ static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
|
|||||||
cmd.address = WILC_SDIO_FBR_DATA_REG;
|
cmd.address = WILC_SDIO_FBR_DATA_REG;
|
||||||
cmd.block_mode = 0;
|
cmd.block_mode = 0;
|
||||||
cmd.increment = 1;
|
cmd.increment = 1;
|
||||||
cmd.count = 4;
|
cmd.count = sizeof(u32);
|
||||||
cmd.buffer = (u8 *)&data;
|
cmd.buffer = (u8 *)&data;
|
||||||
|
cmd.use_global_buf = true;
|
||||||
cmd.block_size = sdio_priv->block_size;
|
cmd.block_size = sdio_priv->block_size;
|
||||||
ret = wilc_sdio_cmd53(wilc, &cmd);
|
ret = wilc_sdio_cmd53(wilc, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -414,6 +438,7 @@ static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
|
|||||||
nblk = size / block_size;
|
nblk = size / block_size;
|
||||||
nleft = size % block_size;
|
nleft = size % block_size;
|
||||||
|
|
||||||
|
cmd.use_global_buf = false;
|
||||||
if (nblk > 0) {
|
if (nblk > 0) {
|
||||||
cmd.block_mode = 1;
|
cmd.block_mode = 1;
|
||||||
cmd.increment = 1;
|
cmd.increment = 1;
|
||||||
@ -492,8 +517,9 @@ static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
|
|||||||
cmd.address = WILC_SDIO_FBR_DATA_REG;
|
cmd.address = WILC_SDIO_FBR_DATA_REG;
|
||||||
cmd.block_mode = 0;
|
cmd.block_mode = 0;
|
||||||
cmd.increment = 1;
|
cmd.increment = 1;
|
||||||
cmd.count = 4;
|
cmd.count = sizeof(u32);
|
||||||
cmd.buffer = (u8 *)data;
|
cmd.buffer = (u8 *)data;
|
||||||
|
cmd.use_global_buf = true;
|
||||||
|
|
||||||
cmd.block_size = sdio_priv->block_size;
|
cmd.block_size = sdio_priv->block_size;
|
||||||
ret = wilc_sdio_cmd53(wilc, &cmd);
|
ret = wilc_sdio_cmd53(wilc, &cmd);
|
||||||
@ -535,6 +561,7 @@ static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
|
|||||||
nblk = size / block_size;
|
nblk = size / block_size;
|
||||||
nleft = size % block_size;
|
nleft = size % block_size;
|
||||||
|
|
||||||
|
cmd.use_global_buf = false;
|
||||||
if (nblk > 0) {
|
if (nblk > 0) {
|
||||||
cmd.block_mode = 1;
|
cmd.block_mode = 1;
|
||||||
cmd.increment = 1;
|
cmd.increment = 1;
|
||||||
|
@ -714,7 +714,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
int counter;
|
int counter;
|
||||||
int timeout;
|
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};
|
u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};
|
||||||
const struct wilc_hif_func *func;
|
const struct wilc_hif_func *func;
|
||||||
int srcu_idx;
|
int srcu_idx;
|
||||||
@ -1252,6 +1252,8 @@ void wilc_wlan_cleanup(struct net_device *dev)
|
|||||||
while ((rqe = wilc_wlan_rxq_remove(wilc)))
|
while ((rqe = wilc_wlan_rxq_remove(wilc)))
|
||||||
kfree(rqe);
|
kfree(rqe);
|
||||||
|
|
||||||
|
kfree(wilc->vmm_table);
|
||||||
|
wilc->vmm_table = NULL;
|
||||||
kfree(wilc->rx_buffer);
|
kfree(wilc->rx_buffer);
|
||||||
wilc->rx_buffer = NULL;
|
wilc->rx_buffer = NULL;
|
||||||
kfree(wilc->tx_buffer);
|
kfree(wilc->tx_buffer);
|
||||||
@ -1489,6 +1491,14 @@ int wilc_wlan_init(struct net_device *dev)
|
|||||||
goto fail;
|
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)
|
if (!wilc->tx_buffer)
|
||||||
wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);
|
wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);
|
||||||
|
|
||||||
@ -1513,7 +1523,8 @@ int wilc_wlan_init(struct net_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
kfree(wilc->vmm_table);
|
||||||
|
wilc->vmm_table = NULL;
|
||||||
kfree(wilc->rx_buffer);
|
kfree(wilc->rx_buffer);
|
||||||
wilc->rx_buffer = NULL;
|
wilc->rx_buffer = NULL;
|
||||||
kfree(wilc->tx_buffer);
|
kfree(wilc->tx_buffer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user