iwlwifi: mvm: clean up queue sync implementation
authorJohannes Berg <johannes.berg@intel.com>
Wed, 31 Mar 2021 09:14:42 +0000 (12:14 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Wed, 14 Apr 2021 09:07:16 +0000 (12:07 +0300)
When we do queue sync, it's confusing that we have the structures
declared in the FW API header files that aren't really firmware,
and the union is also confusing - especially now in the code that
checks the size on the return.

So rework this: change the type of sync and whether to do it in a
synchronous fashion to arguments, and build the data structure in
the function, so we don't need the union.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210331121101.f62833fd9893.I612d7ac1c655ec4880329360e15d207698c750bc@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h

index 2c74db8..3f13b57 100644 (file)
@@ -779,36 +779,6 @@ struct iwl_rxq_sync_notification {
        u8 payload[];
 } __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
 
-/**
- * enum iwl_mvm_rxq_notif_type - Internal message identifier
- *
- * @IWL_MVM_RXQ_EMPTY: empty sync notification
- * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
- * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
- */
-enum iwl_mvm_rxq_notif_type {
-       IWL_MVM_RXQ_EMPTY,
-       IWL_MVM_RXQ_NOTIF_DEL_BA,
-       IWL_MVM_RXQ_NSSN_SYNC,
-};
-
-/**
- * struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
- * in &iwl_rxq_sync_cmd. Should be DWORD aligned.
- * FW is agnostic to the payload, so there are no endianity requirements.
- *
- * @type: value from &iwl_mvm_rxq_notif_type
- * @sync: ctrl path is waiting for all notifications to be received
- * @cookie: internal cookie to identify old notifications
- * @data: payload
- */
-struct iwl_mvm_internal_rxq_notif {
-       u16 type;
-       u16 sync;
-       u32 cookie;
-       u8 data[];
-} __packed;
-
 /**
  * enum iwl_mvm_pm_event - type of station PM event
  * @IWL_MVM_PM_EVENT_AWAKE: station woke up
index fbd37a1..fd35dd3 100644 (file)
@@ -5144,28 +5144,50 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
 }
 
 void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
-                                    struct iwl_mvm_internal_rxq_notif *notif,
-                                    u32 size)
+                                    enum iwl_mvm_rxq_notif_type type,
+                                    bool sync,
+                                    const void *data, u32 size)
 {
-       u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
+       struct {
+               struct iwl_rxq_sync_cmd cmd;
+               struct iwl_mvm_internal_rxq_notif notif;
+       } __packed cmd = {
+               .cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1),
+               .cmd.count =
+                       cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
+                                   size),
+               .notif.type = type,
+               .notif.sync = sync,
+       };
+       struct iwl_host_cmd hcmd = {
+               .id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD),
+               .data[0] = &cmd,
+               .len[0] = sizeof(cmd),
+               .data[1] = data,
+               .len[1] = size,
+               .flags = sync ? 0 : CMD_ASYNC,
+       };
        int ret;
 
+       /* size must be a multiple of DWORD */
+       if (WARN_ON(cmd.cmd.count & cpu_to_le32(3)))
+               return;
 
        if (!iwl_mvm_has_new_rx_api(mvm))
                return;
 
-       if (notif->sync) {
-               notif->cookie = mvm->queue_sync_cookie;
+       if (sync) {
+               cmd.notif.cookie = mvm->queue_sync_cookie;
                mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
        }
 
-       ret = iwl_mvm_notify_rx_queue(mvm, qmask, notif, size, !notif->sync);
+       ret = iwl_mvm_send_cmd(mvm, &hcmd);
        if (ret) {
                IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
                goto out;
        }
 
-       if (notif->sync) {
+       if (sync) {
                lockdep_assert_held(&mvm->mutex);
                ret = wait_event_timeout(mvm->rx_sync_waitq,
                                         READ_ONCE(mvm->queue_sync_state) == 0 ||
@@ -5177,7 +5199,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
        }
 
 out:
-       if (notif->sync) {
+       if (sync) {
                mvm->queue_sync_state = 0;
                mvm->queue_sync_cookie++;
        }
@@ -5186,13 +5208,9 @@ out:
 static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-       struct iwl_mvm_internal_rxq_notif data = {
-               .type = IWL_MVM_RXQ_EMPTY,
-               .sync = 1,
-       };
 
        mutex_lock(&mvm->mutex);
-       iwl_mvm_sync_rx_queues_internal(mvm, &data, sizeof(data));
+       iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY, true, NULL, 0);
        mutex_unlock(&mvm->mutex);
 }
 
index 0a963d0..e607ad7 100644 (file)
@@ -1570,9 +1570,6 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue);
 void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                                  struct iwl_rx_cmd_buffer *rxb, int queue);
-int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
-                           const struct iwl_mvm_internal_rxq_notif *notif,
-                           u32 notif_size, bool async);
 void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
                            struct iwl_rx_cmd_buffer *rxb, int queue);
 void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
@@ -2001,8 +1998,9 @@ void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
 void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
 
 void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
-                                    struct iwl_mvm_internal_rxq_notif *notif,
-                                    u32 size);
+                                    enum iwl_mvm_rxq_notif_type type,
+                                    bool sync,
+                                    const void *data, u32 size);
 void iwl_mvm_reorder_timer_expired(struct timer_list *t);
 struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
 struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid);
index af5a6dd..8e26422 100644 (file)
@@ -527,37 +527,6 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
        return false;
 }
 
-int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
-                           const struct iwl_mvm_internal_rxq_notif *notif,
-                           u32 notif_size, bool async)
-{
-       u8 buf[sizeof(struct iwl_rxq_sync_cmd) +
-              sizeof(struct iwl_mvm_rss_sync_notif)];
-       struct iwl_rxq_sync_cmd *cmd = (void *)buf;
-       u32 data_size = sizeof(*cmd) + notif_size;
-       int ret;
-
-       /*
-        * size must be a multiple of DWORD
-        * Ensure we don't overflow buf
-        */
-       if (WARN_ON(notif_size & 3 ||
-                   notif_size > sizeof(struct iwl_mvm_rss_sync_notif)))
-               return -EINVAL;
-
-       cmd->rxq_mask = cpu_to_le32(rxq_mask);
-       cmd->count =  cpu_to_le32(notif_size);
-       cmd->flags = 0;
-       memcpy(cmd->payload, notif, notif_size);
-
-       ret = iwl_mvm_send_cmd_pdu(mvm,
-                                  WIDE_ID(DATA_PATH_GROUP,
-                                          TRIGGER_RX_QUEUES_NOTIF_CMD),
-                                  async ? CMD_ASYNC : 0, data_size, cmd);
-
-       return ret;
-}
-
 /*
  * Returns true if sn2 - buffer_size < sn1 < sn2.
  * To be used only in order to compare reorder buffer head with NSSN.
@@ -573,15 +542,13 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
 static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
 {
        if (IWL_MVM_USE_NSSN_SYNC) {
-               struct iwl_mvm_rss_sync_notif notif = {
-                       .metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
-                       .metadata.sync = 0,
-                       .nssn_sync.baid = baid,
-                       .nssn_sync.nssn = nssn,
+               struct iwl_mvm_nssn_sync_data notif = {
+                       .baid = baid,
+                       .nssn = nssn,
                };
 
-               iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif,
-                                               sizeof(notif));
+               iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NSSN_SYNC, false,
+                                               &notif, sizeof(notif));
        }
 }
 
@@ -830,8 +797,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
                      "invalid notification size %d (%d)",
                      len, (int)(sizeof(*notif) + sizeof(*internal_notif))))
                return;
-       /* remove only the firmware header, we want all of our payload below */
-       len -= sizeof(*notif);
+       len -= sizeof(*notif) + sizeof(*internal_notif);
 
        if (internal_notif->sync &&
            mvm->queue_sync_cookie != internal_notif->cookie) {
@@ -841,21 +807,19 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
 
        switch (internal_notif->type) {
        case IWL_MVM_RXQ_EMPTY:
-               WARN_ONCE(len != sizeof(*internal_notif),
-                         "invalid empty notification size %d (%d)",
-                         len, (int)sizeof(*internal_notif));
+               WARN_ONCE(len, "invalid empty notification size %d", len);
                break;
        case IWL_MVM_RXQ_NOTIF_DEL_BA:
-               if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
+               if (WARN_ONCE(len != sizeof(struct iwl_mvm_delba_data),
                              "invalid delba notification size %d (%d)",
-                             len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
+                             len, (int)sizeof(struct iwl_mvm_delba_data)))
                        break;
                iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
                break;
        case IWL_MVM_RXQ_NSSN_SYNC:
-               if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
+               if (WARN_ONCE(len != sizeof(struct iwl_mvm_nssn_sync_data),
                              "invalid nssn sync notification size %d (%d)",
-                             len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
+                             len, (int)sizeof(struct iwl_mvm_nssn_sync_data)))
                        break;
                iwl_mvm_nssn_sync(mvm, napi, queue,
                                  (void *)internal_notif->data);
index 3a411bb..f618368 100644 (file)
@@ -2441,12 +2441,12 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 
 static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
 {
-       struct iwl_mvm_rss_sync_notif notif = {
-               .metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA,
-               .metadata.sync = 1,
-               .delba.baid = baid,
+       struct iwl_mvm_delba_data notif = {
+               .baid = baid,
        };
-       iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
+
+       iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NOTIF_DEL_BA, true,
+                                       &notif, sizeof(notif));
 };
 
 static void iwl_mvm_free_reorder(struct iwl_mvm *mvm,
index 35a18b9..32b4d19 100644 (file)
@@ -281,6 +281,36 @@ struct iwl_mvm_key_pn {
        } ____cacheline_aligned_in_smp q[];
 };
 
+/**
+ * enum iwl_mvm_rxq_notif_type - Internal message identifier
+ *
+ * @IWL_MVM_RXQ_EMPTY: empty sync notification
+ * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
+ * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
+ */
+enum iwl_mvm_rxq_notif_type {
+       IWL_MVM_RXQ_EMPTY,
+       IWL_MVM_RXQ_NOTIF_DEL_BA,
+       IWL_MVM_RXQ_NSSN_SYNC,
+};
+
+/**
+ * struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
+ * in &iwl_rxq_sync_cmd. Should be DWORD aligned.
+ * FW is agnostic to the payload, so there are no endianity requirements.
+ *
+ * @type: value from &iwl_mvm_rxq_notif_type
+ * @sync: ctrl path is waiting for all notifications to be received
+ * @cookie: internal cookie to identify old notifications
+ * @data: payload
+ */
+struct iwl_mvm_internal_rxq_notif {
+       u16 type;
+       u16 sync;
+       u32 cookie;
+       u8 data[];
+} __packed;
+
 struct iwl_mvm_delba_data {
        u32 baid;
 } __packed;
@@ -290,14 +320,6 @@ struct iwl_mvm_nssn_sync_data {
        u32 nssn;
 } __packed;
 
-struct iwl_mvm_rss_sync_notif {
-       struct iwl_mvm_internal_rxq_notif metadata;
-       union {
-               struct iwl_mvm_delba_data delba;
-               struct iwl_mvm_nssn_sync_data nssn_sync;
-       };
-} __packed;
-
 /**
  * struct iwl_mvm_rxq_dup_data - per station per rx queue data
  * @last_seq: last sequence per tid for duplicate packet detection