diff options
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 43 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 7 |
5 files changed, 58 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index 4c086d048097..ade170bd8683 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | |||
@@ -437,9 +437,11 @@ struct iwl_rxq_sync_notification { | |||
437 | /** | 437 | /** |
438 | * Internal message identifier | 438 | * Internal message identifier |
439 | * | 439 | * |
440 | * @IWL_MVM_RXQ_SYNC: sync RSS queues | ||
440 | * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA | 441 | * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA |
441 | */ | 442 | */ |
442 | enum iwl_mvm_rxq_notif_type { | 443 | enum iwl_mvm_rxq_notif_type { |
444 | IWL_MVM_RXQ_SYNC, | ||
443 | IWL_MVM_RXQ_NOTIF_DEL_BA, | 445 | IWL_MVM_RXQ_NOTIF_DEL_BA, |
444 | }; | 446 | }; |
445 | 447 | ||
@@ -448,10 +450,12 @@ enum iwl_mvm_rxq_notif_type { | |||
448 | * in &iwl_rxq_sync_cmd. Should be DWORD aligned. | 450 | * in &iwl_rxq_sync_cmd. Should be DWORD aligned. |
449 | * | 451 | * |
450 | * @type: value from &iwl_mvm_rxq_notif_type | 452 | * @type: value from &iwl_mvm_rxq_notif_type |
453 | * @cookie: internal cookie to identify old notifications | ||
451 | * @data: payload | 454 | * @data: payload |
452 | */ | 455 | */ |
453 | struct iwl_mvm_internal_rxq_notif { | 456 | struct iwl_mvm_internal_rxq_notif { |
454 | u32 type; | 457 | u32 type; |
458 | u32 cookie; | ||
455 | u8 data[]; | 459 | u8 data[]; |
456 | } __packed; | 460 | } __packed; |
457 | 461 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 5ace468070cb..d6ad77a2c767 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
@@ -4037,6 +4037,47 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, | |||
4037 | } | 4037 | } |
4038 | } | 4038 | } |
4039 | 4039 | ||
4040 | static void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm) | ||
4041 | { | ||
4042 | struct iwl_mvm_internal_rxq_notif data = { | ||
4043 | .type = IWL_MVM_RXQ_SYNC, | ||
4044 | .cookie = mvm->queue_sync_cookie, | ||
4045 | }; | ||
4046 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(notif_waitq); | ||
4047 | u32 qmask = BIT(mvm->trans->num_rx_queues) - 1; | ||
4048 | int ret; | ||
4049 | |||
4050 | lockdep_assert_held(&mvm->mutex); | ||
4051 | |||
4052 | if (!iwl_mvm_has_new_rx_api(mvm)) | ||
4053 | return; | ||
4054 | |||
4055 | atomic_set(&mvm->queue_sync_counter, mvm->trans->num_rx_queues); | ||
4056 | |||
4057 | ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)&data, sizeof(data)); | ||
4058 | if (ret) { | ||
4059 | IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret); | ||
4060 | goto out; | ||
4061 | } | ||
4062 | ret = wait_event_timeout(notif_waitq, | ||
4063 | atomic_read(&mvm->queue_sync_counter) == 0, | ||
4064 | HZ); | ||
4065 | WARN_ON_ONCE(!ret); | ||
4066 | |||
4067 | out: | ||
4068 | atomic_set(&mvm->queue_sync_counter, 0); | ||
4069 | mvm->queue_sync_cookie++; | ||
4070 | } | ||
4071 | |||
4072 | static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) | ||
4073 | { | ||
4074 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
4075 | |||
4076 | mutex_lock(&mvm->mutex); | ||
4077 | iwl_mvm_sync_rx_queues_internal(mvm); | ||
4078 | mutex_unlock(&mvm->mutex); | ||
4079 | } | ||
4080 | |||
4040 | const struct ieee80211_ops iwl_mvm_hw_ops = { | 4081 | const struct ieee80211_ops iwl_mvm_hw_ops = { |
4041 | .tx = iwl_mvm_mac_tx, | 4082 | .tx = iwl_mvm_mac_tx, |
4042 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 4083 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
@@ -4093,6 +4134,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
4093 | 4134 | ||
4094 | .event_callback = iwl_mvm_mac_event_callback, | 4135 | .event_callback = iwl_mvm_mac_event_callback, |
4095 | 4136 | ||
4137 | .sync_rx_queues = iwl_mvm_sync_rx_queues, | ||
4138 | |||
4096 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) | 4139 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) |
4097 | 4140 | ||
4098 | #ifdef CONFIG_PM_SLEEP | 4141 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 85800ba0c667..c7c8a6205eaa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | |||
@@ -633,6 +633,8 @@ struct iwl_mvm { | |||
633 | 633 | ||
634 | unsigned long status; | 634 | unsigned long status; |
635 | 635 | ||
636 | u32 queue_sync_cookie; | ||
637 | atomic_t queue_sync_counter; | ||
636 | /* | 638 | /* |
637 | * for beacon filtering - | 639 | * for beacon filtering - |
638 | * currently only one interface can be supported | 640 | * currently only one interface can be supported |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 8bfb8e06a90c..7c6a5984105f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c | |||
@@ -586,6 +586,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
586 | skb_queue_head_init(&mvm->d0i3_tx); | 586 | skb_queue_head_init(&mvm->d0i3_tx); |
587 | init_waitqueue_head(&mvm->d0i3_exit_waitq); | 587 | init_waitqueue_head(&mvm->d0i3_exit_waitq); |
588 | 588 | ||
589 | atomic_set(&mvm->queue_sync_counter, 0); | ||
590 | |||
589 | SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev); | 591 | SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev); |
590 | 592 | ||
591 | /* | 593 | /* |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 651604d18a32..b4d9c42d411a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | |||
@@ -406,6 +406,13 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
406 | internal_notif = (void *)notif->payload; | 406 | internal_notif = (void *)notif->payload; |
407 | 407 | ||
408 | switch (internal_notif->type) { | 408 | switch (internal_notif->type) { |
409 | case IWL_MVM_RXQ_SYNC: | ||
410 | if (mvm->queue_sync_cookie == internal_notif->cookie) | ||
411 | atomic_dec(&mvm->queue_sync_counter); | ||
412 | else | ||
413 | WARN_ONCE(1, | ||
414 | "Received expired RX queue sync message\n"); | ||
415 | break; | ||
409 | case IWL_MVM_RXQ_NOTIF_DEL_BA: | 416 | case IWL_MVM_RXQ_NOTIF_DEL_BA: |
410 | /* TODO */ | 417 | /* TODO */ |
411 | break; | 418 | break; |