Commit ab4e4380 authored by Manish Mandlik's avatar Manish Mandlik Committed by Luiz Augusto von Dentz
Browse files

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: default avatarManish Mandlik <mmandlik@google.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 9695ef87
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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.
+97 −0
Original line number Original line Diff line number Diff line
@@ -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);