rsi: fix kernel panic observed on 64bit machine
[ Upstream commit 864db4d5085349fcfa1f260b5bcd2adde3d7f2ed ] Following kernel panic is observed on 64bit machine while loading the driver. It is fixed if we pass dynamically allocated memory to SDIO for DMA. BUG: unable to handle kernel paging request at ffffeb04000172e0 IP: sg_miter_stop+0x56/0x70 PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI Modules linked in: rsi_sdio(OE+) rsi_91x(OE) btrsi(OE) rfcomm bluetooth ecdh_generic mac80211 mmc_block fuse xt_CHECKSUM iptable_mangle drm_kms_helper mmc_core serio_raw drm firewire_ohci tg3 CPU: 0 PID: 4003 Comm: insmod Tainted: G OE 4.16.0-rc1+ #27 Hardware name: Dell Inc. Latitude E5500 /0DW634, BIOS A19 06/13/2013 RIP: 0010:sg_miter_stop+0x56/0x70 RSP: 0018:ffff88007d003e78 EFLAGS: 00010002 RAX: 0000000000000003 RBX: 0000000000000004 RCX: 0000000000000000 RDX: ffffeb04000172c0 RSI: ffff88002f58002c RDI: ffff88007d003e80 RBP: 0000000000000004 R08: ffff88007d003e80 R09: 0000000000000008 R10: 0000000000000003 R11: 0000000000000001 R12: 0000000000000004 R13: ffff88002f580028 R14: 0000000000000000 R15: 0000000000000004 FS: 00007f35c29db700(0000) GS:ffff88007d000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffeb04000172e0 CR3: 000000007038e000 CR4: 00000000000406f0 Call Trace: <IRQ> sg_copy_buffer+0xc6/0xf0 sdhci_tasklet_finish+0x170/0x260 [sdhci] tasklet_action+0xf4/0x100 __do_softirq+0xef/0x26e irq_exit+0xbe/0xd0 do_IRQ+0x4a/0xc0 common_interrupt+0xa2/0xa2 </IRQ> 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
31dbd9cfcb
commit
b652092f8e
@ -636,11 +636,14 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
|
||||
u32 *read_buf, u16 size)
|
||||
{
|
||||
u32 addr_on_bus, *data;
|
||||
u32 align[2] = {};
|
||||
u16 ms_addr;
|
||||
int status;
|
||||
|
||||
data = PTR_ALIGN(&align[0], 8);
|
||||
data = kzalloc(RSI_MASTER_REG_BUF_SIZE, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data = PTR_ALIGN(data, 8);
|
||||
|
||||
ms_addr = (addr >> 16);
|
||||
status = rsi_sdio_master_access_msword(adapter, ms_addr);
|
||||
@ -648,7 +651,7 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Unable to set ms word to common reg\n",
|
||||
__func__);
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
addr &= 0xFFFF;
|
||||
|
||||
@ -666,7 +669,7 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
|
||||
(u8 *)data, 4);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
if (size == 2) {
|
||||
if ((addr & 0x3) == 0)
|
||||
@ -688,17 +691,23 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
|
||||
*read_buf = *data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
|
||||
unsigned long addr,
|
||||
unsigned long data, u16 size)
|
||||
{
|
||||
unsigned long data1[2], *data_aligned;
|
||||
unsigned long *data_aligned;
|
||||
int status;
|
||||
|
||||
data_aligned = PTR_ALIGN(&data1[0], 8);
|
||||
data_aligned = kzalloc(RSI_MASTER_REG_BUF_SIZE, GFP_KERNEL);
|
||||
if (!data_aligned)
|
||||
return -ENOMEM;
|
||||
|
||||
data_aligned = PTR_ALIGN(data_aligned, 8);
|
||||
|
||||
if (size == 2) {
|
||||
*data_aligned = ((data << 16) | (data & 0xFFFF));
|
||||
@ -717,6 +726,7 @@ static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Unable to set ms word to common reg\n",
|
||||
__func__);
|
||||
kfree(data_aligned);
|
||||
return -EIO;
|
||||
}
|
||||
addr = addr & 0xFFFF;
|
||||
@ -726,12 +736,12 @@ static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
|
||||
(adapter,
|
||||
(addr | RSI_SD_REQUEST_MASTER),
|
||||
(u8 *)data_aligned, size);
|
||||
if (status < 0) {
|
||||
if (status < 0)
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"%s: Unable to do AHB reg write\n", __func__);
|
||||
return status;
|
||||
}
|
||||
return 0;
|
||||
|
||||
kfree(data_aligned);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,6 +46,8 @@ enum sdio_interrupt_type {
|
||||
#define PKT_BUFF_AVAILABLE 1
|
||||
#define FW_ASSERT_IND 2
|
||||
|
||||
#define RSI_MASTER_REG_BUF_SIZE 12
|
||||
|
||||
#define RSI_DEVICE_BUFFER_STATUS_REGISTER 0xf3
|
||||
#define RSI_FN1_INT_REGISTER 0xf9
|
||||
#define RSI_SD_REQUEST_MASTER 0x10000
|
||||
|
Loading…
x
Reference in New Issue
Block a user