Files
linux/drivers/net/wireless/rsi/rsi_sdio.h
Amitkumar Karwar b652092f8e rsi: fix kernel panic observed on 64bit machine
[ Upstream commit 864db4d508 ]

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>
2018-05-30 07:52:28 +02:00

135 lines
4.6 KiB
C

/**
* @section LICENSE
* Copyright (c) 2014 Redpine Signals Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef __RSI_SDIO_INTF__
#define __RSI_SDIO_INTF__
#include <linux/mmc/card.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sd.h>
#include <linux/mmc/sdio_ids.h>
#include "rsi_main.h"
enum sdio_interrupt_type {
BUFFER_FULL = 0x0,
BUFFER_AVAILABLE = 0x2,
FIRMWARE_ASSERT_IND = 0x3,
MSDU_PACKET_PENDING = 0x4,
UNKNOWN_INT = 0XE
};
/* Buffer status register related info */
#define PKT_BUFF_SEMI_FULL 0
#define PKT_BUFF_FULL 1
#define PKT_MGMT_BUFF_FULL 2
#define MSDU_PKT_PENDING 3
#define RECV_NUM_BLOCKS 4
/* Interrupt Bit Related Macros */
#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
/* FOR SD CARD ONLY */
#define SDIO_RX_NUM_BLOCKS_REG 0x000F1
#define SDIO_FW_STATUS_REG 0x000F2
#define SDIO_NXT_RD_DELAY2 0x000F5
#define SDIO_MASTER_ACCESS_MSBYTE 0x000FA
#define SDIO_MASTER_ACCESS_LSBYTE 0x000FB
#define SDIO_READ_START_LVL 0x000FC
#define SDIO_READ_FIFO_CTL 0x000FD
#define SDIO_WRITE_FIFO_CTL 0x000FE
#define SDIO_WAKEUP_REG 0x000FF
#define SDIO_FUN1_INTR_CLR_REG 0x0008
#define SDIO_REG_HIGH_SPEED 0x0013
#define RSI_GET_SDIO_INTERRUPT_TYPE(_I, TYPE) \
{ \
TYPE = \
(_I & (1 << PKT_BUFF_AVAILABLE)) ? \
BUFFER_AVAILABLE : \
(_I & (1 << MSDU_PKT_PENDING)) ? \
MSDU_PACKET_PENDING : \
(_I & (1 << FW_ASSERT_IND)) ? \
FIRMWARE_ASSERT_IND : UNKNOWN_INT; \
}
/* common registers in SDIO function1 */
#define TA_SOFT_RESET_REG 0x0004
#define TA_TH0_PC_REG 0x0400
#define TA_HOLD_THREAD_REG 0x0844
#define TA_RELEASE_THREAD_REG 0x0848
#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_RELEASE_THREAD_VALUE cpu_to_le32(0xF)
#define TA_BASE_ADDR 0x2200
#define MISC_CFG_BASE_ADDR 0x4105
struct receive_info {
bool buffer_full;
bool semi_buffer_full;
bool mgmt_buffer_full;
u32 mgmt_buf_full_counter;
u32 buf_semi_full_counter;
u8 watch_bufferfull_count;
u32 sdio_intr_status_zero;
u32 sdio_int_counter;
u32 total_sdio_msdu_pending_intr;
u32 total_sdio_unknown_intr;
u32 buf_full_counter;
u32 buf_available_counter;
};
struct rsi_91x_sdiodev {
struct sdio_func *pfunction;
struct task_struct *sdio_irq_task;
struct receive_info rx_info;
u32 next_read_delay;
u32 sdio_high_speed_enable;
u8 sdio_clock_speed;
u32 cardcapability;
u8 prev_desc[16];
u16 tx_blk_size;
u8 write_fail;
bool buff_status_updated;
};
void rsi_interrupt_handler(struct rsi_hw *adapter);
int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
u32 addr, u8 *data);
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num);
#endif