rsi: fix nommu_map_sg overflow kernel panic
[ Upstream commit f700546682a62a87a9615121a37ee7452dab4b76 ] Following overflow kernel panic is observed on some platforms while loading the driver. It is fixed if dynamically allocated memory is passed to SDIO instead of static one [ 927.513963] nommu_map_sg: overflow 17d54064ba7c+20 of device mask ffffffff [ 927.517712] Modules linked in: rsi_sdio(+) cmac bnep arc4 rsi_91x mac80211 cfg80211 btrsi rfcomm bluetooth ecdh_generic snd_soc_sst_bytcr_rt5660 [ 927.517861] CPU: 0 PID: 1624 Comm: insmod Tainted: G W 4.15.0-1000 #1 [ 927.517870] RIP: 0010:sdhci_send_command+0x5f0/0xa90 [sdhci] [ 927.517873] RSP: 0000:ffffac3fc064b6d8 EFLAGS: 00010086 [ 927.517895] Call Trace: [ 927.517908] ? __schedule+0x3cd/0x890 [ 927.517915] ? mod_timer+0x17b/0x3c0 [ 927.517922] sdhci_request+0x7c/0xf0 [sdhci] [ 927.517928] __mmc_start_request+0x5a/0x170 [ 927.517932] mmc_start_request+0x74/0x90 [ 927.517936] mmc_wait_for_req+0x87/0xe0 [ 927.517940] mmc_io_rw_extended+0x2fd/0x330 [ 927.517946] ? mmc_wait_data_done+0x30/0x30 [ 927.517951] sdio_io_rw_ext_helper+0x160/0x210 [ 927.517956] sdio_writesb+0x1d/0x20 [ 927.517966] rsi_sdio_write_register_multiple+0x68/0x110 [rsi_sdio] [ 927.517976] rsi_hal_device_init+0x357/0x910 [rsi_91x] [ 927.517983] ? rsi_hal_device_init+0x357/0x910 [rsi_91x] [ 927.517990] rsi_probe+0x2c6/0x450 [rsi_sdio] [ 927.517995] sdio_bus_probe+0xfc/0x110 [ 927.518000] driver_probe_device+0x2b3/0x490 [ 927.518005] __driver_attach+0xdf/0xf0 [ 927.518008] ? driver_probe_device+0x490/0x490 [ 927.518014] bus_for_each_dev+0x6c/0xc0 [ 927.518018] driver_attach+0x1e/0x20 [ 927.518021] bus_add_driver+0x1f4/0x270 [ 927.518028] ? rsi_sdio_ack_intr+0x50/0x50 [rsi_sdio] [ 927.518031] driver_register+0x60/0xe0 [ 927.518038] ? rsi_sdio_ack_intr+0x50/0x50 [rsi_sdio] [ 927.518041] sdio_register_driver+0x20/0x30 [ 927.518047] rsi_module_init+0x16/0x40 [rsi_sdio] Signed-off-by: Siva Rebbagondla <siva.rebbagondla@redpinesignals.com> Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0be8aa812c
commit
e7cb8f11f6
drivers/net/wireless/rsi
@ -557,28 +557,32 @@ static int bl_write_header(struct rsi_hw *adapter, u8 *flash_content,
|
||||
u32 content_size)
|
||||
{
|
||||
struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
|
||||
struct bl_header bl_hdr;
|
||||
struct bl_header *bl_hdr;
|
||||
u32 write_addr, write_len;
|
||||
int status;
|
||||
|
||||
bl_hdr.flags = 0;
|
||||
bl_hdr.image_no = cpu_to_le32(adapter->priv->coex_mode);
|
||||
bl_hdr.check_sum = cpu_to_le32(
|
||||
*(u32 *)&flash_content[CHECK_SUM_OFFSET]);
|
||||
bl_hdr.flash_start_address = cpu_to_le32(
|
||||
*(u32 *)&flash_content[ADDR_OFFSET]);
|
||||
bl_hdr.flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
|
||||
bl_hdr = kzalloc(sizeof(*bl_hdr), GFP_KERNEL);
|
||||
if (!bl_hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
bl_hdr->flags = 0;
|
||||
bl_hdr->image_no = cpu_to_le32(adapter->priv->coex_mode);
|
||||
bl_hdr->check_sum =
|
||||
cpu_to_le32(*(u32 *)&flash_content[CHECK_SUM_OFFSET]);
|
||||
bl_hdr->flash_start_address =
|
||||
cpu_to_le32(*(u32 *)&flash_content[ADDR_OFFSET]);
|
||||
bl_hdr->flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
|
||||
write_len = sizeof(struct bl_header);
|
||||
|
||||
if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
|
||||
write_addr = PING_BUFFER_ADDRESS;
|
||||
status = hif_ops->write_reg_multiple(adapter, write_addr,
|
||||
(u8 *)&bl_hdr, write_len);
|
||||
(u8 *)bl_hdr, write_len);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Failed to load Version/CRC structure\n",
|
||||
__func__);
|
||||
return status;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
write_addr = PING_BUFFER_ADDRESS >> 16;
|
||||
@ -587,20 +591,23 @@ static int bl_write_header(struct rsi_hw *adapter, u8 *flash_content,
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Unable to set ms word to common reg\n",
|
||||
__func__);
|
||||
return status;
|
||||
goto fail;
|
||||
}
|
||||
write_addr = RSI_SD_REQUEST_MASTER |
|
||||
(PING_BUFFER_ADDRESS & 0xFFFF);
|
||||
status = hif_ops->write_reg_multiple(adapter, write_addr,
|
||||
(u8 *)&bl_hdr, write_len);
|
||||
(u8 *)bl_hdr, write_len);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Failed to load Version/CRC structure\n",
|
||||
__func__);
|
||||
return status;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
status = 0;
|
||||
fail:
|
||||
kfree(bl_hdr);
|
||||
return status;
|
||||
}
|
||||
|
||||
static u32 read_flash_capacity(struct rsi_hw *adapter)
|
||||
|
@ -968,17 +968,21 @@ static void ulp_read_write(struct rsi_hw *adapter, u16 addr, u32 data,
|
||||
/*This function resets and re-initializes the chip.*/
|
||||
static void rsi_reset_chip(struct rsi_hw *adapter)
|
||||
{
|
||||
__le32 data;
|
||||
u8 *data;
|
||||
u8 sdio_interrupt_status = 0;
|
||||
u8 request = 1;
|
||||
int ret;
|
||||
|
||||
data = kzalloc(sizeof(u32), GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
rsi_dbg(INFO_ZONE, "Writing disable to wakeup register\n");
|
||||
ret = rsi_sdio_write_register(adapter, 0, SDIO_WAKEUP_REG, &request);
|
||||
if (ret < 0) {
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Failed to write SDIO wakeup register\n", __func__);
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
msleep(20);
|
||||
ret = rsi_sdio_read_register(adapter, RSI_FN1_INT_REGISTER,
|
||||
@ -986,7 +990,7 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
|
||||
if (ret < 0) {
|
||||
rsi_dbg(ERR_ZONE, "%s: Failed to Read Intr Status Register\n",
|
||||
__func__);
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
rsi_dbg(INFO_ZONE, "%s: Intr Status Register value = %d\n",
|
||||
__func__, sdio_interrupt_status);
|
||||
@ -996,17 +1000,17 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Unable to set ms word to common reg\n",
|
||||
__func__);
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
|
||||
data = TA_HOLD_THREAD_VALUE;
|
||||
put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
|
||||
if (rsi_sdio_write_register_multiple(adapter, TA_HOLD_THREAD_REG |
|
||||
RSI_SD_REQUEST_MASTER,
|
||||
(u8 *)&data, 4)) {
|
||||
data, 4)) {
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Unable to hold Thread-Arch processor threads\n",
|
||||
__func__);
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* This msleep will ensure Thread-Arch processor to go to hold
|
||||
@ -1027,6 +1031,9 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
|
||||
* read write operations to complete for chip reset.
|
||||
*/
|
||||
msleep(500);
|
||||
err:
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +85,7 @@ enum sdio_interrupt_type {
|
||||
#define TA_SOFT_RST_CLR 0
|
||||
#define TA_SOFT_RST_SET BIT(0)
|
||||
#define TA_PC_ZERO 0
|
||||
#define TA_HOLD_THREAD_VALUE cpu_to_le32(0xF)
|
||||
#define TA_HOLD_THREAD_VALUE 0xF
|
||||
#define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF)
|
||||
#define TA_BASE_ADDR 0x2200
|
||||
#define MISC_CFG_BASE_ADDR 0x4105
|
||||
|
Loading…
x
Reference in New Issue
Block a user