aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/time-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c61
1 files changed, 59 insertions, 2 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 33e5041f1efc..447d3b1003df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -6,6 +6,7 @@
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 12 * it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
31 * BSD LICENSE 32 * BSD LICENSE
32 * 33 *
33 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
35 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
34 * All rights reserved. 36 * All rights reserved.
35 * 37 *
36 * Redistribution and use in source and binary forms, with or without 38 * Redistribution and use in source and binary forms, with or without
@@ -348,6 +350,38 @@ unlock:
348 return 0; 350 return 0;
349} 351}
350 352
353static bool iwl_mvm_te_notif(struct iwl_notif_wait_data *notif_wait,
354 struct iwl_rx_packet *pkt, void *data)
355{
356 struct iwl_mvm *mvm =
357 container_of(notif_wait, struct iwl_mvm, notif_wait);
358 struct iwl_mvm_time_event_data *te_data = data;
359 struct iwl_time_event_notif *resp;
360 int resp_len = iwl_rx_packet_payload_len(pkt);
361
362 if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_NOTIFICATION))
363 return true;
364
365 if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
366 IWL_ERR(mvm, "Invalid TIME_EVENT_NOTIFICATION response\n");
367 return true;
368 }
369
370 resp = (void *)pkt->data;
371
372 /* te_data->uid is already set in the TIME_EVENT_CMD response */
373 if (le32_to_cpu(resp->unique_id) != te_data->uid)
374 return false;
375
376 IWL_DEBUG_TE(mvm, "TIME_EVENT_NOTIFICATION response - UID = 0x%x\n",
377 te_data->uid);
378 if (!resp->status)
379 IWL_ERR(mvm,
380 "TIME_EVENT_NOTIFICATION received but not executed\n");
381
382 return true;
383}
384
351static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, 385static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
352 struct iwl_rx_packet *pkt, void *data) 386 struct iwl_rx_packet *pkt, void *data)
353{ 387{
@@ -441,10 +475,12 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
441void iwl_mvm_protect_session(struct iwl_mvm *mvm, 475void iwl_mvm_protect_session(struct iwl_mvm *mvm,
442 struct ieee80211_vif *vif, 476 struct ieee80211_vif *vif,
443 u32 duration, u32 min_duration, 477 u32 duration, u32 min_duration,
444 u32 max_delay) 478 u32 max_delay, bool wait_for_notif)
445{ 479{
446 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 480 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
447 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 481 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
482 const u8 te_notif_response[] = { TIME_EVENT_NOTIFICATION };
483 struct iwl_notification_wait wait_te_notif;
448 struct iwl_time_event_cmd time_cmd = {}; 484 struct iwl_time_event_cmd time_cmd = {};
449 485
450 lockdep_assert_held(&mvm->mutex); 486 lockdep_assert_held(&mvm->mutex);
@@ -489,7 +525,28 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
489 TE_V2_NOTIF_HOST_EVENT_END | 525 TE_V2_NOTIF_HOST_EVENT_END |
490 T2_V2_START_IMMEDIATELY); 526 T2_V2_START_IMMEDIATELY);
491 527
492 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 528 if (!wait_for_notif) {
529 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
530 return;
531 }
532
533 /*
534 * Create notification_wait for the TIME_EVENT_NOTIFICATION to use
535 * right after we send the time event
536 */
537 iwl_init_notification_wait(&mvm->notif_wait, &wait_te_notif,
538 te_notif_response,
539 ARRAY_SIZE(te_notif_response),
540 iwl_mvm_te_notif, te_data);
541
542 /* If TE was sent OK - wait for the notification that started */
543 if (iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd)) {
544 IWL_ERR(mvm, "Failed to add TE to protect session\n");
545 iwl_remove_notification(&mvm->notif_wait, &wait_te_notif);
546 } else if (iwl_wait_notification(&mvm->notif_wait, &wait_te_notif,
547 TU_TO_JIFFIES(max_delay))) {
548 IWL_ERR(mvm, "Failed to protect session until TE\n");
549 }
493} 550}
494 551
495/* 552/*