Skip to content

Commit

Permalink
rsi: fix kernel panic observed on 64bit machine
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Amitkumar Karwar authored and Kalle Valo committed Mar 27, 2018
1 parent 90b12ae commit 864db4d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
32 changes: 21 additions & 11 deletions drivers/net/wireless/rsi/rsi_91x_sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,19 +653,22 @@ 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);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"%s: Unable to set ms word to common reg\n",
__func__);
return status;
goto err;
}
addr &= 0xFFFF;

Expand All @@ -683,7 +686,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)
Expand All @@ -705,17 +708,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));
Expand All @@ -734,6 +743,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;
Expand All @@ -743,12 +753,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;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/rsi/rsi_sdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_INT_ENABLE_REGISTER 0x04
Expand Down

0 comments on commit 864db4d

Please sign in to comment.