Skip to content

Commit

Permalink
wlcore/wl18xx: fw logger over sdio
Browse files Browse the repository at this point in the history
Enable the FW Logger to work over the SDIO interface in addition to over UART
interface. In the new design we use fw internal memory instead of packet ram
that was used in older (wl12xx) design. This change reduces the impact on TP
and stability.

A new event was added to notify fw logger is ready for reading. Dynamic
configuration to debugfs was added as well.

Signed-off-by: Shahar Patury <shaharp@ti.com>
Signed-off-by: Guy Mishol <guym@ti.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  • Loading branch information
shaharp authored and Kalle Valo committed Dec 31, 2015
1 parent 0510931 commit 3719c17
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 128 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/ti/wl18xx/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
mbox->sc_ssid,
mbox->sc_pwd_len,
mbox->sc_pwd);
if (vector & FW_LOGGER_INDICATION)
wlcore_event_fw_logger(wl);

return 0;
}
1 change: 1 addition & 0 deletions drivers/net/wireless/ti/wl18xx/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum {
SMART_CONFIG_SYNC_EVENT_ID = BIT(22),
SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
TIME_SYNC_EVENT_ID = BIT(24),
FW_LOGGER_INDICATION = BIT(25),
};

enum wl18xx_radar_types {
Expand Down
9 changes: 5 additions & 4 deletions drivers/net/wireless/ti/wl18xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ static struct wlcore_conf wl18xx_conf = {
},
.fwlog = {
.mode = WL12XX_FWLOG_CONTINUOUS,
.mem_blocks = 2,
.mem_blocks = 0,
.severity = 0,
.timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
.output = WL12XX_FWLOG_OUTPUT_DBG_PINS,
Expand Down Expand Up @@ -595,7 +595,7 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
.mem = { .start = 0x00A00000, .size = 0x00012000 },
.reg = { .start = 0x00807000, .size = 0x00005000 },
.mem2 = { .start = 0x00800000, .size = 0x0000B000 },
.mem3 = { .start = 0x00000000, .size = 0x00000000 },
.mem3 = { .start = 0x00401594, .size = 0x00001020 },
},
[PART_DOWN] = {
.mem = { .start = 0x00000000, .size = 0x00014000 },
Expand All @@ -613,7 +613,7 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
.mem = { .start = 0x00800000, .size = 0x000050FC },
.reg = { .start = 0x00B00404, .size = 0x00001000 },
.mem2 = { .start = 0x00C00000, .size = 0x00000400 },
.mem3 = { .start = 0x00000000, .size = 0x00000000 },
.mem3 = { .start = 0x00401594, .size = 0x00001020 },
},
[PART_PHY_INIT] = {
.mem = { .start = WL18XX_PHY_INIT_MEM_ADDR,
Expand Down Expand Up @@ -1040,7 +1040,8 @@ static int wl18xx_boot(struct wl1271 *wl)
DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
SMART_CONFIG_SYNC_EVENT_ID |
SMART_CONFIG_DECODE_EVENT_ID |
TIME_SYNC_EVENT_ID;
TIME_SYNC_EVENT_ID |
FW_LOGGER_INDICATION;

wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;

Expand Down
1 change: 0 additions & 1 deletion drivers/net/wireless/ti/wlcore/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,6 @@ struct wl12xx_cmd_remove_peer {
*/
enum wl12xx_fwlogger_log_mode {
WL12XX_FWLOG_CONTINUOUS,
WL12XX_FWLOG_ON_DEMAND
};

/* Include/exclude timestamps from the log messages */
Expand Down
60 changes: 60 additions & 0 deletions drivers/net/wireless/ti/wlcore/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,65 @@ static const struct file_operations dev_mem_ops = {
.llseek = dev_mem_seek,
};

static ssize_t fw_logger_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;

return wl1271_format_buffer(user_buf, count,
ppos, "%d\n",
wl->conf.fwlog.output);
}

static ssize_t fw_logger_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
unsigned long value;
int ret;

ret = kstrtoul_from_user(user_buf, count, 0, &value);
if (ret < 0) {
wl1271_warning("illegal value in fw_logger");
return -EINVAL;
}

if ((value > 2) || (value == 0)) {
wl1271_warning("fw_logger value must be 1-UART 2-SDIO");
return -ERANGE;
}

if (wl->conf.fwlog.output == 0) {
wl1271_warning("iligal opperation - fw logger disabled by default, please change mode via wlconf");
return -EINVAL;
}

mutex_lock(&wl->mutex);
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0) {
count = ret;
goto out;
}

wl->conf.fwlog.output = value;

ret = wl12xx_cmd_config_fwlog(wl);

wl1271_ps_elp_sleep(wl);

out:
mutex_unlock(&wl->mutex);
return count;
}

static const struct file_operations fw_logger_ops = {
.open = simple_open,
.read = fw_logger_read,
.write = fw_logger_write,
.llseek = default_llseek,
};

static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
Expand All @@ -1260,6 +1319,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(irq_timeout, rootdir);
DEBUGFS_ADD(fw_stats_raw, rootdir);
DEBUGFS_ADD(sleep_auth, rootdir);
DEBUGFS_ADD(fw_logger, rootdir);

streaming = debugfs_create_dir("rx_streaming", rootdir);
if (!streaming || IS_ERR(streaming))
Expand Down
82 changes: 82 additions & 0 deletions drivers/net/wireless/ti/wlcore/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,88 @@
#include "ps.h"
#include "scan.h"
#include "wl12xx_80211.h"
#include "hw_ops.h"

#define WL18XX_LOGGER_SDIO_BUFF_MAX (0x1020)
#define WL18XX_DATA_RAM_BASE_ADDRESS (0x20000000)
#define WL18XX_LOGGER_SDIO_BUFF_ADDR (0x40159c)
#define WL18XX_LOGGER_BUFF_OFFSET (sizeof(struct fw_logger_information))
#define WL18XX_LOGGER_READ_POINT_OFFSET (12)

int wlcore_event_fw_logger(struct wl1271 *wl)
{
u32 ret;
struct fw_logger_information fw_log;
u8 *buffer;
u32 internal_fw_addrbase = WL18XX_DATA_RAM_BASE_ADDRESS;
u32 addr = WL18XX_LOGGER_SDIO_BUFF_ADDR;
u32 end_buff_addr = WL18XX_LOGGER_SDIO_BUFF_ADDR +
WL18XX_LOGGER_BUFF_OFFSET;
u32 available_len;
u32 actual_len;
u32 clear_addr;
size_t len;
u32 start_loc;

buffer = kzalloc(WL18XX_LOGGER_SDIO_BUFF_MAX, GFP_KERNEL);
if (!buffer) {
wl1271_error("Fail to allocate fw logger memory");
fw_log.actual_buff_size = cpu_to_le32(0);
goto out;
}

ret = wlcore_read(wl, addr, buffer, WL18XX_LOGGER_SDIO_BUFF_MAX,
false);
if (ret < 0) {
wl1271_error("Fail to read logger buffer, error_id = %d",
ret);
fw_log.actual_buff_size = cpu_to_le32(0);
goto free_out;
}

memcpy(&fw_log, buffer, sizeof(fw_log));

if (le32_to_cpu(fw_log.actual_buff_size) == 0)
goto free_out;

actual_len = le32_to_cpu(fw_log.actual_buff_size);
start_loc = (le32_to_cpu(fw_log.buff_read_ptr) -
internal_fw_addrbase) - addr;
end_buff_addr += le32_to_cpu(fw_log.max_buff_size);
available_len = end_buff_addr -
(le32_to_cpu(fw_log.buff_read_ptr) -
internal_fw_addrbase);
actual_len = min(actual_len, available_len);
len = actual_len;

wl12xx_copy_fwlog(wl, &buffer[start_loc], len);
clear_addr = addr + start_loc + le32_to_cpu(fw_log.actual_buff_size) +
internal_fw_addrbase;

len = le32_to_cpu(fw_log.actual_buff_size) - len;
if (len) {
wl12xx_copy_fwlog(wl,
&buffer[WL18XX_LOGGER_BUFF_OFFSET],
len);
clear_addr = addr + WL18XX_LOGGER_BUFF_OFFSET + len +
internal_fw_addrbase;
}

/* double check that clear address and write pointer are the same */
if (clear_addr != le32_to_cpu(fw_log.buff_write_ptr)) {
wl1271_error("Calculate of clear addr Clear = %x, write = %x",
clear_addr, le32_to_cpu(fw_log.buff_write_ptr));
}

/* indicate FW about Clear buffer */
ret = wlcore_write32(wl, addr + WL18XX_LOGGER_READ_POINT_OFFSET,
fw_log.buff_write_ptr);
free_out:
kfree(buffer);
out:
return le32_to_cpu(fw_log.actual_buff_size);
}
EXPORT_SYMBOL_GPL(wlcore_event_fw_logger);

void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr)
{
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/wireless/ti/wlcore/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ enum {

#define NUM_OF_RSSI_SNR_TRIGGERS 8

struct fw_logger_information {
__le32 max_buff_size;
__le32 actual_buff_size;
__le32 num_trace_drop;
__le32 buff_read_ptr;
__le32 buff_write_ptr;
} __packed;

struct wl1271;

int wl1271_event_unmask(struct wl1271 *wl);
Expand All @@ -84,4 +92,5 @@ void wlcore_event_max_tx_failure(struct wl1271 *wl, unsigned long sta_bitmap);
void wlcore_event_inactive_sta(struct wl1271 *wl, unsigned long sta_bitmap);
void wlcore_event_roc_complete(struct wl1271 *wl);
void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr);
int wlcore_event_fw_logger(struct wl1271 *wl);
#endif
11 changes: 6 additions & 5 deletions drivers/net/wireless/ti/wlcore/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,13 @@ int wlcore_set_partition(struct wl1271 *wl,
if (ret < 0)
goto out;

/*
* We don't need the size of the last partition, as it is
* automatically calculated based on the total memory size and
* the sizes of the previous partitions.
*/
ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
if (ret < 0)
goto out;

ret = wlcore_raw_write32(wl, HW_PART3_SIZE_ADDR, p->mem3.size);
if (ret < 0)
goto out;

out:
return ret;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ti/wlcore/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
#define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12)
#define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16)
#define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20)
#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24)

#define HW_PART3_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 24)
#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 28)
#define HW_ACCESS_REGISTER_SIZE 4

#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
Expand Down
Loading

0 comments on commit 3719c17

Please sign in to comment.