1e60001e7SSujith Manoharan /* 2e60001e7SSujith Manoharan * Copyright (c) 2013 Qualcomm Atheros, Inc. 3e60001e7SSujith Manoharan * 4e60001e7SSujith Manoharan * Permission to use, copy, modify, and/or distribute this software for any 5e60001e7SSujith Manoharan * purpose with or without fee is hereby granted, provided that the above 6e60001e7SSujith Manoharan * copyright notice and this permission notice appear in all copies. 7e60001e7SSujith Manoharan * 8e60001e7SSujith Manoharan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9e60001e7SSujith Manoharan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10e60001e7SSujith Manoharan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11e60001e7SSujith Manoharan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12e60001e7SSujith Manoharan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13e60001e7SSujith Manoharan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14e60001e7SSujith Manoharan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15e60001e7SSujith Manoharan */ 16e60001e7SSujith Manoharan 17e60001e7SSujith Manoharan #include "ath9k.h" 18e60001e7SSujith Manoharan 19*e68e9c10SSujith Manoharan static const struct wiphy_wowlan_support ath9k_wowlan_support_legacy = { 20babaa80aSSujith Manoharan .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, 21babaa80aSSujith Manoharan .n_patterns = MAX_NUM_USER_PATTERN, 22babaa80aSSujith Manoharan .pattern_min_len = 1, 23babaa80aSSujith Manoharan .pattern_max_len = MAX_PATTERN_SIZE, 24babaa80aSSujith Manoharan }; 25babaa80aSSujith Manoharan 26*e68e9c10SSujith Manoharan static const struct wiphy_wowlan_support ath9k_wowlan_support = { 27*e68e9c10SSujith Manoharan .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, 28*e68e9c10SSujith Manoharan .n_patterns = MAX_NUM_PATTERN - 2, 29*e68e9c10SSujith Manoharan .pattern_min_len = 1, 30*e68e9c10SSujith Manoharan .pattern_max_len = MAX_PATTERN_SIZE, 31*e68e9c10SSujith Manoharan }; 32*e68e9c10SSujith Manoharan 33249943a2SSujith Manoharan static u8 ath9k_wow_map_triggers(struct ath_softc *sc, 34249943a2SSujith Manoharan struct cfg80211_wowlan *wowlan) 35e60001e7SSujith Manoharan { 36249943a2SSujith Manoharan u8 wow_triggers = 0; 37249943a2SSujith Manoharan 38e60001e7SSujith Manoharan if (wowlan->disconnect) 39249943a2SSujith Manoharan wow_triggers |= AH_WOW_LINK_CHANGE | 40e60001e7SSujith Manoharan AH_WOW_BEACON_MISS; 41e60001e7SSujith Manoharan if (wowlan->magic_pkt) 42249943a2SSujith Manoharan wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; 43e60001e7SSujith Manoharan 44e60001e7SSujith Manoharan if (wowlan->n_patterns) 45249943a2SSujith Manoharan wow_triggers |= AH_WOW_USER_PATTERN_EN; 46e60001e7SSujith Manoharan 47249943a2SSujith Manoharan return wow_triggers; 48e60001e7SSujith Manoharan } 49e60001e7SSujith Manoharan 506af75e4dSSujith Manoharan static int ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) 51e60001e7SSujith Manoharan { 52e60001e7SSujith Manoharan struct ath_hw *ah = sc->sc_ah; 53e60001e7SSujith Manoharan struct ath_common *common = ath9k_hw_common(ah); 54e60001e7SSujith Manoharan int pattern_count = 0; 556af75e4dSSujith Manoharan int ret, i, byte_cnt = 0; 56e60001e7SSujith Manoharan u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; 57e60001e7SSujith Manoharan u8 dis_deauth_mask[MAX_PATTERN_SIZE]; 58e60001e7SSujith Manoharan 59e60001e7SSujith Manoharan memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); 60e60001e7SSujith Manoharan memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); 61e60001e7SSujith Manoharan 62e60001e7SSujith Manoharan /* 63e60001e7SSujith Manoharan * Create Dissassociate / Deauthenticate packet filter 64e60001e7SSujith Manoharan * 65e60001e7SSujith Manoharan * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes 66e60001e7SSujith Manoharan * +--------------+----------+---------+--------+--------+---- 67e60001e7SSujith Manoharan * + Frame Control+ Duration + DA + SA + BSSID + 68e60001e7SSujith Manoharan * +--------------+----------+---------+--------+--------+---- 69e60001e7SSujith Manoharan * 70e60001e7SSujith Manoharan * The above is the management frame format for disassociate/ 71e60001e7SSujith Manoharan * deauthenticate pattern, from this we need to match the first byte 72e60001e7SSujith Manoharan * of 'Frame Control' and DA, SA, and BSSID fields 73e60001e7SSujith Manoharan * (skipping 2nd byte of FC and Duration feild. 74e60001e7SSujith Manoharan * 75e60001e7SSujith Manoharan * Disassociate pattern 76e60001e7SSujith Manoharan * -------------------- 77e60001e7SSujith Manoharan * Frame control = 00 00 1010 78e60001e7SSujith Manoharan * DA, SA, BSSID = x:x:x:x:x:x 79e60001e7SSujith Manoharan * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x 80e60001e7SSujith Manoharan * | x:x:x:x:x:x -- 22 bytes 81e60001e7SSujith Manoharan * 82e60001e7SSujith Manoharan * Deauthenticate pattern 83e60001e7SSujith Manoharan * ---------------------- 84e60001e7SSujith Manoharan * Frame control = 00 00 1100 85e60001e7SSujith Manoharan * DA, SA, BSSID = x:x:x:x:x:x 86e60001e7SSujith Manoharan * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x 87e60001e7SSujith Manoharan * | x:x:x:x:x:x -- 22 bytes 88e60001e7SSujith Manoharan */ 89e60001e7SSujith Manoharan 90e60001e7SSujith Manoharan /* Fill out the mask with all FF's */ 91e60001e7SSujith Manoharan for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) 92e60001e7SSujith Manoharan dis_deauth_mask[i] = 0xff; 93e60001e7SSujith Manoharan 94e60001e7SSujith Manoharan /* copy the first byte of frame control field */ 95e60001e7SSujith Manoharan dis_deauth_pattern[byte_cnt] = 0xa0; 96e60001e7SSujith Manoharan byte_cnt++; 97e60001e7SSujith Manoharan 98e60001e7SSujith Manoharan /* skip 2nd byte of frame control and Duration field */ 99e60001e7SSujith Manoharan byte_cnt += 3; 100e60001e7SSujith Manoharan 101e60001e7SSujith Manoharan /* 102e60001e7SSujith Manoharan * need not match the destination mac address, it can be a broadcast 103e60001e7SSujith Manoharan * mac address or an unicast to this station 104e60001e7SSujith Manoharan */ 105e60001e7SSujith Manoharan byte_cnt += 6; 106e60001e7SSujith Manoharan 107e60001e7SSujith Manoharan /* copy the source mac address */ 108e60001e7SSujith Manoharan memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); 109e60001e7SSujith Manoharan 110e60001e7SSujith Manoharan byte_cnt += 6; 111e60001e7SSujith Manoharan 112e60001e7SSujith Manoharan /* copy the bssid, its same as the source mac address */ 113e60001e7SSujith Manoharan memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); 114e60001e7SSujith Manoharan 115e60001e7SSujith Manoharan /* Create Disassociate pattern mask */ 116e60001e7SSujith Manoharan dis_deauth_mask[0] = 0xfe; 117e60001e7SSujith Manoharan dis_deauth_mask[1] = 0x03; 118e60001e7SSujith Manoharan dis_deauth_mask[2] = 0xc0; 119e60001e7SSujith Manoharan 1206af75e4dSSujith Manoharan ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, 121e60001e7SSujith Manoharan pattern_count, byte_cnt); 1226af75e4dSSujith Manoharan if (ret) 1236af75e4dSSujith Manoharan goto exit; 124e60001e7SSujith Manoharan 125e60001e7SSujith Manoharan pattern_count++; 126e60001e7SSujith Manoharan /* 127e60001e7SSujith Manoharan * for de-authenticate pattern, only the first byte of the frame 128e60001e7SSujith Manoharan * control field gets changed from 0xA0 to 0xC0 129e60001e7SSujith Manoharan */ 130e60001e7SSujith Manoharan dis_deauth_pattern[0] = 0xC0; 131e60001e7SSujith Manoharan 1326af75e4dSSujith Manoharan ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, 133e60001e7SSujith Manoharan pattern_count, byte_cnt); 1346af75e4dSSujith Manoharan exit: 1356af75e4dSSujith Manoharan return ret; 136e60001e7SSujith Manoharan } 137e60001e7SSujith Manoharan 1386af75e4dSSujith Manoharan static int ath9k_wow_add_pattern(struct ath_softc *sc, 139e60001e7SSujith Manoharan struct cfg80211_wowlan *wowlan) 140e60001e7SSujith Manoharan { 141e60001e7SSujith Manoharan struct ath_hw *ah = sc->sc_ah; 142e60001e7SSujith Manoharan struct cfg80211_pkt_pattern *patterns = wowlan->patterns; 14334d102c9SSujith Manoharan u8 wow_pattern[MAX_PATTERN_SIZE]; 14434d102c9SSujith Manoharan u8 wow_mask[MAX_PATTERN_SIZE]; 1456af75e4dSSujith Manoharan int mask_len, ret = 0; 146e60001e7SSujith Manoharan s8 i = 0; 147e60001e7SSujith Manoharan 148e60001e7SSujith Manoharan for (i = 0; i < wowlan->n_patterns; i++) { 14934d102c9SSujith Manoharan mask_len = DIV_ROUND_UP(patterns[i].pattern_len, 8); 15034d102c9SSujith Manoharan memset(wow_pattern, 0, MAX_PATTERN_SIZE); 15134d102c9SSujith Manoharan memset(wow_mask, 0, MAX_PATTERN_SIZE); 15234d102c9SSujith Manoharan memcpy(wow_pattern, patterns[i].pattern, patterns[i].pattern_len); 15334d102c9SSujith Manoharan memcpy(wow_mask, patterns[i].mask, mask_len); 154e60001e7SSujith Manoharan 1556af75e4dSSujith Manoharan ret = ath9k_hw_wow_apply_pattern(ah, 15634d102c9SSujith Manoharan wow_pattern, 15734d102c9SSujith Manoharan wow_mask, 158e60001e7SSujith Manoharan i + 2, 15934d102c9SSujith Manoharan patterns[i].pattern_len); 1606af75e4dSSujith Manoharan if (ret) 1616af75e4dSSujith Manoharan break; 162e60001e7SSujith Manoharan } 1636af75e4dSSujith Manoharan 1646af75e4dSSujith Manoharan return ret; 165e60001e7SSujith Manoharan } 166e60001e7SSujith Manoharan 167e60001e7SSujith Manoharan int ath9k_suspend(struct ieee80211_hw *hw, 168e60001e7SSujith Manoharan struct cfg80211_wowlan *wowlan) 169e60001e7SSujith Manoharan { 170e60001e7SSujith Manoharan struct ath_softc *sc = hw->priv; 171e60001e7SSujith Manoharan struct ath_hw *ah = sc->sc_ah; 172e60001e7SSujith Manoharan struct ath_common *common = ath9k_hw_common(ah); 173249943a2SSujith Manoharan u8 triggers; 174e60001e7SSujith Manoharan int ret = 0; 175e60001e7SSujith Manoharan 176ea22df29SSujith Manoharan ath9k_deinit_channel_context(sc); 177ea22df29SSujith Manoharan 178e60001e7SSujith Manoharan mutex_lock(&sc->mutex); 179e60001e7SSujith Manoharan 180eefa01ddSOleksij Rempel if (test_bit(ATH_OP_INVALID, &common->op_flags)) { 18113084c2dSSujith Manoharan ath_err(common, "Device not present\n"); 18213084c2dSSujith Manoharan ret = -ENODEV; 183e60001e7SSujith Manoharan goto fail_wow; 184e60001e7SSujith Manoharan } 185e60001e7SSujith Manoharan 186e60001e7SSujith Manoharan if (WARN_ON(!wowlan)) { 18713084c2dSSujith Manoharan ath_err(common, "None of the WoW triggers enabled\n"); 188e60001e7SSujith Manoharan ret = -EINVAL; 189e60001e7SSujith Manoharan goto fail_wow; 190e60001e7SSujith Manoharan } 191e60001e7SSujith Manoharan 192dc4b277dSSujith Manoharan if (sc->cur_chan->nvifs > 1) { 193dc4b277dSSujith Manoharan ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); 194dc4b277dSSujith Manoharan ret = 1; 195dc4b277dSSujith Manoharan goto fail_wow; 196dc4b277dSSujith Manoharan } 197e60001e7SSujith Manoharan 1981331f5a7SSujith Manoharan if (ath9k_is_chanctx_enabled()) { 1991331f5a7SSujith Manoharan if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) { 2001331f5a7SSujith Manoharan ath_dbg(common, WOW, 2011331f5a7SSujith Manoharan "Multi-channel WOW is not supported\n"); 2021331f5a7SSujith Manoharan ret = 1; 2031331f5a7SSujith Manoharan goto fail_wow; 2041331f5a7SSujith Manoharan } 2051331f5a7SSujith Manoharan } 2061331f5a7SSujith Manoharan 207eefa01ddSOleksij Rempel if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { 208e60001e7SSujith Manoharan ath_dbg(common, WOW, "None of the STA vifs are associated\n"); 209e60001e7SSujith Manoharan ret = 1; 210e60001e7SSujith Manoharan goto fail_wow; 211e60001e7SSujith Manoharan } 212e60001e7SSujith Manoharan 213249943a2SSujith Manoharan triggers = ath9k_wow_map_triggers(sc, wowlan); 214249943a2SSujith Manoharan if (!triggers) { 215249943a2SSujith Manoharan ath_dbg(common, WOW, "No valid WoW triggers\n"); 216249943a2SSujith Manoharan ret = 1; 217249943a2SSujith Manoharan goto fail_wow; 218249943a2SSujith Manoharan } 219249943a2SSujith Manoharan 220dc4b277dSSujith Manoharan ath_cancel_work(sc); 221dc4b277dSSujith Manoharan ath_stop_ani(sc); 222e60001e7SSujith Manoharan 223e60001e7SSujith Manoharan ath9k_ps_wakeup(sc); 224e60001e7SSujith Manoharan 225e60001e7SSujith Manoharan ath9k_stop_btcoex(sc); 226e60001e7SSujith Manoharan 227e60001e7SSujith Manoharan /* 228e60001e7SSujith Manoharan * Enable wake up on recieving disassoc/deauth 229e60001e7SSujith Manoharan * frame by default. 230e60001e7SSujith Manoharan */ 2316af75e4dSSujith Manoharan ret = ath9k_wow_add_disassoc_deauth_pattern(sc); 2326af75e4dSSujith Manoharan if (ret) { 2336af75e4dSSujith Manoharan ath_err(common, 2346af75e4dSSujith Manoharan "Unable to add disassoc/deauth pattern: %d\n", ret); 2356af75e4dSSujith Manoharan goto fail_wow; 2366af75e4dSSujith Manoharan } 237e60001e7SSujith Manoharan 2386af75e4dSSujith Manoharan if (triggers & AH_WOW_USER_PATTERN_EN) { 2396af75e4dSSujith Manoharan ret = ath9k_wow_add_pattern(sc, wowlan); 2406af75e4dSSujith Manoharan if (ret) { 2416af75e4dSSujith Manoharan ath_err(common, 2426af75e4dSSujith Manoharan "Unable to add user pattern: %d\n", ret); 2436af75e4dSSujith Manoharan goto fail_wow; 2446af75e4dSSujith Manoharan } 2456af75e4dSSujith Manoharan } 246e60001e7SSujith Manoharan 247e60001e7SSujith Manoharan spin_lock_bh(&sc->sc_pcu_lock); 248e60001e7SSujith Manoharan /* 249e60001e7SSujith Manoharan * To avoid false wake, we enable beacon miss interrupt only 250e60001e7SSujith Manoharan * when we go to sleep. We save the current interrupt mask 251e60001e7SSujith Manoharan * so we can restore it after the system wakes up 252e60001e7SSujith Manoharan */ 253e60001e7SSujith Manoharan sc->wow_intr_before_sleep = ah->imask; 254e60001e7SSujith Manoharan ah->imask &= ~ATH9K_INT_GLOBAL; 255e60001e7SSujith Manoharan ath9k_hw_disable_interrupts(ah); 256e60001e7SSujith Manoharan ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; 257e60001e7SSujith Manoharan ath9k_hw_set_interrupts(ah); 258e60001e7SSujith Manoharan ath9k_hw_enable_interrupts(ah); 259e60001e7SSujith Manoharan 260e60001e7SSujith Manoharan spin_unlock_bh(&sc->sc_pcu_lock); 261e60001e7SSujith Manoharan 262e60001e7SSujith Manoharan /* 263e60001e7SSujith Manoharan * we can now sync irq and kill any running tasklets, since we already 264e60001e7SSujith Manoharan * disabled interrupts and not holding a spin lock 265e60001e7SSujith Manoharan */ 266e60001e7SSujith Manoharan synchronize_irq(sc->irq); 267e60001e7SSujith Manoharan tasklet_kill(&sc->intr_tq); 268e60001e7SSujith Manoharan 269249943a2SSujith Manoharan ath9k_hw_wow_enable(ah, triggers); 270e60001e7SSujith Manoharan 271e60001e7SSujith Manoharan ath9k_ps_restore(sc); 272249943a2SSujith Manoharan ath_dbg(common, WOW, "Suspend with WoW triggers: 0x%x\n", triggers); 273e60001e7SSujith Manoharan 274249943a2SSujith Manoharan set_bit(ATH_OP_WOW_ENABLED, &common->op_flags); 275e60001e7SSujith Manoharan fail_wow: 276e60001e7SSujith Manoharan mutex_unlock(&sc->mutex); 277e60001e7SSujith Manoharan return ret; 278e60001e7SSujith Manoharan } 279e60001e7SSujith Manoharan 280e60001e7SSujith Manoharan int ath9k_resume(struct ieee80211_hw *hw) 281e60001e7SSujith Manoharan { 282e60001e7SSujith Manoharan struct ath_softc *sc = hw->priv; 283e60001e7SSujith Manoharan struct ath_hw *ah = sc->sc_ah; 284e60001e7SSujith Manoharan struct ath_common *common = ath9k_hw_common(ah); 285e094c337SSujith Manoharan u8 status; 286e60001e7SSujith Manoharan 287e60001e7SSujith Manoharan mutex_lock(&sc->mutex); 288e60001e7SSujith Manoharan 289e60001e7SSujith Manoharan ath9k_ps_wakeup(sc); 290e60001e7SSujith Manoharan 291e60001e7SSujith Manoharan spin_lock_bh(&sc->sc_pcu_lock); 292e60001e7SSujith Manoharan 293e60001e7SSujith Manoharan ath9k_hw_disable_interrupts(ah); 294e60001e7SSujith Manoharan ah->imask = sc->wow_intr_before_sleep; 295e60001e7SSujith Manoharan ath9k_hw_set_interrupts(ah); 296e60001e7SSujith Manoharan ath9k_hw_enable_interrupts(ah); 297e60001e7SSujith Manoharan 298e60001e7SSujith Manoharan spin_unlock_bh(&sc->sc_pcu_lock); 299e60001e7SSujith Manoharan 300e094c337SSujith Manoharan status = ath9k_hw_wow_wakeup(ah); 301e094c337SSujith Manoharan ath_dbg(common, WOW, "Resume with WoW status: 0x%x\n", status); 302e60001e7SSujith Manoharan 303e60001e7SSujith Manoharan ath_restart_work(sc); 304e60001e7SSujith Manoharan ath9k_start_btcoex(sc); 305e60001e7SSujith Manoharan 306249943a2SSujith Manoharan clear_bit(ATH_OP_WOW_ENABLED, &common->op_flags); 307249943a2SSujith Manoharan 308e60001e7SSujith Manoharan ath9k_ps_restore(sc); 309e60001e7SSujith Manoharan mutex_unlock(&sc->mutex); 310e60001e7SSujith Manoharan 311e60001e7SSujith Manoharan return 0; 312e60001e7SSujith Manoharan } 313e60001e7SSujith Manoharan 314e60001e7SSujith Manoharan void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) 315e60001e7SSujith Manoharan { 316e60001e7SSujith Manoharan struct ath_softc *sc = hw->priv; 317661d2581SSujith Manoharan struct ath_common *common = ath9k_hw_common(sc->sc_ah); 318e60001e7SSujith Manoharan 319e60001e7SSujith Manoharan mutex_lock(&sc->mutex); 320e60001e7SSujith Manoharan device_set_wakeup_enable(sc->dev, enabled); 321e60001e7SSujith Manoharan mutex_unlock(&sc->mutex); 322661d2581SSujith Manoharan 323661d2581SSujith Manoharan ath_dbg(common, WOW, "WoW wakeup source is %s\n", 324661d2581SSujith Manoharan (enabled) ? "enabled" : "disabled"); 325e60001e7SSujith Manoharan } 326babaa80aSSujith Manoharan 327babaa80aSSujith Manoharan void ath9k_init_wow(struct ieee80211_hw *hw) 328babaa80aSSujith Manoharan { 329babaa80aSSujith Manoharan struct ath_softc *sc = hw->priv; 330*e68e9c10SSujith Manoharan struct ath_hw *ah = sc->sc_ah; 331babaa80aSSujith Manoharan 3328b861715SSujith Manoharan if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) { 333*e68e9c10SSujith Manoharan if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah)) 334babaa80aSSujith Manoharan hw->wiphy->wowlan = &ath9k_wowlan_support; 335*e68e9c10SSujith Manoharan else 336*e68e9c10SSujith Manoharan hw->wiphy->wowlan = &ath9k_wowlan_support_legacy; 337*e68e9c10SSujith Manoharan 338661d2581SSujith Manoharan device_init_wakeup(sc->dev, 1); 339661d2581SSujith Manoharan } 340661d2581SSujith Manoharan } 341661d2581SSujith Manoharan 342661d2581SSujith Manoharan void ath9k_deinit_wow(struct ieee80211_hw *hw) 343661d2581SSujith Manoharan { 344661d2581SSujith Manoharan struct ath_softc *sc = hw->priv; 345661d2581SSujith Manoharan 3468b861715SSujith Manoharan if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) 347661d2581SSujith Manoharan device_init_wakeup(sc->dev, 0); 348babaa80aSSujith Manoharan } 349