2017-11-27 07:09:37

by Xinming Hu

[permalink] [raw]
Subject: [PATCH v2 1/3] mwifiex: refactor device dump code to make it generic for usb interface

This patch refactor current device dump code to make it generic
for subsequent implementation on usb interface.

Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Ganapathi Bhat <[email protected]>
---
v2: Addressed below review comments from Brian Norris
a) use new API timer_setup/from_timer.
b) reset devdump_len during initization
---
drivers/net/wireless/marvell/mwifiex/init.c | 1 +
drivers/net/wireless/marvell/mwifiex/main.c | 87 +++++++++++++++--------------
drivers/net/wireless/marvell/mwifiex/main.h | 11 +++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 13 +++--
drivers/net/wireless/marvell/mwifiex/sdio.c | 14 +++--
5 files changed, 72 insertions(+), 54 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index e1aa860..b0d3d68 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -314,6 +314,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
adapter->active_scan_triggered = false;
timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
+ adapter->devdump_len = 0;
}

/*
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index a96bd7e..f7d0299 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1051,9 +1051,23 @@ void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter)
}
EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);

-int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
+void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
{
- void *p;
+ /* Dump all the memory data into single file, a userspace script will
+ * be used to split all the memory data to multiple files
+ */
+ mwifiex_dbg(adapter, MSG,
+ "== mwifiex dump information to /sys/class/devcoredump start");
+ dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len,
+ GFP_KERNEL);
+ mwifiex_dbg(adapter, MSG,
+ "== mwifiex dump information to /sys/class/devcoredump end");
+}
+EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
+
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
+{
+ char *p;
char drv_version[64];
struct usb_card_rec *cardp;
struct sdio_mmc_card *sdio_card;
@@ -1061,17 +1075,12 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
int i, idx;
struct netdev_queue *txq;
struct mwifiex_debug_info *debug_info;
- void *drv_info_dump;

mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");

- /* memory allocate here should be free in mwifiex_upload_device_dump*/
- drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
-
- if (!drv_info_dump)
- return 0;
-
- p = (char *)(drv_info_dump);
+ p = adapter->devdump_data;
+ strcpy(p, "========Start dump driverinfo========\n");
+ p += strlen("========Start dump driverinfo========\n");
p += sprintf(p, "driver_name = " "\"mwifiex\"\n");

mwifiex_drv_get_driver_version(adapter, drv_version,
@@ -1155,21 +1164,18 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
kfree(debug_info);
}

+ strcpy(p, "\n========End dump========\n");
+ p += strlen("\n========End dump========\n");
mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
- *drv_info = drv_info_dump;
- return p - drv_info_dump;
+ adapter->devdump_len = p - (char *)adapter->devdump_data;
}
EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);

-void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
- int drv_info_size)
+void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter)
{
- u8 idx, *dump_data, *fw_dump_ptr;
- u32 dump_len;
-
- dump_len = (strlen("========Start dump driverinfo========\n") +
- drv_info_size +
- strlen("\n========End dump========\n"));
+ u8 idx;
+ char *fw_dump_ptr;
+ u32 dump_len = 0;

for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
@@ -1184,24 +1190,24 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
}
}

- dump_data = vzalloc(dump_len + 1);
- if (!dump_data)
- goto done;
-
- fw_dump_ptr = dump_data;
+ if (dump_len + 1 + adapter->devdump_len > MWIFIEX_FW_DUMP_SIZE) {
+ /* Realloc in case buffer overflow */
+ fw_dump_ptr = vzalloc(dump_len + 1 + adapter->devdump_len);
+ mwifiex_dbg(adapter, MSG, "Realloc device dump data.");
+ if (!fw_dump_ptr) {
+ vfree(adapter->devdump_data);
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }

- /* Dump all the memory data into single file, a userspace script will
- * be used to split all the memory data to multiple files
- */
- mwifiex_dbg(adapter, MSG,
- "== mwifiex dump information to /sys/class/devcoredump start");
+ memmove(fw_dump_ptr, adapter->devdump_data,
+ adapter->devdump_len);
+ vfree(adapter->devdump_data);
+ adapter->devdump_data = fw_dump_ptr;
+ }

- strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
- fw_dump_ptr += strlen("========Start dump driverinfo========\n");
- memcpy(fw_dump_ptr, drv_info, drv_info_size);
- fw_dump_ptr += drv_info_size;
- strcpy(fw_dump_ptr, "\n========End dump========\n");
- fw_dump_ptr += strlen("\n========End dump========\n");
+ fw_dump_ptr = (char *)adapter->devdump_data + adapter->devdump_len;

for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
@@ -1228,11 +1234,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
/* device dump data will be free in device coredump release function
* after 5 min
*/
- dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
- mwifiex_dbg(adapter, MSG,
- "== mwifiex dump information to /sys/class/devcoredump end");
+ adapter->devdump_len = fw_dump_ptr - (char *)adapter->devdump_data;

-done:
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
&adapter->mem_type_mapping_tbl[idx];
@@ -1241,10 +1244,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
entry->mem_ptr = NULL;
entry->mem_size = 0;
}
-
- vfree(drv_info);
}
-EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
+EXPORT_SYMBOL_GPL(mwifiex_prepare_fw_dump_info);

/*
* CFG802.11 network device handler for statistics retrieval.
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 154c079..8b6241a 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -94,6 +94,8 @@ enum {

#define MAX_EVENT_SIZE 2048

+#define MWIFIEX_FW_DUMP_SIZE (2 * 1024 * 1024)
+
#define ARP_FILTER_MAX_BUF_SIZE 68

#define MWIFIEX_KEY_BUFFER_SIZE 16
@@ -1032,6 +1034,9 @@ struct mwifiex_adapter {
bool wake_by_wifi;
/* Aggregation parameters*/
struct bus_aggr_params bus_aggr;
+ /* Device dump data/length */
+ void *devdump_data;
+ int devdump_len;
};

void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1656,9 +1661,9 @@ void mwifiex_hist_data_add(struct mwifiex_private *priv,
u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
u8 rx_rate, u8 ht_info);

-int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info);
-void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
- int drv_info_size);
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
+void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter);
+void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index cd31494..f666cb2 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2769,12 +2769,17 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)

static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
{
- int drv_info_size;
- void *drv_info;
+ adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
+ if (!adapter->devdump_data) {
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }

- drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
+ mwifiex_drv_info_dump(adapter);
mwifiex_pcie_fw_dump(adapter);
- mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
+ mwifiex_prepare_fw_dump_info(adapter);
+ mwifiex_upload_device_dump(adapter);
}

static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index fd5183c..a828801 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -2505,15 +2505,21 @@ static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
- int drv_info_size;
- void *drv_info;

- drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
+ adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
+ if (!adapter->devdump_data) {
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }
+
+ mwifiex_drv_info_dump(adapter);
if (card->fw_dump_enh)
mwifiex_sdio_generic_fw_dump(adapter);
else
mwifiex_sdio_fw_dump(adapter);
- mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
+ mwifiex_prepare_fw_dump_info(adapter);
+ mwifiex_upload_device_dump(adapter);
}

static void mwifiex_sdio_work(struct work_struct *work)
--
1.9.1


2017-11-30 16:33:30

by Brian Norris

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] mwifiex: debugfs: trigger device dump for usb interface

On Mon, Nov 27, 2017 at 03:09:15PM +0800, Xinming Hu wrote:
> This patch extend device_dump debugfs function to make it
> works for usb interface.
>
> Signed-off-by: Xinming Hu <[email protected]>
> Signed-off-by: Cathy Luo <[email protected]>
> ---
> v2: Same as v1

With the same problems as v1 :)

2017-11-27 07:09:42

by Xinming Hu

[permalink] [raw]
Subject: [PATCH v2 3/3] mwifiex: debugfs: trigger device dump for usb interface

This patch extend device_dump debugfs function to make it
works for usb interface.

Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
v2: Same as v1
---
drivers/net/wireless/marvell/mwifiex/cmdevt.c | 11 +++++++----
drivers/net/wireless/marvell/mwifiex/debugfs.c | 9 +++++----
drivers/net/wireless/marvell/mwifiex/fw.h | 1 +
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 ++++
4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index dcc529e..8746600 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -290,13 +290,16 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
get_unaligned_le16((u8 *)host_cmd + S_DS_GEN);

+ /* Setup the timer after transmit command, except that specific
+ * command might not have command response.
+ */
+ if (cmd_code != HostCmd_CMD_FW_DUMP_EVENT)
+ mod_timer(&adapter->cmd_timer,
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+
/* Clear BSS_NO_BITS from HostCmd */
cmd_code &= HostCmd_CMD_ID_MASK;

- /* Setup the timer after transmit command */
- mod_timer(&adapter->cmd_timer,
- jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-
return 0;
}

diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index 6f4239b..5d476de 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -168,10 +168,11 @@
{
struct mwifiex_private *priv = file->private_data;

- if (!priv->adapter->if_ops.device_dump)
- return -EIO;
-
- priv->adapter->if_ops.device_dump(priv->adapter);
+ if (priv->adapter->iface_type == MWIFIEX_USB)
+ mwifiex_send_cmd(priv, HostCmd_CMD_FW_DUMP_EVENT,
+ HostCmd_ACT_GEN_SET, 0, NULL, true);
+ else
+ priv->adapter->if_ops.device_dump(priv->adapter);

return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 4d5e686..9c2cdef 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -409,6 +409,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_TDLS_CONFIG 0x0100
#define HostCmd_CMD_MC_POLICY 0x0121
#define HostCmd_CMD_TDLS_OPER 0x0122
+#define HostCmd_CMD_FW_DUMP_EVENT 0x0125
#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
#define HostCmd_CMD_CHAN_REGION_CFG 0x0242
#define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index fb09014..211e47d 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2206,6 +2206,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
case HostCmd_CMD_CHAN_REGION_CFG:
ret = mwifiex_cmd_chan_region_cfg(priv, cmd_ptr, cmd_action);
break;
+ case HostCmd_CMD_FW_DUMP_EVENT:
+ cmd_ptr->command = cpu_to_le16(cmd_no);
+ cmd_ptr->size = cpu_to_le16(S_DS_GEN);
+ break;
default:
mwifiex_dbg(priv->adapter, ERROR,
"PREP_CMD: unknown cmd- %#x\n", cmd_no);
--
1.9.1

2017-11-27 07:09:38

by Xinming Hu

[permalink] [raw]
Subject: [PATCH v2 2/3] mwifiex: device dump support for usb interface

Firmware dump on usb interface is different with current
sdio/pcie chipset, which is based on register operation.

When firmware hang on usb interface, context dump will be
upload to host using 0x73 firmware debug event.

This patch store dump data from debug event and send to
userspace using device coredump API.

Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
v2: Addressed below review comments from Brian Norris
a) Check for overflow introduced by invalid event.
b) Use end of transmission signal to recognize last event.
---
drivers/net/wireless/marvell/mwifiex/fw.h | 10 ++++
drivers/net/wireless/marvell/mwifiex/init.c | 9 ++++
drivers/net/wireless/marvell/mwifiex/main.h | 2 +
drivers/net/wireless/marvell/mwifiex/sta_event.c | 61 ++++++++++++++++++++++++
4 files changed, 82 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 13cd58e9..4d5e686 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -56,6 +56,15 @@ struct mwifiex_fw_data {
u8 data[1];
} __packed;

+struct mwifiex_fw_dump_header {
+ __le16 seq_num;
+ __le16 reserved;
+ __le16 type;
+ __le16 len;
+} __packed;
+
+#define FW_DUMP_INFO_ENDED 0x0002
+
#define MWIFIEX_FW_DNLD_CMD_1 0x1
#define MWIFIEX_FW_DNLD_CMD_5 0x5
#define MWIFIEX_FW_DNLD_CMD_6 0x6
@@ -570,6 +579,7 @@ enum mwifiex_channel_flags {
#define EVENT_BG_SCAN_STOPPED 0x00000065
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
#define EVENT_MULTI_CHAN_INFO 0x0000006a
+#define EVENT_FW_DUMP_INFO 0x00000073
#define EVENT_TX_STATUS_REPORT 0x00000074
#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076

diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index b0d3d68..d239e92 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -64,6 +64,13 @@ static void wakeup_timer_fn(struct timer_list *t)
adapter->if_ops.card_reset(adapter);
}

+static void fw_dump_timer_fn(struct timer_list *t)
+{
+ struct mwifiex_adapter *adapter = from_timer(adapter, t, devdump_timer);
+
+ mwifiex_upload_device_dump(adapter);
+}
+
/*
* This function initializes the private structure and sets default
* values to the members.
@@ -315,6 +322,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_triggered = false;
timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
adapter->devdump_len = 0;
+ timer_setup(&adapter->devdump_timer, fw_dump_timer_fn, 0);
}

/*
@@ -397,6 +405,7 @@ static void mwifiex_invalidate_lists(struct mwifiex_adapter *adapter)
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
del_timer(&adapter->wakeup_timer);
+ del_timer_sync(&adapter->devdump_timer);
mwifiex_cancel_all_pending_cmd(adapter);
wake_up_interruptible(&adapter->cmd_wait_q.wait);
wake_up_interruptible(&adapter->hs_activate_wait_q);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 8b6241a..6b5539b 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1037,6 +1037,7 @@ struct mwifiex_adapter {
/* Device dump data/length */
void *devdump_data;
int devdump_len;
+ struct timer_list devdump_timer;
};

void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1682,6 +1683,7 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter);
int mwifiex_set_mac_address(struct mwifiex_private *priv,
struct net_device *dev);
+void mwifiex_devdump_tmo_func(unsigned long function_context);

#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index d8db412..93dfb76 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -584,6 +584,62 @@ void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
adapter->coex_rx_win_size);
}

+static void
+mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
+ struct sk_buff *event_skb)
+{
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct mwifiex_fw_dump_header *fw_dump_hdr =
+ (void *)adapter->event_body;
+
+ if (adapter->iface_type != MWIFIEX_USB) {
+ mwifiex_dbg(adapter, MSG,
+ "event is not on usb interface, ignore it\n");
+ return;
+ }
+
+ if (!adapter->devdump_data) {
+ /* When receive the first event, allocate device dump
+ * buffer, dump driver info.
+ */
+ adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
+ if (!adapter->devdump_data) {
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }
+
+ mwifiex_drv_info_dump(adapter);
+
+ /* If no proceeded event arrive in 10s, upload device
+ * dump data, this will be useful if the end of
+ * transmission event get lost, in this cornel case,
+ * user would still get partial of the dump.
+ */
+ mod_timer(&adapter->devdump_timer,
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+ }
+
+ /* Overflow check */
+ if (adapter->devdump_len + event_skb->len >= MWIFIEX_FW_DUMP_SIZE)
+ goto upload_dump;
+
+ memmove(adapter->devdump_data + adapter->devdump_len,
+ adapter->event_skb->data, event_skb->len);
+ adapter->devdump_len += event_skb->len;
+
+ if (le16_to_cpu(fw_dump_hdr->type == FW_DUMP_INFO_ENDED)) {
+ mwifiex_dbg(adapter, MSG,
+ "receive end of transmission flag event!\n");
+ goto upload_dump;
+ }
+ return;
+
+upload_dump:
+ del_timer_sync(&adapter->devdump_timer);
+ mwifiex_upload_device_dump(adapter);
+}
+
/*
* This function handles events generated by firmware.
*
@@ -636,6 +692,7 @@ void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
* - EVENT_DELBA
* - EVENT_BA_STREAM_TIEMOUT
* - EVENT_AMSDU_AGGR_CTRL
+ * - EVENT_FW_DUMP_INFO
*/
int mwifiex_process_sta_event(struct mwifiex_private *priv)
{
@@ -1007,6 +1064,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
adapter->event_skb->len -
sizeof(eventcause));
break;
+ case EVENT_FW_DUMP_INFO:
+ mwifiex_dbg(adapter, EVENT, "event: firmware debug info\n");
+ mwifiex_fw_dump_info_event(priv, adapter->event_skb);
+ break;
/* Debugging event; not used, but let's not print an ERROR for it. */
case EVENT_UNKNOWN_DEBUG:
mwifiex_dbg(adapter, EVENT, "event: debug\n");
--
1.9.1