Commit 40b717bf authored by Ajay.Kathat@microchip.com's avatar Ajay.Kathat@microchip.com Committed by Kalle Valo

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: 5625f965 ("wilc1000: move wilc driver out of staging")
Reported-by: default avatarMichael Walle <mwalle@kernel.org>
Suggested-by: default avatarMichael Walle <mwalle@kernel.org>
Signed-off-by: default avatarAjay Singh <ajay.kathat@microchip.com>
Reviewed-by: default avatarMichael Walle <mwalle@kernel.org>
Tested-by: default avatarMichael Walle <mwalle@kernel.org>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220809075749.62752-1-ajay.kathat@microchip.com
parent fa3fbe64
...@@ -245,6 +245,7 @@ struct wilc { ...@@ -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 { ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 @@ static int wilc_sdio_probe(struct sdio_func *func, ...@@ -161,6 +182,7 @@ static int wilc_sdio_probe(struct sdio_func *func,
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment