diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 61 |
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 | ||
353 | static 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 | |||
351 | static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, | 385 | static 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, | |||
441 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 475 | void 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 | /* |