Skip to content

Commit

Permalink
mwifiex: device dump support via devcoredump framework
Browse files Browse the repository at this point in the history
Currently device dump generated in the driver is retrieved
using ethtool set/get dump commands. We will get rid of
ethtool approach and use devcoredump framework.

Device dump can be trigger by
cat /debugfs/mwifiex/mlanX/device_dump
and when the dump operation is completed, data can be read by
cat /sys/class/devcoredump/devcdX/data

We have prepared following script to split device dump data
into multiple files.

 [root]# cat mwifiex_split_dump_data.sh
 #!/bin/bash
 # usage: ./mwifiex_split_dump_data.sh dump_data

 fw_dump_data=$1

 mem_type="driverinfo ITCM DTCM SQRAM APU CIU ICU MAC"

 for name in ${mem_type[@]}
 do
     sed -n "/Start dump $name/,/End dump/p" $fw_dump_data  > tmp.$name.log
     if [ ! -s tmp.$name.log ]
     then
         rm -rf tmp.$name.log
     else
         #Remove the describle info "Start dump" and "End dump"
         sed '1d' tmp.$name.log | sed '$d' > /data/$name.log
         if [ -s /data/$name.log ]
         then
             echo "generate /data/$name.log"
         else
             sed '1d' tmp.$name.log | sed '$d' > /var/$name.log
             echo "generate /var/$name.log"
         fi
         rm -rf tmp.$name.log
     fi
 done

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  • Loading branch information
Amitkumar Karwar authored and Kalle Valo committed Jun 2, 2015
1 parent fc69715 commit 57670ee
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 117 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/mwifiex/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ config MWIFIEX_SDIO
tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897"
depends on MWIFIEX && MMC
select FW_LOADER
select WANT_DEV_COREDUMP
---help---
This adds support for wireless adapters based on Marvell
8786/8787/8797/8887/8897 chipsets with SDIO interface.
Expand All @@ -23,6 +24,7 @@ config MWIFIEX_PCIE
tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897"
depends on MWIFIEX && PCI
select FW_LOADER
select WANT_DEV_COREDUMP
---help---
This adds support for wireless adapters based on Marvell
8766/8897 chipsets with PCIe interface.
Expand Down
99 changes: 0 additions & 99 deletions drivers/net/wireless/mwifiex/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,106 +64,7 @@ static int mwifiex_ethtool_set_wol(struct net_device *dev,
return 0;
}

static int
mwifiex_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_adapter *adapter = priv->adapter;
struct memory_type_mapping *entry;

if (!adapter->if_ops.device_dump)
return -ENOTSUPP;

dump->flag = adapter->curr_mem_idx;
dump->version = 1;
if (adapter->curr_mem_idx == MWIFIEX_DRV_INFO_IDX) {
dump->len = adapter->drv_info_size;
} else if (adapter->curr_mem_idx != MWIFIEX_FW_DUMP_IDX) {
entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
dump->len = entry->mem_size;
} else {
dump->len = 0;
}

return 0;
}

static int
mwifiex_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
void *buffer)
{
u8 *p = buffer;
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_adapter *adapter = priv->adapter;
struct memory_type_mapping *entry;

if (!adapter->if_ops.device_dump)
return -ENOTSUPP;

if (adapter->curr_mem_idx == MWIFIEX_DRV_INFO_IDX) {
if (!adapter->drv_info_dump)
return -EFAULT;
memcpy(p, adapter->drv_info_dump, adapter->drv_info_size);
return 0;
}

if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
mwifiex_dbg(adapter, ERROR,
"device dump in progress!!\n");
return -EBUSY;
}

entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];

if (!entry->mem_ptr)
return -EFAULT;

memcpy(p, entry->mem_ptr, entry->mem_size);

entry->mem_size = 0;
vfree(entry->mem_ptr);
entry->mem_ptr = NULL;

return 0;
}

static int mwifiex_set_dump(struct net_device *dev, struct ethtool_dump *val)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_adapter *adapter = priv->adapter;

if (!adapter->if_ops.device_dump)
return -ENOTSUPP;

if (val->flag == MWIFIEX_DRV_INFO_IDX) {
adapter->curr_mem_idx = MWIFIEX_DRV_INFO_IDX;
return 0;
}

if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
mwifiex_dbg(adapter, ERROR,
"device dump in progress!!\n");
return -EBUSY;
}

if (val->flag == MWIFIEX_FW_DUMP_IDX) {
adapter->curr_mem_idx = val->flag;
adapter->if_ops.device_dump(adapter);
return 0;
}

if (val->flag < 0 || val->flag >= adapter->num_mem_types)
return -EINVAL;

adapter->curr_mem_idx = val->flag;

return 0;
}

const struct ethtool_ops mwifiex_ethtool_ops = {
.get_wol = mwifiex_ethtool_get_wol,
.set_wol = mwifiex_ethtool_set_wol,
.get_dump_flag = mwifiex_get_dump_flag,
.get_dump_data = mwifiex_get_dump_data,
.set_dump = mwifiex_set_dump,
};
90 changes: 90 additions & 0 deletions drivers/net/wireless/mwifiex/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,96 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
}
EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);

void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
{
u8 idx, *dump_data, *fw_dump_ptr;
u32 dump_len;

dump_len = (strlen("========Start dump driverinfo========\n") +
adapter->drv_info_size +
strlen("\n========End dump========\n"));

for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
&adapter->mem_type_mapping_tbl[idx];

if (entry->mem_ptr) {
dump_len += (strlen("========Start dump ") +
strlen(entry->mem_name) +
strlen("========\n") +
(entry->mem_size + 1) +
strlen("\n========End dump========\n"));
}
}

dump_data = vzalloc(dump_len + 1);
if (!dump_data)
goto done;

fw_dump_ptr = dump_data;

/* 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");

strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
fw_dump_ptr += strlen("========Start dump driverinfo========\n");
memcpy(fw_dump_ptr, adapter->drv_info_dump, adapter->drv_info_size);
fw_dump_ptr += adapter->drv_info_size;
strcpy(fw_dump_ptr, "\n========End dump========\n");
fw_dump_ptr += strlen("\n========End dump========\n");

for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
&adapter->mem_type_mapping_tbl[idx];

if (entry->mem_ptr) {
strcpy(fw_dump_ptr, "========Start dump ");
fw_dump_ptr += strlen("========Start dump ");

strcpy(fw_dump_ptr, entry->mem_name);
fw_dump_ptr += strlen(entry->mem_name);

strcpy(fw_dump_ptr, "========\n");
fw_dump_ptr += strlen("========\n");

memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
fw_dump_ptr += entry->mem_size;

strcpy(fw_dump_ptr, "\n========End dump========\n");
fw_dump_ptr += strlen("\n========End dump========\n");
}
}

/* 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");

done:
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
&adapter->mem_type_mapping_tbl[idx];

if (entry->mem_ptr) {
vfree(entry->mem_ptr);
entry->mem_ptr = NULL;
}
entry->mem_size = 0;
}

if (adapter->drv_info_dump) {
vfree(adapter->drv_info_dump);
adapter->drv_info_dump = NULL;
adapter->drv_info_size = 0;
}
}
EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);

/*
* CFG802.11 network device handler for statistics retrieval.
*/
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/mwifiex/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/of.h>
#include <linux/idr.h>
#include <linux/inetdevice.h>
#include <linux/devcoredump.h>

#include "decl.h"
#include "ioctl.h"
Expand Down Expand Up @@ -950,7 +951,6 @@ struct mwifiex_adapter {
u8 key_api_major_ver, key_api_minor_ver;
struct memory_type_mapping *mem_type_mapping_tbl;
u8 num_mem_types;
u8 curr_mem_idx;
void *drv_info_dump;
u32 drv_info_size;
bool scan_chan_gap_enabled;
Expand Down Expand Up @@ -1485,6 +1485,7 @@ u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
u8 rx_rate, u8 ht_info);

void mwifiex_drv_info_dump(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);

Expand Down
21 changes: 8 additions & 13 deletions drivers/net/wireless/mwifiex/pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -2314,7 +2314,6 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
enum rdwr_status stat;
u32 memory_size;
int ret;
static char *env[] = { "DRIVER=mwifiex_pcie", "EVENT=fw_dump", NULL };

if (!card->pcie.can_dump_fw)
return;
Expand All @@ -2334,7 +2333,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
/* Read the number of the memories which will dump */
stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
if (stat == RDWR_STATUS_FAILURE)
goto done;
return;

reg = creg->fw_dump_start;
mwifiex_read_reg_byte(adapter, reg, &dump_num);
Expand All @@ -2345,7 +2344,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)

stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
if (stat == RDWR_STATUS_FAILURE)
goto done;
return;

memory_size = 0;
reg = creg->fw_dump_start;
Expand All @@ -2361,7 +2360,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
FW_DUMP_READ_DONE);
if (ret) {
mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
goto done;
return;
}
break;
}
Expand All @@ -2373,7 +2372,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
if (!entry->mem_ptr) {
mwifiex_dbg(adapter, ERROR,
"Vmalloc %s failed\n", entry->mem_name);
goto done;
return;
}
dbg_ptr = entry->mem_ptr;
end_ptr = dbg_ptr + memory_size;
Expand All @@ -2385,7 +2384,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
do {
stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
if (RDWR_STATUS_FAILURE == stat)
goto done;
return;

reg_start = creg->fw_dump_start;
reg_end = creg->fw_dump_end;
Expand All @@ -2396,7 +2395,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
} else {
mwifiex_dbg(adapter, ERROR,
"Allocated buf not enough\n");
goto done;
return;
}
}

Expand All @@ -2409,18 +2408,14 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
break;
} while (true);
}
mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");

kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);

done:
adapter->curr_mem_idx = 0;
mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
}

static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
{
mwifiex_drv_info_dump(adapter);
mwifiex_pcie_fw_dump(adapter);
mwifiex_upload_device_dump(adapter);
}

static unsigned long iface_work_flags;
Expand Down
5 changes: 1 addition & 4 deletions drivers/net/wireless/mwifiex/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2185,7 +2185,6 @@ static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
enum rdwr_status stat;
u32 memory_size;
static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL };

if (!card->can_dump_fw)
return;
Expand Down Expand Up @@ -2297,17 +2296,15 @@ static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
}
mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");

kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);

done:
sdio_release_host(card->func);
adapter->curr_mem_idx = 0;
}

static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
{
mwifiex_drv_info_dump(adapter);
mwifiex_sdio_fw_dump(adapter);
mwifiex_upload_device_dump(adapter);
}

static void mwifiex_sdio_work(struct work_struct *work)
Expand Down

0 comments on commit 57670ee

Please sign in to comment.