Commit dc759613 authored by Xinming Hu's avatar Xinming Hu Committed by Marcel Holtmann

Bluetooth: btmrvl add firmware dump support

This patch adds firmware dump support for marvell
bluetooth chipset. Currently only SD8897 is supported.
This is implemented based on dev_coredump, a new mechnism
introduced in kernel 3.18rc3

Firmware dump can be trigger by
echo 1 > /sys/kernel/debug/bluetooth/hci*/config/fw_dump
and when the dump operation is completed, data can be read by
cat /sys/class/devcoredump/devcd*/data

We have prepared following script to divide fw memory
dump data into multiple files based on memory type.

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

 fw_dump_data=$1

 mem_type="ITCM DTCM SQRAM APU CIU ICU MAC EXT7 EXT8 EXT9 EXT10 EXT11 EXT12 EXT13 EXTLAST"

 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: default avatarXinming Hu <huxm@marvell.com>
Signed-off-by: default avatarCathy Luo <cluo@marvell.com>
Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Reviewed-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Reviewed-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 7365d475
...@@ -210,6 +210,7 @@ config BT_MRVL_SDIO ...@@ -210,6 +210,7 @@ config BT_MRVL_SDIO
tristate "Marvell BT-over-SDIO driver" tristate "Marvell BT-over-SDIO driver"
depends on BT_MRVL && MMC depends on BT_MRVL && MMC
select FW_LOADER select FW_LOADER
select WANT_DEV_COREDUMP
help help
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
......
...@@ -167,6 +167,35 @@ static const struct file_operations btmrvl_hscmd_fops = { ...@@ -167,6 +167,35 @@ static const struct file_operations btmrvl_hscmd_fops = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
static ssize_t btmrvl_fwdump_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct btmrvl_private *priv = file->private_data;
char buf[16];
bool result;
memset(buf, 0, sizeof(buf));
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (strtobool(buf, &result))
return -EINVAL;
if (!result)
return -EINVAL;
btmrvl_firmware_dump(priv);
return count;
}
static const struct file_operations btmrvl_fwdump_fops = {
.write = btmrvl_fwdump_write,
.open = simple_open,
.llseek = default_llseek,
};
void btmrvl_debugfs_init(struct hci_dev *hdev) void btmrvl_debugfs_init(struct hci_dev *hdev)
{ {
struct btmrvl_private *priv = hci_get_drvdata(hdev); struct btmrvl_private *priv = hci_get_drvdata(hdev);
...@@ -197,6 +226,8 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) ...@@ -197,6 +226,8 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
priv, &btmrvl_hscmd_fops); priv, &btmrvl_hscmd_fops);
debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
priv, &btmrvl_hscfgcmd_fops); priv, &btmrvl_hscfgcmd_fops);
debugfs_create_file("fw_dump", 0200, dbg->config_dir,
priv, &btmrvl_fwdump_fops);
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs); dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
debugfs_create_u8("curpsmode", 0444, dbg->status_dir, debugfs_create_u8("curpsmode", 0444, dbg->status_dir,
......
...@@ -32,6 +32,24 @@ ...@@ -32,6 +32,24 @@
/* Time to wait for command response in millisecond */ /* Time to wait for command response in millisecond */
#define WAIT_UNTIL_CMD_RESP 5000 #define WAIT_UNTIL_CMD_RESP 5000
enum rdwr_status {
RDWR_STATUS_SUCCESS = 0,
RDWR_STATUS_FAILURE = 1,
RDWR_STATUS_DONE = 2
};
#define FW_DUMP_MAX_NAME_LEN 8
#define FW_DUMP_HOST_READY 0xEE
#define FW_DUMP_DONE 0xFF
#define FW_DUMP_READ_DONE 0xFE
struct memory_type_mapping {
u8 mem_name[FW_DUMP_MAX_NAME_LEN];
u8 *mem_ptr;
u32 mem_size;
u8 done_flag;
};
struct btmrvl_thread { struct btmrvl_thread {
struct task_struct *task; struct task_struct *task;
wait_queue_head_t wait_q; wait_queue_head_t wait_q;
...@@ -81,6 +99,7 @@ struct btmrvl_private { ...@@ -81,6 +99,7 @@ struct btmrvl_private {
u8 *payload, u16 nb); u8 *payload, u16 nb);
int (*hw_wakeup_firmware) (struct btmrvl_private *priv); int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
int (*hw_process_int_status) (struct btmrvl_private *priv); int (*hw_process_int_status) (struct btmrvl_private *priv);
void (*firmware_dump)(struct btmrvl_private *priv);
spinlock_t driver_lock; /* spinlock used by driver */ spinlock_t driver_lock; /* spinlock used by driver */
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void *debugfs_data; void *debugfs_data;
...@@ -151,6 +170,7 @@ int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); ...@@ -151,6 +170,7 @@ int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv);
int btmrvl_enable_hs(struct btmrvl_private *priv); int btmrvl_enable_hs(struct btmrvl_private *priv);
void btmrvl_firmware_dump(struct btmrvl_private *priv);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void btmrvl_debugfs_init(struct hci_dev *hdev); void btmrvl_debugfs_init(struct hci_dev *hdev);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#include <linux/mmc/sdio_func.h>
#include "btmrvl_drv.h" #include "btmrvl_drv.h"
#include "btmrvl_sdio.h" #include "btmrvl_sdio.h"
...@@ -335,6 +336,12 @@ int btmrvl_prepare_command(struct btmrvl_private *priv) ...@@ -335,6 +336,12 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
return ret; return ret;
} }
void btmrvl_firmware_dump(struct btmrvl_private *priv)
{
if (priv->firmware_dump)
priv->firmware_dump(priv);
}
static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb) static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
{ {
int ret = 0; int ret = 0;
......
This diff is collapsed.
...@@ -81,6 +81,9 @@ struct btmrvl_sdio_card_reg { ...@@ -81,6 +81,9 @@ struct btmrvl_sdio_card_reg {
bool int_read_to_clear; bool int_read_to_clear;
u8 host_int_rsr; u8 host_int_rsr;
u8 card_misc_cfg; u8 card_misc_cfg;
u8 fw_dump_ctrl;
u8 fw_dump_start;
u8 fw_dump_end;
}; };
struct btmrvl_sdio_card { struct btmrvl_sdio_card {
...@@ -90,6 +93,7 @@ struct btmrvl_sdio_card { ...@@ -90,6 +93,7 @@ struct btmrvl_sdio_card {
const char *firmware; const char *firmware;
const struct btmrvl_sdio_card_reg *reg; const struct btmrvl_sdio_card_reg *reg;
bool support_pscan_win_report; bool support_pscan_win_report;
bool supports_fw_dump;
u16 sd_blksz_fw_dl; u16 sd_blksz_fw_dl;
u8 rx_unit; u8 rx_unit;
struct btmrvl_private *priv; struct btmrvl_private *priv;
...@@ -101,6 +105,7 @@ struct btmrvl_sdio_device { ...@@ -101,6 +105,7 @@ struct btmrvl_sdio_device {
const struct btmrvl_sdio_card_reg *reg; const struct btmrvl_sdio_card_reg *reg;
const bool support_pscan_win_report; const bool support_pscan_win_report;
u16 sd_blksz_fw_dl; u16 sd_blksz_fw_dl;
bool supports_fw_dump;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment