[ALPS02870048] BT Driver: Enable core dump for mt7668
Test: Pass
Change-Id: I11c0b0036367d1c07aee5b10833dbdbe9db27b51
Signed-off-by: can.chen <can.chen@mediatek.com>
Feature: BT Driver(MT7668)
CR-Id: ALPS02870048
diff --git a/btmtk_drv.h b/btmtk_drv.h
index e8feb8e..f3e7f24 100644
--- a/btmtk_drv.h
+++ b/btmtk_drv.h
@@ -19,9 +19,9 @@
#include <linux/slab.h>
#include <net/bluetooth/bluetooth.h>
-#define SAVE_FW_DUMP_IN_KERNEL 1
+#define SAVE_FW_DUMP_IN_KERNEL 0
-#define SUPPORT_FW_DUMP 1
+#define SUPPORT_FW_DUMP 1
#define BTM_HEADER_LEN 5
#define BTM_UPLD_SIZE 2312
@@ -126,6 +126,7 @@
struct task_struct *fw_dump_tsk;
struct task_struct *fw_dump_end_check_tsk;
#endif
+ bool no_fw_own;
};
#define MTK_VENDOR_PKT 0xFE
@@ -222,13 +223,9 @@
};
#ifdef CONFIG_DEBUG_FS
-
#define FIXED_STPBT_MAJOR_DEV_ID 111
-
-
#define FW_DUMP_END_EVENT "coredump end"
-
#endif
#endif
diff --git a/btmtk_sdio.c b/btmtk_sdio.c
index ad3e466..b2d50de 100644
--- a/btmtk_sdio.c
+++ b/btmtk_sdio.c
@@ -64,6 +64,7 @@
/*static int btmtk_woble_state = BTMTK_WOBLE_STATE_UNKNOWN;*/
static int need_reset_stack;
+static int need_set_i2s = 0;
/* The btmtk_sdio_remove() callback function is called
* when user removes this module from kernel space or ejects
* the card from the slot. The driver handles these 2 cases
@@ -103,6 +104,7 @@
static int btmtk_proc_show(struct seq_file *m, void *v);
static int btmtk_proc_open(struct inode *inode, struct file *file);
static void btmtk_proc_create_new_entry(void);
+static int btmtk_sdio_trigger_fw_assert(void);
static char fw_dump_file_name[FW_DUMP_FILE_NAME_SIZE] = {0};
static char event_need_compare[EVENT_COMPARE_SIZE] = {0};
@@ -110,6 +112,8 @@
static char event_compare_status;
/*add special header in the beginning of even, stack won't recognize these event*/
+struct _OSAL_UNSLEEPABLE_LOCK_ event_compare_status_lock;
+struct _OSAL_UNSLEEPABLE_LOCK_ tx_function_lock;
@@ -587,38 +591,13 @@
return ret;
}
-struct sk_buff *btmtk_create_send_data(struct sk_buff *skb)
+static void btmtk_sdio_set_no_fw_own(struct btmtk_private *priv, bool no_fw_own)
{
- struct sk_buff *queue_skb = NULL;
- u32 sdio_header_len = skb->len + BTM_HEADER_LEN;
-
- if (skb_headroom(skb) < (BTM_HEADER_LEN)) {
- queue_skb = bt_skb_alloc(sdio_header_len, GFP_ATOMIC);
- if (queue_skb == NULL) {
- pr_err("bt_skb_alloc fail return\n");
- return 0;
- }
-
- queue_skb->data[0] = (sdio_header_len & 0x0000ff);
- queue_skb->data[1] = (sdio_header_len & 0x00ff00) >> 8;
- queue_skb->data[2] = 0;
- queue_skb->data[3] = 0;
- queue_skb->data[4] = bt_cb(skb)->pkt_type;
- queue_skb->len = sdio_header_len;
- memcpy(&queue_skb->data[5], &skb->data[0], skb->len);
- kfree_skb(skb);
- } else {
- queue_skb = skb;
- skb_push(queue_skb, BTM_HEADER_LEN);
- queue_skb->data[0] = (sdio_header_len & 0x0000ff);
- queue_skb->data[1] = (sdio_header_len & 0x00ff00) >> 8;
- queue_skb->data[2] = 0;
- queue_skb->data[3] = 0;
- queue_skb->data[4] = bt_cb(skb)->pkt_type;
- }
-
- pr_info("%s end\n", __func__);
- return queue_skb;
+ if (priv) {
+ priv->no_fw_own = no_fw_own;
+ pr_debug("%s set no_fw_own %d\n", __func__, priv->no_fw_own);
+ } else
+ pr_debug("%s priv is NULL\n", __func__);
}
static int btmtk_sdio_set_own_back(int owntype)
@@ -635,6 +614,13 @@
if (user_rmmod)
set_checkretry = 1;
+ if (owntype == FW_OWN && (g_priv)) {
+ if (g_priv->no_fw_own) {
+ pr_debug("%s no_fw_own is on, just return \n", __func__);
+ return ret;
+ }
+ }
+
ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue);
pr_debug("%s btmtk_sdio_readl CHLPCR done\n", __func__);
@@ -1476,8 +1462,7 @@
}
} while (ret);
- if (priv)
- priv->btmtk_dev.tx_dnld_rdy = false;
+ priv->btmtk_dev.tx_dnld_rdy = false;
exit:
@@ -2135,6 +2120,7 @@
u32 dump_len = 0;
char *core_dump_end = NULL;
int i = 0;
+ u8 reset_event[] = {0x0E, 0x04, 0x01, 0x03, 0x0C, 0x00};
static int print_dump_data_counter;
#if SUPPORT_FW_DUMP
@@ -2177,6 +2163,7 @@
fw_dump_file_name,
O_RDWR | O_CREAT,
0644);
+ btmtk_sdio_set_no_fw_own(g_priv, TRUE);
print_dump_data_counter = 0;
if (!(IS_ERR(fw_dump_file))) {
current_fwdump_file_number =
@@ -2216,7 +2203,7 @@
#endif
/* This is coredump data, save coredump data to picus_queue */
- pr_debug("%s : Receive coredump data, move data to fwlog queue for picus", __func__);
+ pr_info("%s : Receive coredump data, move data to fwlog queue for picus", __func__);
buf_len = rx_length-(MTK_SDIO_PACKET_HEADER_SIZE+1);
lock_unsleepable_lock(&(fwlog_metabuffer.spin_lock));
fwlog_fops_skb = bt_skb_alloc(buf_len, GFP_ATOMIC);
@@ -2226,12 +2213,13 @@
pr_debug("%s fwlog_fops_skb length = %d, buf_len = %d\n",
__func__, fwlog_fops_skb->len, buf_len);
if (skb_queue_empty(&g_priv->adapter->fwlog_fops_queue))
- pr_warn("%s fwlog_fops_queue is empty empty\n", __func__);
+ pr_info("%s fwlog_fops_queue is empty empty\n", __func__);
kfree_skb(skb);
wake_up_interruptible(&fw_log_inq);
unlock_unsleepable_lock(&(fwlog_metabuffer.spin_lock));
+#ifdef CONFIG_DEBUG_FS
if (dump_len >= sizeof(FW_DUMP_END_EVENT)) {
core_dump_end = strstr(
&rxbuf[SDIO_HEADER_LEN+10],
@@ -2241,6 +2229,7 @@
if (core_dump_end)
btmtk_sdio_for_code_style();
}
+#endif
}
}
}
@@ -2315,8 +2304,20 @@
case HCI_EVENT_PKT:
buf_len = skb->data[1] + 2;
break;
+ default:
+ BTSDIO_INFO_RAW(skb->data, (buf_len < 16 ? buf_len : 16), "%s: skb->data(type %d):", __func__, type);
+ /* trigger fw core dump */
+ btmtk_sdio_trigger_fw_assert();
+ ret = -EINVAL;
+ goto exit;
}
+ if ((g_priv->adapter->fops_mode == true) &&
+ memcmp(skb->data, reset_event, sizeof(reset_event)) == 0)
+ {
+ pr_debug("%s get reset complete event!\n", __func__);
+ need_set_i2s = 1;
+ }
if (event_compare_status == BTMTK_SDIO_EVENT_COMPARE_STATE_NEED_COMPARE)
BTSDIO_DEBUG_RAW(skb->data, buf_len, "%s: skb->data :", __func__);
@@ -2348,7 +2349,10 @@
if (buf_len >= event_need_compare_len) {
if (memcmp(skb->data, event_need_compare, event_need_compare_len) == 0) {
event_compare_status = BTMTK_SDIO_EVENT_COMPARE_STATE_COMPARE_SUCCESS;
- pr_debug("%s compare success\n", __func__);
+ pr_info("%s compare success and goto exit !\n", __func__);
+ /* for VTS loopback mode test, the command send by driver event should not report to stack */
+ kfree_skb(skb);
+ goto exit;
} else {
pr_debug("%s compare fail\n", __func__);
BTSDIO_DEBUG_RAW(event_need_compare, event_need_compare_len,
@@ -2409,6 +2413,12 @@
u32 u32ReadCRValue = 0;
ret = btmtk_sdio_readl(CHISR, &u32ReadCRValue);
+ pr_debug("%s CHISR 0x%08x\n", __func__, u32ReadCRValue);
+ if (u32ReadCRValue & FIRMWARE_INT_BIT15) {
+ btmtk_sdio_set_no_fw_own(g_priv, TRUE);
+ btmtk_sdio_writel(CHISR, FIRMWARE_INT_BIT15);
+ }
+
pr_debug("%s check TX_EMPTY CHISR 0x%08x\n", __func__, u32ReadCRValue);
if (TX_EMPTY&u32ReadCRValue) {
ret = btmtk_sdio_writel(CHISR, (TX_EMPTY | TX_COMPLETE_COUNT));
@@ -2420,12 +2430,14 @@
ret = btmtk_sdio_recv_rx_data();
if (ret == 0) {
+ lock_unsleepable_lock(&event_compare_status_lock);
while (rx_length > (MTK_SDIO_PACKET_HEADER_SIZE)) {
btmtk_sdio_card_to_host(priv, NULL, -1, 0);
u32rxdatacount++;
pr_debug("%s u32rxdatacount %d\n",
__func__, u32rxdatacount);
}
+ unlock_unsleepable_lock(&event_compare_status_lock);
}
btmtk_sdio_enable_interrupt(1);
@@ -2909,7 +2921,8 @@
btmtk_sdio_set_i2s();
/* Move from btmtk_fops_open() */
spin_lock_init(&(metabuffer.spin_lock.lock));
- spin_lock_init(&(fwlog_metabuffer.spin_lock.lock));
+ spin_lock_init(&(event_compare_status_lock.lock));
+ spin_lock_init(&(tx_function_lock.lock));
pr_debug("%s spin_lock_init end\n", __func__);
priv = btmtk_add_card(card);
@@ -3085,6 +3098,34 @@
return ret;
}
+static int btmtk_sdio_trigger_fw_assert(void)
+{
+ int ret = 0;
+ u8 cmd[] = { 0x5b, 0xfd, 0x00 };
+
+ pr_info("%s begin\n", __func__);
+ ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd,
+ sizeof(cmd),
+ NULL, 0, WOBLE_COMP_EVENT_TIMO, 1);
+ if (ret != 0)
+ pr_info("%s ret = %d \n", __func__, ret);
+ return ret;
+}
+
+static int btmtk_sdio_send_set_i2s_slave(void)
+{
+ int ret = 0;
+ u8 comp_event[] = {0xE, 0x04, 0x01, 0x72, 0xFC, 0x00 };
+ u8 cmd[] = { 0x72, 0xFC, 4, 03, 0x10, 0x00, 0x02 };
+
+ ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd,
+ sizeof(cmd),
+ comp_event, sizeof(comp_event), WOBLE_COMP_EVENT_TIMO, 1);
+ if (ret != 0)
+ pr_info("%s ret = %d \n", __func__, ret);
+ return ret;
+}
+
static int btmtk_sdio_send_get_vendor_cap(void)
{
int ret = -1;
@@ -3499,7 +3540,6 @@
pr_info("%s:irq_enable count:%d\n", __func__, atomic_read(&(g_card->irq_enable_count)));
#endif
-
if (func) {
pm_flags = sdio_get_host_pm_caps(func);
pr_debug("%s: suspend: PM flags = 0x%x\n",
@@ -3568,6 +3608,21 @@
}
};
+static int btmtk_sdio_send_hci_reset(void)
+{
+ int ret = 0;
+ u8 comp_event[] = {0x0e, 0x04, 0x01, 0x03, 0x0c, 0x00 };
+ u8 cmd[] = { 0x03, 0x0c, 0x00 };
+
+ pr_info("%s begin\n", __func__);
+ ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd,
+ sizeof(cmd),
+ comp_event, sizeof(comp_event), WOBLE_COMP_EVENT_TIMO, 1);
+ if (ret != 0)
+ pr_info("%s ret = %d \n", __func__, ret);
+ return ret;
+}
+
static int btmtk_clean_queue(void)
{
struct sk_buff *skb = NULL;
@@ -3640,6 +3695,8 @@
if (g_priv)
g_priv->adapter->fops_mode = false;
+ /* for VTS loopback mode test */
+ btmtk_sdio_send_hci_reset();
btmtk_clean_queue();
pr_info("%s fops_mode=%d end\n", __func__, g_priv->adapter->fops_mode);
@@ -3846,6 +3903,12 @@
}
}
+ if (need_set_i2s == 1) {
+ pr_info("%s get reset complete and set I2S !\n",__func__ );
+ btmtk_sdio_send_set_i2s_slave();
+ need_set_i2s = 0;
+ }
+
lock_unsleepable_lock(&(metabuffer.spin_lock));
if (skb_queue_empty(&g_priv->adapter->fops_queue)) {
/* if (filp->f_flags & O_NONBLOCK) { */
@@ -4051,8 +4114,6 @@
return -EFAULT;
}
- btmtk_sdio_set_own_back(DRIVER_OWN);
-
if (g_priv == NULL) {
pr_info("%s g_priv is NULL\n", __func__);
goto exit;
@@ -4390,12 +4451,12 @@
dev_t devIDfwlog = g_devIDfwlog;
pr_info("%s\n", __func__);
-
- if (g_proc_dir != NULL) {
+ if (g_proc_dir != 0) {
+ g_proc_dir = 0;
remove_proc_entry("bt_fw_version", g_proc_dir);
remove_proc_entry("stpbt", NULL);
- g_proc_dir = NULL;
pr_info("proc device node and folder removed!!");
+ return;
}
if (g_card) {
@@ -4440,6 +4501,9 @@
cdev_del(&BTMTK_cdev);
pr_info("%s 10\n", __func__);
unregister_chrdev_region(dev, 1);
+
+ cdev_del(&BT_cdevfwlog);
+ unregister_chrdev_region(devIDfwlog, 1);
pr_info("%s driver removed.\n", BT_DRIVER_NAME);
}
diff --git a/btmtk_sdio.h b/btmtk_sdio.h
index 6674d95..486daff 100644
--- a/btmtk_sdio.h
+++ b/btmtk_sdio.h
@@ -19,7 +19,7 @@
#endif
-#define VERSION "v0.0.0.51_2018031901_YOCTO"
+#define VERSION "v0.0.0.52_2018070901_YOCTO"
#define SDIO_HEADER_LEN 4
@@ -224,6 +224,7 @@
/*CHISR*/
#define RX_PKT_LEN 0xFFFF0000
#define FIRMWARE_INT 0x0000FE00
+#define FIRMWARE_INT_BIT15 0x00008000/*FW inform driver don't change to fw own for dore dump*/
#define TX_FIFO_OVERFLOW 0x00000100
#define FW_INT_IND_INDICATOR 0x00000080
#define TX_COMPLETE_COUNT 0x00000070