Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b00a905f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: add support for PCIe D3hot in system suspend"

parents d32a2358 e3309bf4
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -1665,6 +1665,42 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
	return wil_ps_update(wil, ps_profile);
}

static int wil_cfg80211_suspend(struct wiphy *wiphy,
				struct cfg80211_wowlan *wow)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	int rc;

	/* Setting the wakeup trigger based on wow is TBD */

	if (test_bit(wil_status_suspended, wil->status)) {
		wil_dbg_pm(wil, "trying to suspend while suspended\n");
		return 0;
	}

	rc = wil_can_suspend(wil, false);
	if (rc)
		goto out;

	wil_dbg_pm(wil, "suspending\n");

	wil_p2p_stop_discovery(wil);

	wil_abort_scan(wil, true);

out:
	return rc;
}

static int wil_cfg80211_resume(struct wiphy *wiphy)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);

	wil_dbg_pm(wil, "resuming\n");

	return 0;
}

static struct cfg80211_ops wil_cfg80211_ops = {
	.add_virtual_intf = wil_cfg80211_add_iface,
	.del_virtual_intf = wil_cfg80211_del_iface,
@@ -1696,6 +1732,8 @@ static struct cfg80211_ops wil_cfg80211_ops = {
	.start_p2p_device = wil_cfg80211_start_p2p_device,
	.stop_p2p_device = wil_cfg80211_stop_p2p_device,
	.set_power_mgmt = wil_cfg80211_set_power_mgmt,
	.suspend = wil_cfg80211_suspend,
	.resume = wil_cfg80211_resume,
};

static void wil_wiphy_init(struct wiphy *wiphy)
+49 −0
Original line number Diff line number Diff line
@@ -509,6 +509,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
	void *buf;
	size_t ret;

	if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
	    test_bit(wil_status_suspended, wil_blob->wil->status))
		return 0;

	if (pos < 0)
		return -EINVAL;

@@ -1604,6 +1608,49 @@ static const struct file_operations fops_fw_version = {
	.llseek		= seq_lseek,
};

/*---------suspend_stats---------*/
static ssize_t wil_write_suspend_stats(struct file *file,
				       const char __user *buf,
				       size_t len, loff_t *ppos)
{
	struct wil6210_priv *wil = file->private_data;

	memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));

	return len;
}

static ssize_t wil_read_suspend_stats(struct file *file,
				      char __user *user_buf,
				      size_t count, loff_t *ppos)
{
	struct wil6210_priv *wil = file->private_data;
	static char text[400];
	int n;

	n = snprintf(text, sizeof(text),
		     "Suspend statistics:\n"
		     "successful suspends:%ld failed suspends:%ld\n"
		     "successful resumes:%ld failed resumes:%ld\n"
		     "rejected by host:%ld rejected by device:%ld\n",
		     wil->suspend_stats.successful_suspends,
		     wil->suspend_stats.failed_suspends,
		     wil->suspend_stats.successful_resumes,
		     wil->suspend_stats.failed_resumes,
		     wil->suspend_stats.rejected_by_host,
		     wil->suspend_stats.rejected_by_device);

	n = min_t(int, n, sizeof(text));

	return simple_read_from_buffer(user_buf, count, ppos, text, n);
}

static const struct file_operations fops_suspend_stats = {
	.read = wil_read_suspend_stats,
	.write = wil_write_suspend_stats,
	.open  = simple_open,
};

/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
				       struct dentry *dbg)
@@ -1656,6 +1703,7 @@ static const struct {
	{"led_blink_time",	0644,	&fops_led_blink_time},
	{"fw_capabilities",	0444,	&fops_fw_capabilities},
	{"fw_version",	0444,		&fops_fw_version},
	{"suspend_stats",	0644,	&fops_suspend_stats},
};

static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1702,6 +1750,7 @@ static const struct dbg_off dbg_wil_off[] = {
	WIL_FIELD(discovery_mode, 0644,	doff_u8),
	WIL_FIELD(chip_revision, 0444,	doff_u8),
	WIL_FIELD(abft_len, 0644,		doff_u8),
	WIL_FIELD(wakeup_trigger, 0644,		doff_u8),
	{},
};

+6 −0
Original line number Diff line number Diff line
@@ -467,6 +467,12 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)

	wil6210_unmask_irq_pseudo(wil);

	if (wil->suspend_resp_rcvd) {
		wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
		wil->suspend_resp_comp = true;
		wake_up_interruptible(&wil->wq);
	}

	return IRQ_HANDLED;
}

+6 −1
Original line number Diff line number Diff line
@@ -579,6 +579,9 @@ int wil_priv_init(struct wil6210_priv *wil)

	wil->ps_profile =  WMI_PS_PROFILE_TYPE_DEFAULT;

	wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
			      WMI_WAKEUP_TRIGGER_BCAST;

	return 0;

out_wmi_wq:
@@ -589,9 +592,11 @@ int wil_priv_init(struct wil6210_priv *wil)

void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
{
	if (wil->platform_ops.bus_request)
	if (wil->platform_ops.bus_request) {
		wil->bus_request_kbps = kbps;
		wil->platform_ops.bus_request(wil->platform_handle, kbps);
	}
}

/**
 * wil6210_disconnect - disconnect one connection
+34 −16
Original line number Diff line number Diff line
@@ -112,8 +112,6 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)

	wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only);

	pdev->msi_enabled = 0;

	pci_set_master(pdev);

	wil_dbg_misc(wil, "Setup %s interrupt\n", use_msi ? "MSI" : "INTx");
@@ -249,7 +247,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	}

	rc = pci_enable_device(pdev);
	if (rc) {
	if (rc && pdev->msi_enabled == 0) {
		wil_err(wil,
			"pci_enable_device failed, retry with MSI only\n");
		/* Work around for platforms that can't allocate IRQ:
@@ -264,6 +262,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
		goto err_plat;
	}
	/* rollback to err_disable_pdev */
	pci_set_power_state(pdev, PCI_D0);

	rc = pci_request_region(pdev, 0, WIL_NAME);
	if (rc) {
@@ -284,6 +283,15 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	wil_set_capabilities(wil);
	wil6210_clear_irq(wil);

	wil->keep_radio_on_during_sleep =
		wil->platform_ops.keep_radio_on_during_sleep &&
		wil->platform_ops.keep_radio_on_during_sleep(
			wil->platform_handle) &&
		test_bit(WMI_FW_CAPABILITY_D3_SUSPEND, wil->fw_capabilities);

	wil_info(wil, "keep_radio_on_during_sleep (%d)\n",
		 wil->keep_radio_on_during_sleep);

	/* FW should raise IRQ when ready */
	rc = wil_if_pcie_enable(wil);
	if (rc) {
@@ -383,15 +391,16 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
		goto out;

	rc = wil_suspend(wil, is_runtime);
	if (rc)
		goto out;

	/* TODO: how do I bring card in low power state? */
	if (!rc) {
		wil->suspend_stats.successful_suspends++;

		/* If platform device supports keep_radio_on_during_sleep
		 * it will control PCIe master
		 */
		if (!wil->keep_radio_on_during_sleep)
			/* disable bus mastering */
			pci_clear_master(pdev);
	/* PCI will call pci_save_state(pdev) and pci_prepare_to_sleep(pdev) */

	}
out:
	return rc;
}
@@ -404,12 +413,21 @@ static int wil6210_resume(struct device *dev, bool is_runtime)

	wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");

	/* If platform device supports keep_radio_on_during_sleep it will
	 * control PCIe master
	 */
	if (!wil->keep_radio_on_during_sleep)
		/* allow master */
		pci_set_master(pdev);

	rc = wil_resume(wil, is_runtime);
	if (rc)
	if (rc) {
		wil_err(wil, "device failed to resume (%d)\n", rc);
		wil->suspend_stats.failed_resumes++;
		if (!wil->keep_radio_on_during_sleep)
			pci_clear_master(pdev);
	} else {
		wil->suspend_stats.successful_resumes++;
	}

	return rc;
}
Loading