aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c7
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*/
442enum iwl_mvm_rxq_notif_type { 443enum 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*/
453struct iwl_mvm_internal_rxq_notif { 456struct 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
4040static 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
4067out:
4068 atomic_set(&mvm->queue_sync_counter, 0);
4069 mvm->queue_sync_cookie++;
4070}
4071
4072static 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
4040const struct ieee80211_ops iwl_mvm_hw_ops = { 4081const 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;