Commit f7005466 authored by Siva Rebbagondla's avatar Siva Rebbagondla Committed by Kalle Valo
Browse files

rsi: fix nommu_map_sg overflow kernel panic



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: default avatarSiva Rebbagondla <siva.rebbagondla@redpinesignals.com>
Signed-off-by: default avatarAmitkumar Karwar <amit.karwar@redpinesignals.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent f0b147b8
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -635,28 +635,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;
@@ -665,20 +669,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)
+14 −7
Original line number Diff line number Diff line
@@ -1038,17 +1038,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,
@@ -1056,7 +1060,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);
@@ -1066,17 +1070,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
@@ -1097,6 +1101,9 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
	 * read write operations to complete for chip reset.
	 */
	msleep(500);
err:
	kfree(data);
	return;
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,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