Commit d210ee58 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'for-net-next-2025-09-27' of...

Merge tag 'for-net-next-2025-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Luiz Augusto von Dentz says:

====================
bluetooth-next pull request for net-next:

core:

 - MAINTAINERS: add a sub-entry for the Qualcomm bluetooth driver
 - Avoid a couple dozen -Wflex-array-member-not-at-end warnings
 - bcsp: receive data only if registered
 - HCI: Fix using LE/ACL buffers for ISO packets
 - hci_core: Detect if an ISO link has stalled
 - ISO: Don't initiate CIS connections if there are no buffers
 - ISO: Use sk_sndtimeo as conn_timeout

drivers:

 - btusb: Check for unexpected bytes when defragmenting HCI frames
 - btusb: Add new VID/PID 13d3/3627 for MT7925
 - btusb: Add new VID/PID 13d3/3633 for MT7922
 - btusb: Add USB ID 2001:332a for D-Link AX9U rev. A1
 - btintel: Add support for BlazarIW core
 - btintel_pcie: Add support for _suspend() / _resume()
 - btintel_pcie: Define hdev->wakeup() callback
 - btintel_pcie: Add Bluetooth core/platform as comments
 - btintel_pcie: Add id of Scorpious, Panther Lake-H484
 - btintel_pcie: Refactor Device Coredump

* tag 'for-net-next-2025-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: (30 commits)
  Bluetooth: Avoid a couple dozen -Wflex-array-member-not-at-end warnings
  Bluetooth: hci_sync: Fix using random address for BIG/PA advertisements
  Bluetooth: ISO: don't leak skb in ISO_CONT RX
  Bluetooth: ISO: free rx_skb if not consumed
  Bluetooth: ISO: Fix possible UAF on iso_conn_free
  Bluetooth: SCO: Fix UAF on sco_conn_free
  Bluetooth: bcsp: receive data only if registered
  Bluetooth: btusb: Add new VID/PID 13d3/3633 for MT7922
  Bluetooth: btusb: Add new VID/PID 13d3/3627 for MT7925
  Bluetooth: remove duplicate h4_recv_buf() in header
  Bluetooth: btusb: Check for unexpected bytes when defragmenting HCI frames
  Bluetooth: hci_core: Print information of hcon on hci_low_sent
  Bluetooth: hci_core: Print number of packets in conn->data_q
  Bluetooth: Add function and line information to bt_dbg
  Bluetooth: MGMT: Fix not exposing debug UUID on MGMT_OP_READ_EXP_FEATURES_INFO
  Bluetooth: hci_core: Detect if an ISO link has stalled
  Bluetooth: ISO: Use sk_sndtimeo as conn_timeout
  Bluetooth: HCI: Fix using LE/ACL buffers for ISO packets
  Bluetooth: ISO: Don't initiate CIS connections if there are no buffers
  MAINTAINERS: add a sub-entry for the Qualcomm bluetooth driver
  ...
====================

Link: https://patch.msgid.link/20250927154616.1032839-1-luiz.dentz@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents c39d6d4d be812ace
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -20686,6 +20686,13 @@ S: Maintained
F:	Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
F:	drivers/net/wwan/qcom_bam_dmux.c
QUALCOMM BLUETOOTH DRIVER
L:	linux-arm-msm@vger.kernel.org
S:	Maintained
F:	drivers/bluetooth/btqca.[ch]
F:	drivers/bluetooth/btqcomsmd.c
F:	drivers/bluetooth/hci_qca.c
QUALCOMM CAMERA SUBSYSTEM DRIVER
M:	Robert Foss <rfoss@kernel.org>
M:	Todor Tomov <todor.too@gmail.com>
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>

#include "h4_recv.h"
#include "hci_uart.h"

#define VERSION "0.11"

+3 −0
Original line number Diff line number Diff line
@@ -484,6 +484,7 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
	case 0x1d:	/* BlazarU (BzrU) */
	case 0x1e:	/* BlazarI (Bzr) */
	case 0x1f:      /* Scorpious Peak */
	case 0x22:	/* BlazarIW (BzrIW) */
		break;
	default:
		bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
@@ -3253,6 +3254,7 @@ void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant)
	case 0x1d:
	case 0x1e:
	case 0x1f:
	case 0x22:
		hci_set_msft_opcode(hdev, 0xFC1E);
		break;
	default:
@@ -3593,6 +3595,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
	case 0x1d:
	case 0x1e:
	case 0x1f:
	case 0x22:
		/* Display version information of TLV type */
		btintel_version_info_tlv(hdev, &ver_tlv);

+181 −147
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>

#include <linux/unaligned.h>
#include <linux/devcoredump.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -35,8 +36,13 @@

/* Intel Bluetooth PCIe device id table */
static const struct pci_device_id btintel_pcie_table[] = {
	/* BlazarI, Wildcat Lake */
	{ BTINTEL_PCI_DEVICE(0x4D76, PCI_ANY_ID) },
	/* BlazarI, Lunar Lake */
	{ BTINTEL_PCI_DEVICE(0xA876, PCI_ANY_ID) },
	/* Scorpious, Panther Lake-H484 */
	{ BTINTEL_PCI_DEVICE(0xE376, PCI_ANY_ID) },
	 /* Scorpious, Panther Lake-H404 */
	{ BTINTEL_PCI_DEVICE(0xE476, PCI_ANY_ID) },
	{ 0 }
};
@@ -554,25 +560,6 @@ static void btintel_pcie_mac_init(struct btintel_pcie_data *data)
	btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}

static int btintel_pcie_add_dmp_data(struct hci_dev *hdev, const void *data, int size)
{
	struct sk_buff *skb;
	int err;

	skb = alloc_skb(size, GFP_ATOMIC);
	if (!skb)
		return -ENOMEM;

	skb_put_data(skb, data, size);
	err = hci_devcd_append(hdev, skb);
	if (err) {
		bt_dev_err(hdev, "Failed to append data in the coredump");
		return err;
	}

	return 0;
}

static int btintel_pcie_get_mac_access(struct btintel_pcie_data *data)
{
	u32 reg;
@@ -617,30 +604,35 @@ static void btintel_pcie_release_mac_access(struct btintel_pcie_data *data)
	btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}

static void btintel_pcie_copy_tlv(struct sk_buff *skb, enum btintel_pcie_tlv_type type,
				  void *data, int size)
static void *btintel_pcie_copy_tlv(void *dest, enum btintel_pcie_tlv_type type,
				   void *data, size_t size)
{
	struct intel_tlv *tlv;

	tlv = skb_put(skb, sizeof(*tlv) + size);
	tlv = dest;
	tlv->type = type;
	tlv->len = size;
	memcpy(tlv->val, data, tlv->len);
	return dest + sizeof(*tlv) + size;
}

static int btintel_pcie_read_dram_buffers(struct btintel_pcie_data *data)
{
	u32 offset, prev_size, wr_ptr_status, dump_size, i;
	u32 offset, prev_size, wr_ptr_status, dump_size, data_len;
	struct btintel_pcie_dbgc *dbgc = &data->dbgc;
	u8 buf_idx, dump_time_len, fw_build;
	struct hci_dev *hdev = data->hdev;
	u8 *pdata, *p, buf_idx;
	struct intel_tlv *tlv;
	struct timespec64 now;
	struct sk_buff *skb;
	struct tm tm_now;
	char buf[256];
	u16 hdr_len;
	int ret;
	char fw_build[128];
	char ts[128];
	char vendor[64];
	char driver[64];

	if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
		return -EOPNOTSUPP;


	wr_ptr_status = btintel_pcie_rd_dev_mem(data, BTINTEL_PCIE_DBGC_CUR_DBGBUFF_STATUS);
	offset = wr_ptr_status & BTINTEL_PCIE_DBG_OFFSET_BIT_MASK;
@@ -657,88 +649,84 @@ static int btintel_pcie_read_dram_buffers(struct btintel_pcie_data *data)
	else
		return -EINVAL;

	snprintf(vendor, sizeof(vendor), "Vendor: Intel\n");
	snprintf(driver, sizeof(driver), "Driver: %s\n",
		 data->dmp_hdr.driver_name);

	ktime_get_real_ts64(&now);
	time64_to_tm(now.tv_sec, 0, &tm_now);
	dump_time_len = snprintf(buf, sizeof(buf), "Dump Time: %02d-%02d-%04ld %02d:%02d:%02d",
	snprintf(ts, sizeof(ts), "Dump Time: %02d-%02d-%04ld %02d:%02d:%02d",
				 tm_now.tm_mday, tm_now.tm_mon + 1, tm_now.tm_year + 1900,
				 tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec);

	fw_build = snprintf(buf + dump_time_len, sizeof(buf) - dump_time_len,
	snprintf(fw_build, sizeof(fw_build),
			    "Firmware Timestamp: Year %u WW %02u buildtype %u build %u",
			    2000 + (data->dmp_hdr.fw_timestamp >> 8),
			    data->dmp_hdr.fw_timestamp & 0xff, data->dmp_hdr.fw_build_type,
			    data->dmp_hdr.fw_build_num);

	hdr_len = sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_bt) +
	data_len = sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_bt) +
		sizeof(*tlv) + sizeof(data->dmp_hdr.write_ptr) +
		sizeof(*tlv) + sizeof(data->dmp_hdr.wrap_ctr) +
		sizeof(*tlv) + sizeof(data->dmp_hdr.trigger_reason) +
		sizeof(*tlv) + sizeof(data->dmp_hdr.fw_git_sha1) +
		sizeof(*tlv) + sizeof(data->dmp_hdr.cnvr_top) +
		sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_top) +
		  sizeof(*tlv) + dump_time_len +
		  sizeof(*tlv) + fw_build;
		sizeof(*tlv) + strlen(ts) +
		sizeof(*tlv) + strlen(fw_build) +
		sizeof(*tlv) + strlen(vendor) +
		sizeof(*tlv) + strlen(driver);

	dump_size = hdr_len + sizeof(hdr_len);
	/*
	 * sizeof(u32) - signature
	 * sizeof(data_len) - to store tlv data size
	 * data_len - TLV data
	 */
	dump_size = sizeof(u32) + sizeof(data_len) + data_len;

	skb = alloc_skb(dump_size, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	/* Add debug buffers data length to dump size */
	dump_size += BTINTEL_PCIE_DBGC_BUFFER_SIZE * dbgc->count;

	ret = hci_devcd_init(hdev, dump_size);
	if (ret) {
		bt_dev_err(hdev, "Failed to init devcoredump, err %d", ret);
		kfree_skb(skb);
		return ret;
	}
	pdata = vmalloc(dump_size);
	if (!pdata)
		return -ENOMEM;
	p = pdata;

	skb_put_data(skb, &hdr_len, sizeof(hdr_len));
	*(u32 *)p = BTINTEL_PCIE_MAGIC_NUM;
	p += sizeof(u32);

	btintel_pcie_copy_tlv(skb, BTINTEL_CNVI_BT, &data->dmp_hdr.cnvi_bt,
			      sizeof(data->dmp_hdr.cnvi_bt));
	*(u32 *)p = data_len;
	p += sizeof(u32);

	btintel_pcie_copy_tlv(skb, BTINTEL_WRITE_PTR, &data->dmp_hdr.write_ptr,

	p = btintel_pcie_copy_tlv(p, BTINTEL_VENDOR, vendor, strlen(vendor));
	p = btintel_pcie_copy_tlv(p, BTINTEL_DRIVER, driver, strlen(driver));
	p = btintel_pcie_copy_tlv(p, BTINTEL_DUMP_TIME, ts, strlen(ts));
	p = btintel_pcie_copy_tlv(p, BTINTEL_FW_BUILD, fw_build,
				  strlen(fw_build));
	p = btintel_pcie_copy_tlv(p, BTINTEL_CNVI_BT, &data->dmp_hdr.cnvi_bt,
				  sizeof(data->dmp_hdr.cnvi_bt));
	p = btintel_pcie_copy_tlv(p, BTINTEL_WRITE_PTR, &data->dmp_hdr.write_ptr,
				  sizeof(data->dmp_hdr.write_ptr));
	p = btintel_pcie_copy_tlv(p, BTINTEL_WRAP_CTR, &data->dmp_hdr.wrap_ctr,
				  sizeof(data->dmp_hdr.wrap_ctr));

	data->dmp_hdr.wrap_ctr = btintel_pcie_rd_dev_mem(data,
							 BTINTEL_PCIE_DBGC_DBGBUFF_WRAP_ARND);

	btintel_pcie_copy_tlv(skb, BTINTEL_WRAP_CTR, &data->dmp_hdr.wrap_ctr,
			      sizeof(data->dmp_hdr.wrap_ctr));

	btintel_pcie_copy_tlv(skb, BTINTEL_TRIGGER_REASON, &data->dmp_hdr.trigger_reason,
	p = btintel_pcie_copy_tlv(p, BTINTEL_TRIGGER_REASON, &data->dmp_hdr.trigger_reason,
				  sizeof(data->dmp_hdr.trigger_reason));

	btintel_pcie_copy_tlv(skb, BTINTEL_FW_SHA, &data->dmp_hdr.fw_git_sha1,
	p = btintel_pcie_copy_tlv(p, BTINTEL_FW_SHA, &data->dmp_hdr.fw_git_sha1,
				  sizeof(data->dmp_hdr.fw_git_sha1));

	btintel_pcie_copy_tlv(skb, BTINTEL_CNVR_TOP, &data->dmp_hdr.cnvr_top,
	p = btintel_pcie_copy_tlv(p, BTINTEL_CNVR_TOP, &data->dmp_hdr.cnvr_top,
				  sizeof(data->dmp_hdr.cnvr_top));

	btintel_pcie_copy_tlv(skb, BTINTEL_CNVI_TOP, &data->dmp_hdr.cnvi_top,
	p = btintel_pcie_copy_tlv(p, BTINTEL_CNVI_TOP, &data->dmp_hdr.cnvi_top,
				  sizeof(data->dmp_hdr.cnvi_top));

	btintel_pcie_copy_tlv(skb, BTINTEL_DUMP_TIME, buf, dump_time_len);

	btintel_pcie_copy_tlv(skb, BTINTEL_FW_BUILD, buf + dump_time_len, fw_build);

	ret = hci_devcd_append(hdev, skb);
	if (ret)
		goto exit_err;

	for (i = 0; i < dbgc->count; i++) {
		ret = btintel_pcie_add_dmp_data(hdev, dbgc->bufs[i].data,
						BTINTEL_PCIE_DBGC_BUFFER_SIZE);
		if (ret)
			break;
	}

exit_err:
	hci_devcd_complete(hdev);
	return ret;
	memcpy(p, dbgc->bufs[0].data, dbgc->count * BTINTEL_PCIE_DBGC_BUFFER_SIZE);
	dev_coredumpv(&hdev->dev, pdata, dump_size, GFP_KERNEL);
	return 0;
}

static void btintel_pcie_dump_traces(struct hci_dev *hdev)
@@ -760,51 +748,6 @@ static void btintel_pcie_dump_traces(struct hci_dev *hdev)
		bt_dev_err(hdev, "Failed to dump traces: (%d)", ret);
}

static void btintel_pcie_dump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct btintel_pcie_data *data = hci_get_drvdata(hdev);
	u16 len = skb->len;
	u16 *hdrlen_ptr;
	char buf[80];

	hdrlen_ptr = skb_put_zero(skb, sizeof(len));

	snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
		 INTEL_HW_VARIANT(data->dmp_hdr.cnvi_bt));
	skb_put_data(skb, buf, strlen(buf));

	snprintf(buf, sizeof(buf), "Firmware Build Number: %u\n",
		 data->dmp_hdr.fw_build_num);
	skb_put_data(skb, buf, strlen(buf));

	snprintf(buf, sizeof(buf), "Driver: %s\n", data->dmp_hdr.driver_name);
	skb_put_data(skb, buf, strlen(buf));

	snprintf(buf, sizeof(buf), "Vendor: Intel\n");
	skb_put_data(skb, buf, strlen(buf));

	*hdrlen_ptr = skb->len - len;
}

static void btintel_pcie_dump_notify(struct hci_dev *hdev, int state)
{
	struct btintel_pcie_data *data = hci_get_drvdata(hdev);

	switch (state) {
	case HCI_DEVCOREDUMP_IDLE:
		data->dmp_hdr.state = HCI_DEVCOREDUMP_IDLE;
		break;
	case HCI_DEVCOREDUMP_ACTIVE:
		data->dmp_hdr.state = HCI_DEVCOREDUMP_ACTIVE;
		break;
	case HCI_DEVCOREDUMP_TIMEOUT:
	case HCI_DEVCOREDUMP_ABORT:
	case HCI_DEVCOREDUMP_DONE:
		data->dmp_hdr.state = HCI_DEVCOREDUMP_IDLE;
		break;
	}
}

/* This function enables BT function by setting BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT bit in
 * BTINTEL_PCIE_CSR_FUNC_CTRL_REG register and wait for MSI-X with
 * BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0.
@@ -1378,6 +1321,11 @@ static void btintel_pcie_rx_work(struct work_struct *work)
					struct btintel_pcie_data, rx_work);
	struct sk_buff *skb;

	if (test_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags)) {
		btintel_pcie_dump_traces(data->hdev);
		clear_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags);
	}

	if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) {
		/* Unlike usb products, controller will not send hardware
		 * exception event on exception. Instead controller writes the
@@ -1390,11 +1338,6 @@ static void btintel_pcie_rx_work(struct work_struct *work)
		clear_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags);
	}

	if (test_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags)) {
		btintel_pcie_dump_traces(data->hdev);
		clear_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags);
	}

	/* Process the sk_buf in queue and send to the HCI layer */
	while ((skb = skb_dequeue(&data->rx_skb_q))) {
		btintel_pcie_recv_frame(data, skb);
@@ -2149,6 +2092,7 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
	switch (INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) {
	case 0x1e:	/* BzrI */
	case 0x1f:	/* ScP  */
	case 0x22:	/* BzrIW */
		/* Display version information of TLV type */
		btintel_version_info_tlv(hdev, &ver_tlv);

@@ -2184,13 +2128,6 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
	if (ver_tlv.img_type == 0x02 || ver_tlv.img_type == 0x03)
		data->dmp_hdr.fw_git_sha1 = ver_tlv.git_sha1;

	err = hci_devcd_register(hdev, btintel_pcie_dump_traces, btintel_pcie_dump_hdr,
				 btintel_pcie_dump_notify);
	if (err) {
		bt_dev_err(hdev, "Failed to register coredump (%d)", err);
		goto exit_error;
	}

	btintel_print_fseq_info(hdev);
exit_error:
	kfree_skb(skb);
@@ -2236,6 +2173,7 @@ btintel_pcie_get_recovery(struct pci_dev *pdev, struct device *dev)
{
	struct btintel_pcie_dev_recovery *tmp, *data = NULL;
	const char *name = pci_name(pdev);
	const size_t name_len = strlen(name) + 1;
	struct hci_dev *hdev = to_hci_dev(dev);

	spin_lock(&btintel_pcie_recovery_lock);
@@ -2252,11 +2190,11 @@ btintel_pcie_get_recovery(struct pci_dev *pdev, struct device *dev)
		return data;
	}

	data = kzalloc(struct_size(data, name, strlen(name) + 1), GFP_ATOMIC);
	data = kzalloc(struct_size(data, name, name_len), GFP_ATOMIC);
	if (!data)
		return NULL;

	strscpy_pad(data->name, name, strlen(name) + 1);
	strscpy(data->name, name, name_len);
	spin_lock(&btintel_pcie_recovery_lock);
	list_add_tail(&data->list, &btintel_pcie_recovery_list);
	spin_unlock(&btintel_pcie_recovery_lock);
@@ -2319,7 +2257,6 @@ static void btintel_pcie_removal_work(struct work_struct *wk)
	btintel_pcie_synchronize_irqs(data);

	flush_work(&data->rx_work);
	flush_work(&data->hdev->dump.dump_rx);

	bt_dev_dbg(data->hdev, "Release bluetooth interface");
	btintel_pcie_release_hdev(data);
@@ -2410,6 +2347,13 @@ static void btintel_pcie_hw_error(struct hci_dev *hdev, u8 code)
	btintel_pcie_reset(hdev);
}

static bool btintel_pcie_wakeup(struct hci_dev *hdev)
{
	struct btintel_pcie_data *data = hci_get_drvdata(hdev);

	return device_may_wakeup(&data->pdev->dev);
}

static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
{
	int err;
@@ -2435,6 +2379,7 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
	hdev->set_diag = btintel_set_diag;
	hdev->set_bdaddr = btintel_set_bdaddr;
	hdev->reset = btintel_pcie_reset;
	hdev->wakeup = btintel_pcie_wakeup;

	err = hci_register_dev(hdev);
	if (err < 0) {
@@ -2573,11 +2518,100 @@ static void btintel_pcie_coredump(struct device *dev)
}
#endif

static int btintel_pcie_suspend_late(struct device *dev, pm_message_t mesg)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct btintel_pcie_data *data;
	ktime_t start;
	u32 dxstate;
	int err;

	data = pci_get_drvdata(pdev);

	dxstate = (mesg.event == PM_EVENT_SUSPEND ?
		   BTINTEL_PCIE_STATE_D3_HOT : BTINTEL_PCIE_STATE_D3_COLD);

	data->gp0_received = false;

	start = ktime_get();

	/* Refer: 6.4.11.7 -> Platform power management */
	btintel_pcie_wr_sleep_cntrl(data, dxstate);
	err = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
				 msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
	if (err == 0) {
		bt_dev_err(data->hdev,
			   "Timeout (%u ms) on alive interrupt for D3 entry",
			   BTINTEL_DEFAULT_INTR_TIMEOUT_MS);
		return -EBUSY;
	}

	bt_dev_dbg(data->hdev,
		   "device entered into d3 state from d0 in %lld us",
		   ktime_to_us(ktime_get() - start));

	return 0;
}

static int btintel_pcie_suspend(struct device *dev)
{
	return btintel_pcie_suspend_late(dev, PMSG_SUSPEND);
}

static int btintel_pcie_hibernate(struct device *dev)
{
	return btintel_pcie_suspend_late(dev, PMSG_HIBERNATE);
}

static int btintel_pcie_freeze(struct device *dev)
{
	return btintel_pcie_suspend_late(dev, PMSG_FREEZE);
}

static int btintel_pcie_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct btintel_pcie_data *data;
	ktime_t start;
	int err;

	data = pci_get_drvdata(pdev);
	data->gp0_received = false;

	start = ktime_get();

	/* Refer: 6.4.11.7 -> Platform power management */
	btintel_pcie_wr_sleep_cntrl(data, BTINTEL_PCIE_STATE_D0);
	err = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
				 msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
	if (err == 0) {
		bt_dev_err(data->hdev,
			   "Timeout (%u ms) on alive interrupt for D0 entry",
			   BTINTEL_DEFAULT_INTR_TIMEOUT_MS);
		return -EBUSY;
	}

	bt_dev_dbg(data->hdev,
		    "device entered into d0 state from d3 in %lld us",
		     ktime_to_us(ktime_get() - start));
	return 0;
}

static const struct dev_pm_ops btintel_pcie_pm_ops = {
	.suspend = btintel_pcie_suspend,
	.resume = btintel_pcie_resume,
	.freeze = btintel_pcie_freeze,
	.thaw = btintel_pcie_resume,
	.poweroff = btintel_pcie_hibernate,
	.restore = btintel_pcie_resume,
};

static struct pci_driver btintel_pcie_driver = {
	.name = KBUILD_MODNAME,
	.id_table = btintel_pcie_table,
	.probe = btintel_pcie_probe,
	.remove = btintel_pcie_remove,
	.driver.pm = pm_sleep_ptr(&btintel_pcie_pm_ops),
#ifdef CONFIG_DEV_COREDUMP
	.driver.coredump = btintel_pcie_coredump
#endif
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,8 @@ enum btintel_pcie_tlv_type {
	BTINTEL_CNVI_TOP,
	BTINTEL_DUMP_TIME,
	BTINTEL_FW_BUILD,
	BTINTEL_VENDOR,
	BTINTEL_DRIVER
};

/* causes for the MBOX interrupts */
Loading