drivers/net/wireless/ath/ath9k/wow.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath9k/wow.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath9k/wow.c
Extension
.c
Size
9194 bytes
Lines
349
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
			ath_dbg(common, WOW,
				"Multi-channel WOW is not supported\n");
			ret = 1;
			goto fail_wow;
		}
	}

	if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
		ath_dbg(common, WOW, "None of the STA vifs are associated\n");
		ret = 1;
		goto fail_wow;
	}

	triggers = ath9k_wow_map_triggers(sc, wowlan);
	if (!triggers) {
		ath_dbg(common, WOW, "No valid WoW triggers\n");
		ret = 1;
		goto fail_wow;
	}

	ath_cancel_work(sc);
	ath_stop_ani(sc);

	ath9k_ps_wakeup(sc);

	ath9k_stop_btcoex(sc);

	/*
	 * Enable wake up on receiving disassoc/deauth
	 * frame by default.
	 */
	ret = ath9k_wow_add_disassoc_deauth_pattern(sc);
	if (ret) {
		ath_err(common,
			"Unable to add disassoc/deauth pattern: %d\n", ret);
		goto fail_wow;
	}

	if (triggers & AH_WOW_USER_PATTERN_EN) {
		ret = ath9k_wow_add_pattern(sc, wowlan);
		if (ret) {
			ath_err(common,
				"Unable to add user pattern: %d\n", ret);
			goto fail_wow;
		}
	}

	spin_lock_bh(&sc->sc_pcu_lock);
	/*
	 * To avoid false wake, we enable beacon miss interrupt only
	 * when we go to sleep. We save the current interrupt mask
	 * so we can restore it after the system wakes up
	 */
	sc->wow_intr_before_sleep = ah->imask;
	ah->imask &= ~ATH9K_INT_GLOBAL;
	ath9k_hw_disable_interrupts(ah);
	ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;
	ath9k_hw_set_interrupts(ah);
	ath9k_hw_enable_interrupts(ah);

	spin_unlock_bh(&sc->sc_pcu_lock);

	/*
	 * we can now sync irq and kill any running tasklets, since we already
	 * disabled interrupts and not holding a spin lock
	 */
	synchronize_irq(sc->irq);
	tasklet_kill(&sc->intr_tq);

	ath9k_hw_wow_enable(ah, triggers);

	ath9k_ps_restore(sc);
	ath_dbg(common, WOW, "Suspend with WoW triggers: 0x%x\n", triggers);

	set_bit(ATH_OP_WOW_ENABLED, &common->op_flags);
fail_wow:
	mutex_unlock(&sc->mutex);
	return ret;
}

int ath9k_resume(struct ieee80211_hw *hw)
{
	struct ath_softc *sc = hw->priv;
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
	u8 status;

	mutex_lock(&sc->mutex);

Annotation

Implementation Notes