Ejemplo n.º 1
0
Archivo: pm.c Proyecto: avagin/linux
static int wil_suspend_radio_off(struct wil6210_priv *wil)
{
	int rc = 0;
	bool active_ifaces;

	wil_dbg_pm(wil, "suspend radio off\n");

	rc = down_write_trylock(&wil->mem_lock);
	if (!rc) {
		wil_err(wil,
			"device is busy. down_write_trylock failed, returned (0x%x)\n",
			rc);
		wil->suspend_stats.rejected_by_host++;
		return -EBUSY;
	}

	set_bit(wil_status_suspending, wil->status);
	up_write(&wil->mem_lock);

	/* if netif up, hardware is alive, shut it down */
	mutex_lock(&wil->vif_mutex);
	active_ifaces = wil_has_active_ifaces(wil, true, false);
	mutex_unlock(&wil->vif_mutex);

	if (active_ifaces) {
		rc = wil_down(wil);
		if (rc) {
			wil_err(wil, "wil_down : %d\n", rc);
			wil->suspend_stats.r_off.failed_suspends++;
			goto out;
		}
	}

	/* Disable PCIe IRQ to prevent sporadic IRQs when PCIe is suspending */
	wil_dbg_pm(wil, "Disabling PCIe IRQ before suspending\n");
	wil_disable_irq(wil);

	if (wil->platform_ops.suspend) {
		rc = wil->platform_ops.suspend(wil->platform_handle, false);
		if (rc) {
			wil_enable_irq(wil);
			wil->suspend_stats.r_off.failed_suspends++;
			goto out;
		}
	}

	set_bit(wil_status_suspended, wil->status);

out:
	clear_bit(wil_status_suspending, wil->status);
	wil_dbg_pm(wil, "suspend radio off: %d\n", rc);

	return rc;
}
Ejemplo n.º 2
0
Archivo: pm.c Proyecto: krzk/linux
static int wil_suspend_radio_off(struct wil6210_priv *wil)
{
	int rc = 0;
	bool active_ifaces;

	wil_dbg_pm(wil, "suspend radio off\n");

	set_bit(wil_status_suspending, wil->status);
	if (test_bit(wil_status_collecting_dumps, wil->status)) {
		/* Device collects crash dump, cancel the suspend */
		wil_dbg_pm(wil, "reject suspend while collecting crash dump\n");
		clear_bit(wil_status_suspending, wil->status);
		wil->suspend_stats.rejected_by_host++;
		return -EBUSY;
	}

	/* if netif up, hardware is alive, shut it down */
	mutex_lock(&wil->vif_mutex);
	active_ifaces = wil_has_active_ifaces(wil, true, false);
	mutex_unlock(&wil->vif_mutex);

	if (active_ifaces) {
		rc = wil_down(wil);
		if (rc) {
			wil_err(wil, "wil_down : %d\n", rc);
			wil->suspend_stats.r_off.failed_suspends++;
			goto out;
		}
	}

	/* Disable PCIe IRQ to prevent sporadic IRQs when PCIe is suspending */
	wil_dbg_pm(wil, "Disabling PCIe IRQ before suspending\n");
	wil_disable_irq(wil);

	if (wil->platform_ops.suspend) {
		rc = wil->platform_ops.suspend(wil->platform_handle, false);
		if (rc) {
			wil_enable_irq(wil);
			wil->suspend_stats.r_off.failed_suspends++;
			goto out;
		}
	}

	set_bit(wil_status_suspended, wil->status);

out:
	clear_bit(wil_status_suspending, wil->status);
	wil_dbg_pm(wil, "suspend radio off: %d\n", rc);

	return rc;
}
Ejemplo n.º 3
0
Archivo: pm.c Proyecto: avagin/linux
static int wil_resume_radio_off(struct wil6210_priv *wil)
{
	int rc = 0;
	bool active_ifaces;

	wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
	wil_enable_irq(wil);
	/* if any netif up, bring hardware up
	 * During open(), IFF_UP set after actual device method
	 * invocation. This prevent recursive call to wil_up()
	 * wil_status_suspended will be cleared in wil_reset
	 */
	mutex_lock(&wil->vif_mutex);
	active_ifaces = wil_has_active_ifaces(wil, true, false);
	mutex_unlock(&wil->vif_mutex);
	if (active_ifaces)
		rc = wil_up(wil);
	else
		clear_bit(wil_status_suspended, wil->status);

	return rc;
}
Ejemplo n.º 4
0
Archivo: pm.c Proyecto: avagin/linux
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
{
	int rc = 0, i;
	bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY,
				 wil->fw_capabilities);
	bool active_ifaces;

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

	if (wmi_only || debug_fw) {
		wil_dbg_pm(wil, "Deny any suspend - %s mode\n",
			   wmi_only ? "wmi_only" : "debug_fw");
		rc = -EBUSY;
		goto out;
	}
	if (is_runtime && !wil->platform_ops.suspend) {
		rc = -EBUSY;
		goto out;
	}

	mutex_lock(&wil->vif_mutex);
	active_ifaces = wil_has_active_ifaces(wil, true, false);
	mutex_unlock(&wil->vif_mutex);

	if (!active_ifaces) {
		/* can always sleep when down */
		wil_dbg_pm(wil, "Interface is down\n");
		goto out;
	}
	if (test_bit(wil_status_resetting, wil->status)) {
		wil_dbg_pm(wil, "Delay suspend when resetting\n");
		rc = -EBUSY;
		goto out;
	}
	if (wil->recovery_state != fw_recovery_idle) {
		wil_dbg_pm(wil, "Delay suspend during recovery\n");
		rc = -EBUSY;
		goto out;
	}

	/* interface is running */
	mutex_lock(&wil->vif_mutex);
	for (i = 0; i < GET_MAX_VIFS(wil); i++) {
		struct wil6210_vif *vif = wil->vifs[i];

		if (!vif)
			continue;
		if (!wil_can_suspend_vif(wil, vif, is_runtime)) {
			rc = -EBUSY;
			mutex_unlock(&wil->vif_mutex);
			goto out;
		}
	}
	mutex_unlock(&wil->vif_mutex);

out:
	wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n",
		   is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);

	if (rc)
		wil->suspend_stats.rejected_by_host++;

	return rc;
}