aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-15 16:23:45 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-07-21 10:31:31 -0400
commitc8ac61cf6e53fefb3b439fc58390fb65d2730e63 (patch)
tree2896810ca3ccb2bd221d4b0b2d488bd0e7c55955 /drivers/net
parent5a3d9882b84edf5fa8e8ca33a5d6df25e2e727a5 (diff)
iwlagn: implement WoWLAN
Implement WoWLAN support in iwlagn. The device supports a number of wakeup triggers and can do GTK rekeying when asleep (if HW crypto is used). Unfortunately, we need to disconnect from the AP after resume since we can't yet get all the info out of the wowlan uCode to stay connected safely. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c517
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h128
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c6
11 files changed, 705 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index e77f91380a4a..3bee0f119bcd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -400,6 +400,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
400 struct iwl_tx_queue *txq = &priv->txq[txq_id]; 400 struct iwl_tx_queue *txq = &priv->txq[txq_id];
401 struct ieee80211_tx_info *info; 401 struct ieee80211_tx_info *info;
402 struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; 402 struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
403 struct ieee80211_hdr *hdr;
403 struct iwl_tx_info *txb; 404 struct iwl_tx_info *txb;
404 u32 status = le16_to_cpu(tx_resp->status.status); 405 u32 status = le16_to_cpu(tx_resp->status.status);
405 int tid; 406 int tid;
@@ -426,6 +427,11 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
426 IWLAGN_TX_RES_RA_POS; 427 IWLAGN_TX_RES_RA_POS;
427 428
428 spin_lock_irqsave(&priv->sta_lock, flags); 429 spin_lock_irqsave(&priv->sta_lock, flags);
430
431 hdr = (void *)txb->skb->data;
432 if (!ieee80211_is_data_qos(hdr->frame_control))
433 priv->last_seq_ctl = tx_resp->seq_ctl;
434
429 if (txq->sched_retry) { 435 if (txq->sched_retry) {
430 const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); 436 const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
431 struct iwl_ht_agg *agg; 437 struct iwl_ht_agg *agg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 71487487d603..d78a4659dbff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -855,6 +855,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
855 iwl_wake_any_queue(priv, ctx); 855 iwl_wake_any_queue(priv, ctx);
856 } 856 }
857 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; 857 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
858
859 if (ctx->ctxid == IWL_RXON_CTX_BSS)
860 priv->have_rekey_data = false;
858 } 861 }
859 862
860 iwlagn_bt_coex_rssi_monitor(priv); 863 iwlagn_bt_coex_rssi_monitor(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 946d3a16e494..a895a099d086 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -513,14 +513,21 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
513 return -EIO; 513 return -EIO;
514 } 514 }
515 515
516 ret = iwl_verify_ucode(priv, image); 516 /*
517 if (ret) { 517 * This step takes a long time (60-80ms!!) and
518 priv->ucode_type = old_type; 518 * WoWLAN image should be loaded quickly, so
519 return ret; 519 * skip it for WoWLAN.
520 } 520 */
521 if (ucode_type != IWL_UCODE_WOWLAN) {
522 ret = iwl_verify_ucode(priv, image);
523 if (ret) {
524 priv->ucode_type = old_type;
525 return ret;
526 }
521 527
522 /* delay a bit to give rfkill time to run */ 528 /* delay a bit to give rfkill time to run */
523 msleep(5); 529 msleep(5);
530 }
524 531
525 ret = iwlagn_alive_notify(priv); 532 ret = iwlagn_alive_notify(priv);
526 if (ret) { 533 if (ret) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 0bab19563394..299acb491f0d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -593,6 +593,7 @@ static void iwl_dealloc_ucode(struct iwl_priv *priv)
593{ 593{
594 iwl_free_fw_img(priv, &priv->ucode_rt); 594 iwl_free_fw_img(priv, &priv->ucode_rt);
595 iwl_free_fw_img(priv, &priv->ucode_init); 595 iwl_free_fw_img(priv, &priv->ucode_init);
596 iwl_free_fw_img(priv, &priv->ucode_wowlan);
596} 597}
597 598
598static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, 599static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
@@ -662,8 +663,9 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
662} 663}
663 664
664struct iwlagn_firmware_pieces { 665struct iwlagn_firmware_pieces {
665 const void *inst, *data, *init, *init_data; 666 const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
666 size_t inst_size, data_size, init_size, init_data_size; 667 size_t inst_size, data_size, init_size, init_data_size,
668 wowlan_inst_size, wowlan_data_size;
667 669
668 u32 build; 670 u32 build;
669 671
@@ -902,6 +904,14 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
902 goto invalid_tlv_len; 904 goto invalid_tlv_len;
903 priv->enhance_sensitivity_table = true; 905 priv->enhance_sensitivity_table = true;
904 break; 906 break;
907 case IWL_UCODE_TLV_WOWLAN_INST:
908 pieces->wowlan_inst = tlv_data;
909 pieces->wowlan_inst_size = tlv_len;
910 break;
911 case IWL_UCODE_TLV_WOWLAN_DATA:
912 pieces->wowlan_data = tlv_data;
913 pieces->wowlan_data_size = tlv_len;
914 break;
905 case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: 915 case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
906 if (tlv_len != sizeof(u32)) 916 if (tlv_len != sizeof(u32))
907 goto invalid_tlv_len; 917 goto invalid_tlv_len;
@@ -1096,6 +1106,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1096 goto err_pci_alloc; 1106 goto err_pci_alloc;
1097 } 1107 }
1098 1108
1109 /* WoWLAN instructions and data */
1110 if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
1111 if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.code,
1112 pieces.wowlan_inst,
1113 pieces.wowlan_inst_size))
1114 goto err_pci_alloc;
1115 if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.data,
1116 pieces.wowlan_data,
1117 pieces.wowlan_data_size))
1118 goto err_pci_alloc;
1119 }
1120
1099 /* Now that we can no longer fail, copy information */ 1121 /* Now that we can no longer fail, copy information */
1100 1122
1101 /* 1123 /*
@@ -1698,7 +1720,7 @@ int iwl_alive_start(struct iwl_priv *priv)
1698 /* Configure Tx antenna selection based on H/W config */ 1720 /* Configure Tx antenna selection based on H/W config */
1699 iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); 1721 iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
1700 1722
1701 if (iwl_is_associated_ctx(ctx)) { 1723 if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
1702 struct iwl_rxon_cmd *active_rxon = 1724 struct iwl_rxon_cmd *active_rxon =
1703 (struct iwl_rxon_cmd *)&ctx->active; 1725 (struct iwl_rxon_cmd *)&ctx->active;
1704 /* apply any changes in staging */ 1726 /* apply any changes in staging */
@@ -1713,7 +1735,10 @@ int iwl_alive_start(struct iwl_priv *priv)
1713 iwlagn_set_rxon_chain(priv, ctx); 1735 iwlagn_set_rxon_chain(priv, ctx);
1714 } 1736 }
1715 1737
1716 iwl_reset_run_time_calib(priv); 1738 if (!priv->wowlan) {
1739 /* WoWLAN ucode will not reply in the same way, skip it */
1740 iwl_reset_run_time_calib(priv);
1741 }
1717 1742
1718 set_bit(STATUS_READY, &priv->status); 1743 set_bit(STATUS_READY, &priv->status);
1719 1744
@@ -2153,6 +2178,23 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
2153 WIPHY_FLAG_DISABLE_BEACON_HINTS | 2178 WIPHY_FLAG_DISABLE_BEACON_HINTS |
2154 WIPHY_FLAG_IBSS_RSN; 2179 WIPHY_FLAG_IBSS_RSN;
2155 2180
2181 if (priv->ucode_wowlan.code.len && device_can_wakeup(priv->bus->dev)) {
2182 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
2183 WIPHY_WOWLAN_DISCONNECT |
2184 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
2185 WIPHY_WOWLAN_RFKILL_RELEASE;
2186 if (!iwlagn_mod_params.sw_crypto)
2187 hw->wiphy->wowlan.flags |=
2188 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
2189 WIPHY_WOWLAN_GTK_REKEY_FAILURE;
2190
2191 hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS;
2192 hw->wiphy->wowlan.pattern_min_len =
2193 IWLAGN_WOWLAN_MIN_PATTERN_LEN;
2194 hw->wiphy->wowlan.pattern_max_len =
2195 IWLAGN_WOWLAN_MAX_PATTERN_LEN;
2196 }
2197
2156 if (iwlagn_mod_params.power_save) 2198 if (iwlagn_mod_params.power_save)
2157 hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; 2199 hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
2158 else 2200 else
@@ -2237,6 +2279,467 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
2237 IWL_DEBUG_MAC80211(priv, "leave\n"); 2279 IWL_DEBUG_MAC80211(priv, "leave\n");
2238} 2280}
2239 2281
2282static int iwlagn_send_patterns(struct iwl_priv *priv,
2283 struct cfg80211_wowlan *wowlan)
2284{
2285 struct iwlagn_wowlan_patterns_cmd *pattern_cmd;
2286 struct iwl_host_cmd cmd = {
2287 .id = REPLY_WOWLAN_PATTERNS,
2288 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
2289 .flags = CMD_SYNC,
2290 };
2291 int i, err;
2292
2293 if (!wowlan->n_patterns)
2294 return 0;
2295
2296 cmd.len[0] = sizeof(*pattern_cmd) +
2297 wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern);
2298
2299 pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
2300 if (!pattern_cmd)
2301 return -ENOMEM;
2302
2303 pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
2304
2305 for (i = 0; i < wowlan->n_patterns; i++) {
2306 int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
2307
2308 memcpy(&pattern_cmd->patterns[i].mask,
2309 wowlan->patterns[i].mask, mask_len);
2310 memcpy(&pattern_cmd->patterns[i].pattern,
2311 wowlan->patterns[i].pattern,
2312 wowlan->patterns[i].pattern_len);
2313 pattern_cmd->patterns[i].mask_size = mask_len;
2314 pattern_cmd->patterns[i].pattern_size =
2315 wowlan->patterns[i].pattern_len;
2316 }
2317
2318 cmd.data[0] = pattern_cmd;
2319 err = trans_send_cmd(&priv->trans, &cmd);
2320 kfree(pattern_cmd);
2321 return err;
2322}
2323
2324static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
2325 struct ieee80211_vif *vif,
2326 struct cfg80211_gtk_rekey_data *data)
2327{
2328 struct iwl_priv *priv = hw->priv;
2329
2330 if (iwlagn_mod_params.sw_crypto)
2331 return;
2332
2333 mutex_lock(&priv->mutex);
2334
2335 if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
2336 goto out;
2337
2338 memcpy(priv->kek, data->kek, NL80211_KEK_LEN);
2339 memcpy(priv->kck, data->kck, NL80211_KCK_LEN);
2340 priv->replay_ctr = cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr));
2341 priv->have_rekey_data = true;
2342
2343 out:
2344 mutex_unlock(&priv->mutex);
2345}
2346
2347struct wowlan_key_data {
2348 struct iwl_rxon_context *ctx;
2349 struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc;
2350 struct iwlagn_wowlan_tkip_params_cmd *tkip;
2351 const u8 *bssid;
2352 bool error, use_rsc_tsc, use_tkip;
2353};
2354
2355static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
2356{
2357 int i;
2358
2359 for (i = 0; i < IWLAGN_P1K_SIZE; i++)
2360 out[i] = cpu_to_le16(p1k[i]);
2361}
2362
2363static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
2364 struct ieee80211_vif *vif,
2365 struct ieee80211_sta *sta,
2366 struct ieee80211_key_conf *key,
2367 void *_data)
2368{
2369 struct iwl_priv *priv = hw->priv;
2370 struct wowlan_key_data *data = _data;
2371 struct iwl_rxon_context *ctx = data->ctx;
2372 struct aes_sc *aes_sc, *aes_tx_sc = NULL;
2373 struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
2374 struct iwlagn_p1k_cache *rx_p1ks;
2375 u8 *rx_mic_key;
2376 struct ieee80211_key_seq seq;
2377 u32 cur_rx_iv32 = 0;
2378 u16 p1k[IWLAGN_P1K_SIZE];
2379 int ret, i;
2380
2381 mutex_lock(&priv->mutex);
2382
2383 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
2384 key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
2385 !sta && !ctx->key_mapping_keys)
2386 ret = iwl_set_default_wep_key(priv, ctx, key);
2387 else
2388 ret = iwl_set_dynamic_key(priv, ctx, key, sta);
2389
2390 if (ret) {
2391 IWL_ERR(priv, "Error setting key during suspend!\n");
2392 data->error = true;
2393 }
2394
2395 switch (key->cipher) {
2396 case WLAN_CIPHER_SUITE_TKIP:
2397 if (sta) {
2398 tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
2399 tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
2400
2401 rx_p1ks = data->tkip->rx_uni;
2402
2403 ieee80211_get_key_tx_seq(key, &seq);
2404 tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
2405 tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
2406
2407 ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
2408 iwlagn_convert_p1k(p1k, data->tkip->tx.p1k);
2409
2410 memcpy(data->tkip->mic_keys.tx,
2411 &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
2412 IWLAGN_MIC_KEY_SIZE);
2413
2414 rx_mic_key = data->tkip->mic_keys.rx_unicast;
2415 } else {
2416 tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
2417 rx_p1ks = data->tkip->rx_multi;
2418 rx_mic_key = data->tkip->mic_keys.rx_mcast;
2419 }
2420
2421 /*
2422 * For non-QoS this relies on the fact that both the uCode and
2423 * mac80211 use TID 0 (as they need to to avoid replay attacks)
2424 * for checking the IV in the frames.
2425 */
2426 for (i = 0; i < IWLAGN_NUM_RSC; i++) {
2427 ieee80211_get_key_rx_seq(key, i, &seq);
2428 tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);
2429 tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
2430 /* wrapping isn't allowed, AP must rekey */
2431 if (seq.tkip.iv32 > cur_rx_iv32)
2432 cur_rx_iv32 = seq.tkip.iv32;
2433 }
2434
2435 ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k);
2436 iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k);
2437 ieee80211_get_tkip_rx_p1k(key, data->bssid,
2438 cur_rx_iv32 + 1, p1k);
2439 iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k);
2440
2441 memcpy(rx_mic_key,
2442 &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
2443 IWLAGN_MIC_KEY_SIZE);
2444
2445 data->use_tkip = true;
2446 data->use_rsc_tsc = true;
2447 break;
2448 case WLAN_CIPHER_SUITE_CCMP:
2449 if (sta) {
2450 u8 *pn = seq.ccmp.pn;
2451
2452 aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
2453 aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
2454
2455 ieee80211_get_key_tx_seq(key, &seq);
2456 aes_tx_sc->pn = cpu_to_le64(
2457 (u64)pn[5] |
2458 ((u64)pn[4] << 8) |
2459 ((u64)pn[3] << 16) |
2460 ((u64)pn[2] << 24) |
2461 ((u64)pn[1] << 32) |
2462 ((u64)pn[0] << 40));
2463 } else
2464 aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
2465
2466 /*
2467 * For non-QoS this relies on the fact that both the uCode and
2468 * mac80211 use TID 0 for checking the IV in the frames.
2469 */
2470 for (i = 0; i < IWLAGN_NUM_RSC; i++) {
2471 u8 *pn = seq.ccmp.pn;
2472
2473 ieee80211_get_key_rx_seq(key, i, &seq);
2474 aes_sc->pn = cpu_to_le64(
2475 (u64)pn[5] |
2476 ((u64)pn[4] << 8) |
2477 ((u64)pn[3] << 16) |
2478 ((u64)pn[2] << 24) |
2479 ((u64)pn[1] << 32) |
2480 ((u64)pn[0] << 40));
2481 }
2482 data->use_rsc_tsc = true;
2483 break;
2484 }
2485
2486 mutex_unlock(&priv->mutex);
2487}
2488
2489static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
2490 struct cfg80211_wowlan *wowlan)
2491{
2492 struct iwl_priv *priv = hw->priv;
2493 struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
2494 struct iwl_rxon_cmd rxon;
2495 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
2496 struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
2497 struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
2498 struct wowlan_key_data key_data = {
2499 .ctx = ctx,
2500 .bssid = ctx->active.bssid_addr,
2501 .use_rsc_tsc = false,
2502 .tkip = &tkip_cmd,
2503 .use_tkip = false,
2504 };
2505 int ret, i;
2506 u16 seq;
2507
2508 if (WARN_ON(!wowlan))
2509 return -EINVAL;
2510
2511 mutex_lock(&priv->mutex);
2512
2513 /* Don't attempt WoWLAN when not associated, tear down instead. */
2514 if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
2515 !iwl_is_associated_ctx(ctx)) {
2516 ret = 1;
2517 goto out;
2518 }
2519
2520 key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
2521 if (!key_data.rsc_tsc) {
2522 ret = -ENOMEM;
2523 goto out;
2524 }
2525
2526 memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd));
2527
2528 /*
2529 * We know the last used seqno, and the uCode expects to know that
2530 * one, it will increment before TX.
2531 */
2532 seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ;
2533 wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq);
2534
2535 /*
2536 * For QoS counters, we store the one to use next, so subtract 0x10
2537 * since the uCode will add 0x10 before using the value.
2538 */
2539 for (i = 0; i < 8; i++) {
2540 seq = priv->stations[IWL_AP_ID].tid[i].seq_number;
2541 seq -= 0x10;
2542 wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
2543 }
2544
2545 if (wowlan->disconnect)
2546 wakeup_filter_cmd.enabled |=
2547 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS |
2548 IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE);
2549 if (wowlan->magic_pkt)
2550 wakeup_filter_cmd.enabled |=
2551 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET);
2552 if (wowlan->gtk_rekey_failure)
2553 wakeup_filter_cmd.enabled |=
2554 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
2555 if (wowlan->eap_identity_req)
2556 wakeup_filter_cmd.enabled |=
2557 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ);
2558 if (wowlan->four_way_handshake)
2559 wakeup_filter_cmd.enabled |=
2560 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
2561 if (wowlan->rfkill_release)
2562 wakeup_filter_cmd.enabled |=
2563 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_RFKILL);
2564 if (wowlan->n_patterns)
2565 wakeup_filter_cmd.enabled |=
2566 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH);
2567
2568 iwl_scan_cancel_timeout(priv, 200);
2569
2570 memcpy(&rxon, &ctx->active, sizeof(rxon));
2571
2572 trans_stop_device(&priv->trans);
2573
2574 priv->wowlan = true;
2575
2576 ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan,
2577 IWL_UCODE_WOWLAN);
2578 if (ret)
2579 goto error;
2580
2581 /* now configure WoWLAN ucode */
2582 ret = iwl_alive_start(priv);
2583 if (ret)
2584 goto error;
2585
2586 memcpy(&ctx->staging, &rxon, sizeof(rxon));
2587 ret = iwlagn_commit_rxon(priv, ctx);
2588 if (ret)
2589 goto error;
2590
2591 ret = iwl_power_update_mode(priv, true);
2592 if (ret)
2593 goto error;
2594
2595 if (!iwlagn_mod_params.sw_crypto) {
2596 /* mark all keys clear */
2597 priv->ucode_key_table = 0;
2598 ctx->key_mapping_keys = 0;
2599
2600 /*
2601 * This needs to be unlocked due to lock ordering
2602 * constraints. Since we're in the suspend path
2603 * that isn't really a problem though.
2604 */
2605 mutex_unlock(&priv->mutex);
2606 ieee80211_iter_keys(priv->hw, ctx->vif,
2607 iwlagn_wowlan_program_keys,
2608 &key_data);
2609 mutex_lock(&priv->mutex);
2610 if (key_data.error) {
2611 ret = -EIO;
2612 goto error;
2613 }
2614
2615 if (key_data.use_rsc_tsc) {
2616 struct iwl_host_cmd rsc_tsc_cmd = {
2617 .id = REPLY_WOWLAN_TSC_RSC_PARAMS,
2618 .flags = CMD_SYNC,
2619 .data[0] = key_data.rsc_tsc,
2620 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
2621 .len[0] = sizeof(*key_data.rsc_tsc),
2622 };
2623
2624 ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd);
2625 if (ret)
2626 goto error;
2627 }
2628
2629 if (key_data.use_tkip) {
2630 ret = trans_send_cmd_pdu(&priv->trans,
2631 REPLY_WOWLAN_TKIP_PARAMS,
2632 CMD_SYNC, sizeof(tkip_cmd),
2633 &tkip_cmd);
2634 if (ret)
2635 goto error;
2636 }
2637
2638 if (priv->have_rekey_data) {
2639 memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
2640 memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN);
2641 kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
2642 memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN);
2643 kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
2644 kek_kck_cmd.replay_ctr = priv->replay_ctr;
2645
2646 ret = trans_send_cmd_pdu(&priv->trans,
2647 REPLY_WOWLAN_KEK_KCK_MATERIAL,
2648 CMD_SYNC, sizeof(kek_kck_cmd),
2649 &kek_kck_cmd);
2650 if (ret)
2651 goto error;
2652 }
2653 }
2654
2655 ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER,
2656 CMD_SYNC, sizeof(wakeup_filter_cmd),
2657 &wakeup_filter_cmd);
2658 if (ret)
2659 goto error;
2660
2661 ret = iwlagn_send_patterns(priv, wowlan);
2662 if (ret)
2663 goto error;
2664
2665 device_set_wakeup_enable(priv->bus->dev, true);
2666
2667 /* Now let the ucode operate on its own */
2668 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
2669 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
2670
2671 goto out;
2672
2673 error:
2674 priv->wowlan = false;
2675 iwlagn_prepare_restart(priv);
2676 ieee80211_restart_hw(priv->hw);
2677 out:
2678 mutex_unlock(&priv->mutex);
2679 kfree(key_data.rsc_tsc);
2680 return ret;
2681}
2682
2683static int iwlagn_mac_resume(struct ieee80211_hw *hw)
2684{
2685 struct iwl_priv *priv = hw->priv;
2686 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
2687 struct ieee80211_vif *vif;
2688 unsigned long flags;
2689 u32 base, status = 0xffffffff;
2690 int ret = -EIO;
2691
2692 mutex_lock(&priv->mutex);
2693
2694 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
2695 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
2696
2697 base = priv->device_pointers.error_event_table;
2698 if (iwlagn_hw_valid_rtc_data_addr(base)) {
2699 spin_lock_irqsave(&priv->reg_lock, flags);
2700 ret = iwl_grab_nic_access_silent(priv);
2701 if (ret == 0) {
2702 iwl_write32(priv, HBUS_TARG_MEM_RADDR, base);
2703 status = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
2704 iwl_release_nic_access(priv);
2705 }
2706 spin_unlock_irqrestore(&priv->reg_lock, flags);
2707
2708#ifdef CONFIG_IWLWIFI_DEBUGFS
2709 if (ret == 0) {
2710 if (!priv->wowlan_sram)
2711 priv->wowlan_sram =
2712 kzalloc(priv->ucode_wowlan.data.len,
2713 GFP_KERNEL);
2714
2715 if (priv->wowlan_sram)
2716 _iwl_read_targ_mem_words(
2717 priv, 0x800000, priv->wowlan_sram,
2718 priv->ucode_wowlan.data.len / 4);
2719 }
2720#endif
2721 }
2722
2723 /* we'll clear ctx->vif during iwlagn_prepare_restart() */
2724 vif = ctx->vif;
2725
2726 priv->wowlan = false;
2727
2728 device_set_wakeup_enable(priv->bus->dev, false);
2729
2730 iwlagn_prepare_restart(priv);
2731
2732 memset((void *)&ctx->active, 0, sizeof(ctx->active));
2733 iwl_connection_init_rx_config(priv, ctx);
2734 iwlagn_set_rxon_chain(priv, ctx);
2735
2736 mutex_unlock(&priv->mutex);
2737
2738 ieee80211_resume_disconnect(vif);
2739
2740 return 1;
2741}
2742
2240static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 2743static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2241{ 2744{
2242 struct iwl_priv *priv = hw->priv; 2745 struct iwl_priv *priv = hw->priv;
@@ -2926,6 +3429,9 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
2926 iwl_free_channel_map(priv); 3429 iwl_free_channel_map(priv);
2927 kfree(priv->scan_cmd); 3430 kfree(priv->scan_cmd);
2928 kfree(priv->beacon_cmd); 3431 kfree(priv->beacon_cmd);
3432#ifdef CONFIG_IWLWIFI_DEBUGFS
3433 kfree(priv->wowlan_sram);
3434#endif
2929} 3435}
2930 3436
2931static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, 3437static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
@@ -2955,6 +3461,8 @@ struct ieee80211_ops iwlagn_hw_ops = {
2955 .tx = iwlagn_mac_tx, 3461 .tx = iwlagn_mac_tx,
2956 .start = iwlagn_mac_start, 3462 .start = iwlagn_mac_start,
2957 .stop = iwlagn_mac_stop, 3463 .stop = iwlagn_mac_stop,
3464 .suspend = iwlagn_mac_suspend,
3465 .resume = iwlagn_mac_resume,
2958 .add_interface = iwl_mac_add_interface, 3466 .add_interface = iwl_mac_add_interface,
2959 .remove_interface = iwl_mac_remove_interface, 3467 .remove_interface = iwl_mac_remove_interface,
2960 .change_interface = iwl_mac_change_interface, 3468 .change_interface = iwl_mac_change_interface,
@@ -2962,6 +3470,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
2962 .configure_filter = iwlagn_configure_filter, 3470 .configure_filter = iwlagn_configure_filter,
2963 .set_key = iwlagn_mac_set_key, 3471 .set_key = iwlagn_mac_set_key,
2964 .update_tkip_key = iwlagn_mac_update_tkip_key, 3472 .update_tkip_key = iwlagn_mac_update_tkip_key,
3473 .set_rekey_data = iwlagn_mac_set_rekey_data,
2965 .conf_tx = iwl_mac_conf_tx, 3474 .conf_tx = iwl_mac_conf_tx,
2966 .bss_info_changed = iwlagn_bss_info_changed, 3475 .bss_info_changed = iwlagn_bss_info_changed,
2967 .ampdu_action = iwlagn_mac_ampdu_action, 3476 .ampdu_action = iwlagn_mac_ampdu_action,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index b58985373a71..5769ca5cebca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -188,6 +188,13 @@ enum {
188 REPLY_WIPAN_NOA_NOTIFICATION = 0xbc, 188 REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
189 REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd, 189 REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd,
190 190
191 REPLY_WOWLAN_PATTERNS = 0xe0,
192 REPLY_WOWLAN_WAKEUP_FILTER = 0xe1,
193 REPLY_WOWLAN_TSC_RSC_PARAMS = 0xe2,
194 REPLY_WOWLAN_TKIP_PARAMS = 0xe3,
195 REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4,
196 REPLY_WOWLAN_GET_STATUS = 0xe5,
197
191 REPLY_MAX = 0xff 198 REPLY_MAX = 0xff
192}; 199};
193 200
@@ -3764,6 +3771,127 @@ struct iwl_bt_coex_prot_env_cmd {
3764 u8 reserved[2]; 3771 u8 reserved[2];
3765} __attribute__((packed)); 3772} __attribute__((packed));
3766 3773
3774/*
3775 * REPLY_WOWLAN_PATTERNS
3776 */
3777#define IWLAGN_WOWLAN_MIN_PATTERN_LEN 16
3778#define IWLAGN_WOWLAN_MAX_PATTERN_LEN 128
3779
3780struct iwlagn_wowlan_pattern {
3781 u8 mask[IWLAGN_WOWLAN_MAX_PATTERN_LEN / 8];
3782 u8 pattern[IWLAGN_WOWLAN_MAX_PATTERN_LEN];
3783 u8 mask_size;
3784 u8 pattern_size;
3785 __le16 reserved;
3786} __packed;
3787
3788#define IWLAGN_WOWLAN_MAX_PATTERNS 20
3789
3790struct iwlagn_wowlan_patterns_cmd {
3791 __le32 n_patterns;
3792 struct iwlagn_wowlan_pattern patterns[];
3793} __packed;
3794
3795/*
3796 * REPLY_WOWLAN_WAKEUP_FILTER
3797 */
3798enum iwlagn_wowlan_wakeup_filters {
3799 IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
3800 IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
3801 IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
3802 IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
3803 IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
3804 IWLAGN_WOWLAN_WAKEUP_RFKILL = BIT(5),
3805 IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR = BIT(6),
3806 IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(7),
3807 IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(8),
3808 IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(9),
3809 IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(10),
3810};
3811
3812struct iwlagn_wowlan_wakeup_filter_cmd {
3813 __le32 enabled;
3814 __le16 non_qos_seq;
3815 u8 min_sleep_seconds;
3816 u8 reserved;
3817 __le16 qos_seq[8];
3818};
3819
3820/*
3821 * REPLY_WOWLAN_TSC_RSC_PARAMS
3822 */
3823#define IWLAGN_NUM_RSC 16
3824
3825struct tkip_sc {
3826 __le16 iv16;
3827 __le16 pad;
3828 __le32 iv32;
3829} __packed;
3830
3831struct iwlagn_tkip_rsc_tsc {
3832 struct tkip_sc unicast_rsc[IWLAGN_NUM_RSC];
3833 struct tkip_sc multicast_rsc[IWLAGN_NUM_RSC];
3834 struct tkip_sc tsc;
3835} __packed;
3836
3837struct aes_sc {
3838 __le64 pn;
3839} __packed;
3840
3841struct iwlagn_aes_rsc_tsc {
3842 struct aes_sc unicast_rsc[IWLAGN_NUM_RSC];
3843 struct aes_sc multicast_rsc[IWLAGN_NUM_RSC];
3844 struct aes_sc tsc;
3845} __packed;
3846
3847union iwlagn_all_tsc_rsc {
3848 struct iwlagn_tkip_rsc_tsc tkip;
3849 struct iwlagn_aes_rsc_tsc aes;
3850};
3851
3852struct iwlagn_wowlan_rsc_tsc_params_cmd {
3853 union iwlagn_all_tsc_rsc all_tsc_rsc;
3854} __packed;
3855
3856/*
3857 * REPLY_WOWLAN_TKIP_PARAMS
3858 */
3859#define IWLAGN_MIC_KEY_SIZE 8
3860#define IWLAGN_P1K_SIZE 5
3861struct iwlagn_mic_keys {
3862 u8 tx[IWLAGN_MIC_KEY_SIZE];
3863 u8 rx_unicast[IWLAGN_MIC_KEY_SIZE];
3864 u8 rx_mcast[IWLAGN_MIC_KEY_SIZE];
3865} __packed;
3866
3867struct iwlagn_p1k_cache {
3868 __le16 p1k[IWLAGN_P1K_SIZE];
3869} __packed;
3870
3871#define IWLAGN_NUM_RX_P1K_CACHE 2
3872
3873struct iwlagn_wowlan_tkip_params_cmd {
3874 struct iwlagn_mic_keys mic_keys;
3875 struct iwlagn_p1k_cache tx;
3876 struct iwlagn_p1k_cache rx_uni[IWLAGN_NUM_RX_P1K_CACHE];
3877 struct iwlagn_p1k_cache rx_multi[IWLAGN_NUM_RX_P1K_CACHE];
3878} __packed;
3879
3880/*
3881 * REPLY_WOWLAN_KEK_KCK_MATERIAL
3882 */
3883
3884#define IWLAGN_KCK_MAX_SIZE 32
3885#define IWLAGN_KEK_MAX_SIZE 32
3886
3887struct iwlagn_wowlan_kek_kck_material_cmd {
3888 u8 kck[IWLAGN_KCK_MAX_SIZE];
3889 u8 kek[IWLAGN_KEK_MAX_SIZE];
3890 __le16 kck_len;
3891 __le16 kek_len;
3892 __le64 replay_ctr;
3893} __packed;
3894
3767/****************************************************************************** 3895/******************************************************************************
3768 * (13) 3896 * (13)
3769 * Union of all expected notifications/responses: 3897 * Union of all expected notifications/responses:
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 9b9f462ea0ff..2f42547622d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1903,8 +1903,12 @@ int iwl_suspend(struct iwl_priv *priv)
1903 * first but since iwl_mac_stop() has no knowledge of who the caller is, 1903 * first but since iwl_mac_stop() has no knowledge of who the caller is,
1904 * it will not call apm_ops.stop() to stop the DMA operation. 1904 * it will not call apm_ops.stop() to stop the DMA operation.
1905 * Calling apm_ops.stop here to make sure we stop the DMA. 1905 * Calling apm_ops.stop here to make sure we stop the DMA.
1906 *
1907 * But of course ... if we have configured WoWLAN then we did other
1908 * things already :-)
1906 */ 1909 */
1907 iwl_apm_stop(priv); 1910 if (!priv->wowlan)
1911 iwl_apm_stop(priv);
1908 1912
1909 return 0; 1913 return 0;
1910} 1914}
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 5ab90ba7a024..d6dbb0423045 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -351,6 +351,7 @@
351#define CSR_UCODE_SW_BIT_RFKILL (0x00000002) 351#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
352#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) 352#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
353#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) 353#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
354#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE (0x00000020)
354 355
355/* GP Driver */ 356/* GP Driver */
356#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003) 357#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 17aebf08dff8..ec1485b2d3fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -322,6 +322,19 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
322 return count; 322 return count;
323} 323}
324 324
325static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
326 char __user *user_buf,
327 size_t count, loff_t *ppos)
328{
329 struct iwl_priv *priv = file->private_data;
330
331 if (!priv->wowlan_sram)
332 return -ENODATA;
333
334 return simple_read_from_buffer(user_buf, count, ppos,
335 priv->wowlan_sram,
336 priv->ucode_wowlan.data.len);
337}
325static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, 338static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
326 size_t count, loff_t *ppos) 339 size_t count, loff_t *ppos)
327{ 340{
@@ -856,6 +869,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
856} 869}
857 870
858DEBUGFS_READ_WRITE_FILE_OPS(sram); 871DEBUGFS_READ_WRITE_FILE_OPS(sram);
872DEBUGFS_READ_FILE_OPS(wowlan_sram);
859DEBUGFS_READ_WRITE_FILE_OPS(log_event); 873DEBUGFS_READ_WRITE_FILE_OPS(log_event);
860DEBUGFS_READ_FILE_OPS(nvm); 874DEBUGFS_READ_FILE_OPS(nvm);
861DEBUGFS_READ_FILE_OPS(stations); 875DEBUGFS_READ_FILE_OPS(stations);
@@ -2667,6 +2681,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
2667 2681
2668 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 2682 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
2669 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 2683 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
2684 DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR);
2670 DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); 2685 DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
2671 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 2686 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
2672 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 2687 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c27380440b66..fc2387342456 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -551,7 +551,8 @@ enum iwl_ucode_tlv_type {
551 IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, 551 IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13,
552 IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, 552 IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14,
553 IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, 553 IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15,
554 /* 16 and 17 reserved for future use */ 554 IWL_UCODE_TLV_WOWLAN_INST = 16,
555 IWL_UCODE_TLV_WOWLAN_DATA = 17,
555 IWL_UCODE_TLV_FLAGS = 18, 556 IWL_UCODE_TLV_FLAGS = 18,
556}; 557};
557 558
@@ -1284,6 +1285,7 @@ struct iwl_priv {
1284 1285
1285 struct fw_img ucode_rt; 1286 struct fw_img ucode_rt;
1286 struct fw_img ucode_init; 1287 struct fw_img ucode_init;
1288 struct fw_img ucode_wowlan;
1287 1289
1288 enum iwlagn_ucode_type ucode_type; 1290 enum iwlagn_ucode_type ucode_type;
1289 u8 ucode_write_complete; /* the image write is complete */ 1291 u8 ucode_write_complete; /* the image write is complete */
@@ -1356,6 +1358,8 @@ struct iwl_priv {
1356 1358
1357 u8 mac80211_registered; 1359 u8 mac80211_registered;
1358 1360
1361 bool wowlan;
1362
1359 /* eeprom -- this is in the card's little endian byte order */ 1363 /* eeprom -- this is in the card's little endian byte order */
1360 u8 *eeprom; 1364 u8 *eeprom;
1361 int nvm_device_type; 1365 int nvm_device_type;
@@ -1508,6 +1512,7 @@ struct iwl_priv {
1508 struct dentry *debugfs_dir; 1512 struct dentry *debugfs_dir;
1509 u32 dbgfs_sram_offset, dbgfs_sram_len; 1513 u32 dbgfs_sram_offset, dbgfs_sram_len;
1510 bool disable_ht40; 1514 bool disable_ht40;
1515 void *wowlan_sram;
1511#endif /* CONFIG_IWLWIFI_DEBUGFS */ 1516#endif /* CONFIG_IWLWIFI_DEBUGFS */
1512 1517
1513 struct work_struct txpower_work; 1518 struct work_struct txpower_work;
@@ -1528,6 +1533,11 @@ struct iwl_priv {
1528 u32 tm_fixed_rate; 1533 u32 tm_fixed_rate;
1529#endif 1534#endif
1530 1535
1536 /* WoWLAN GTK rekey data */
1537 u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
1538 __le64 replay_ctr;
1539 __le16 last_seq_ctl;
1540 bool have_rekey_data;
1531}; /*iwl_priv */ 1541}; /*iwl_priv */
1532 1542
1533static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) 1543static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index de4f33304edb..3ec619c6881c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -347,7 +347,9 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
347 347
348 dtimper = priv->hw->conf.ps_dtim_period ?: 1; 348 dtimper = priv->hw->conf.ps_dtim_period ?: 1;
349 349
350 if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) 350 if (priv->wowlan)
351 iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
352 else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
351 iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); 353 iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
352 else if (iwl_tt_is_low_power_state(priv)) { 354 else if (iwl_tt_is_low_power_state(priv)) {
353 /* in thermal throttling low power state */ 355 /* in thermal throttling low power state */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
index 27f78fed2ec2..a6b2b1db0b1d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
@@ -866,6 +866,12 @@ const char *get_cmd_string(u8 cmd)
866 IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); 866 IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
867 IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); 867 IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
868 IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); 868 IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
869 IWL_CMD(REPLY_WOWLAN_PATTERNS);
870 IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
871 IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
872 IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
873 IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
874 IWL_CMD(REPLY_WOWLAN_GET_STATUS);
869 default: 875 default:
870 return "UNKNOWN"; 876 return "UNKNOWN";
871 877