mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
Bluetooth: Add vhci devcoredump support
Add devcoredump support for vhci that creates forcce_devcoredump debugfs entry. This is used for mgmt-tester tests. Signed-off-by: Manish Mandlik <mmandlik@google.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
9695ef876f
commit
ab4e4380d4
@ -363,6 +363,7 @@ config BT_HCIBLUECARD
|
|||||||
|
|
||||||
config BT_HCIVHCI
|
config BT_HCIVHCI
|
||||||
tristate "HCI VHCI (Virtual HCI device) driver"
|
tristate "HCI VHCI (Virtual HCI device) driver"
|
||||||
|
select WANT_DEV_COREDUMP
|
||||||
help
|
help
|
||||||
Bluetooth Virtual HCI device driver.
|
Bluetooth Virtual HCI device driver.
|
||||||
This driver is required if you want to use HCI Emulation software.
|
This driver is required if you want to use HCI Emulation software.
|
||||||
|
|||||||
@ -278,6 +278,100 @@ static int vhci_setup(struct hci_dev *hdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vhci_coredump(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
/* No need to do anything */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhci_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
char buf[80];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Controller Name: vhci_ctrl\n");
|
||||||
|
skb_put_data(skb, buf, strlen(buf));
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Firmware Version: vhci_fw\n");
|
||||||
|
skb_put_data(skb, buf, strlen(buf));
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Driver: vhci_drv\n");
|
||||||
|
skb_put_data(skb, buf, strlen(buf));
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Vendor: vhci\n");
|
||||||
|
skb_put_data(skb, buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_COREDUMP_LINE_LEN 40
|
||||||
|
|
||||||
|
struct devcoredump_test_data {
|
||||||
|
enum devcoredump_state state;
|
||||||
|
unsigned int timeout;
|
||||||
|
char data[MAX_COREDUMP_LINE_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void force_devcd_timeout(struct hci_dev *hdev,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_DEV_COREDUMP
|
||||||
|
hdev->dump.timeout = msecs_to_jiffies(timeout * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t force_devcd_write(struct file *file, const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct vhci_data *data = file->private_data;
|
||||||
|
struct hci_dev *hdev = data->hdev;
|
||||||
|
struct sk_buff *skb = NULL;
|
||||||
|
struct devcoredump_test_data dump_data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = simple_write_to_buffer(&dump_data, sizeof(dump_data), ppos,
|
||||||
|
user_buf, count);
|
||||||
|
if (ret < count)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
skb = alloc_skb(sizeof(dump_data.data), GFP_ATOMIC);
|
||||||
|
if (!skb)
|
||||||
|
return -ENOMEM;
|
||||||
|
skb_put_data(skb, &dump_data.data, sizeof(dump_data.data));
|
||||||
|
|
||||||
|
hci_devcd_register(hdev, vhci_coredump, vhci_coredump_hdr, NULL);
|
||||||
|
|
||||||
|
/* Force the devcoredump timeout */
|
||||||
|
if (dump_data.timeout)
|
||||||
|
force_devcd_timeout(hdev, dump_data.timeout);
|
||||||
|
|
||||||
|
ret = hci_devcd_init(hdev, skb->len);
|
||||||
|
if (ret) {
|
||||||
|
BT_ERR("Failed to generate devcoredump");
|
||||||
|
kfree_skb(skb);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_devcd_append(hdev, skb);
|
||||||
|
|
||||||
|
switch (dump_data.state) {
|
||||||
|
case HCI_DEVCOREDUMP_DONE:
|
||||||
|
hci_devcd_complete(hdev);
|
||||||
|
break;
|
||||||
|
case HCI_DEVCOREDUMP_ABORT:
|
||||||
|
hci_devcd_abort(hdev);
|
||||||
|
break;
|
||||||
|
case HCI_DEVCOREDUMP_TIMEOUT:
|
||||||
|
/* Do nothing */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations force_devcoredump_fops = {
|
||||||
|
.open = simple_open,
|
||||||
|
.write = force_devcd_write,
|
||||||
|
};
|
||||||
|
|
||||||
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
@ -355,6 +449,9 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
|||||||
debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data,
|
debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data,
|
||||||
&aosp_capable_fops);
|
&aosp_capable_fops);
|
||||||
|
|
||||||
|
debugfs_create_file("force_devcoredump", 0644, hdev->debugfs, data,
|
||||||
|
&force_devcoredump_fops);
|
||||||
|
|
||||||
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
|
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
|
||||||
|
|
||||||
skb_put_u8(skb, 0xff);
|
skb_put_u8(skb, 0xff);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user