When the firmware misbehaves (according to the driver), we
often either ignore that, or WARN_ON, which is very noisy
but doesn't really help.
Add a little helper macro IWL_FW_CHECK() that can be used
in place of WARN_ON() in conditions, and make it take a
message that's printed in this case. We can also add more
behaviour to this in the future.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230614123446.2e12ac670cea.Ia0198036b7a626876d836bd41a4b2d2b1e65c5ca@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2005-2014, 2018-2019, 2021-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
 void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
                                    u32 timepoint,
                                    u32 timepoint_data);
+
+#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...)                           \
+       IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__)
+
+#define IWL_FW_CHECK(_obj, _cond, _fmt, ...)                           \
+       ({                                                              \
+               bool __cond = (_cond);                                  \
+                                                                       \
+               if (unlikely(__cond))                                   \
+                       IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__);   \
+                                                                       \
+               unlikely(__cond);                                       \
+       })
+
 #endif  /* __iwl_fw_dbg_h__ */
 
                if (rx_h->cmd_id != WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd))
                        continue;
 
-               if (unlikely(pkt_len < rx_h->min_size))
+               if (IWL_FW_CHECK(mvm, pkt_len < rx_h->min_size,
+                                "unexpected notification 0x%04x size %d, need %d\n",
+                                rx_h->cmd_id, pkt_len, rx_h->min_size))
                        return;
 
                if (rx_h->context == RX_HANDLER_SYNC) {
 
        sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
        rcu_read_unlock();
 
-       if (WARN(tid != baid_data->tid ||
-                !(sta_mask & baid_data->sta_mask),
-                "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
-                baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid))
+       if (IWL_FW_CHECK(mvm,
+                        tid != baid_data->tid ||
+                        !(sta_mask & baid_data->sta_mask),
+                        "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
+                        baid, baid_data->sta_mask, baid_data->tid,
+                        sta_mask, tid))
                return false;
 
        nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
 
                u16 tfd_cnt;
                int i;
 
-               if (unlikely(sizeof(*ba_res) > pkt_len))
+               if (IWL_FW_CHECK(mvm, sizeof(*ba_res) > pkt_len,
+                                "short BA notification (%d)\n", pkt_len))
                        return;
 
                sta_id = ba_res->sta_id;
                        (void *)(uintptr_t)ba_res->reduced_txp;
 
                tfd_cnt = le16_to_cpu(ba_res->tfd_cnt);
-               if (!tfd_cnt || struct_size(ba_res, tfd, tfd_cnt) > pkt_len)
+               if (!tfd_cnt)
+                       return;
+
+               if (IWL_FW_CHECK(mvm,
+                                struct_size(ba_res, tfd, tfd_cnt) > pkt_len,
+                                "short BA notification (tfds:%d, size:%d)\n",
+                                tfd_cnt, pkt_len))
                        return;
 
                rcu_read_lock();
 
        rcu_read_lock();
        mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, sta_id);
-       if (WARN_ON_ONCE(!mvmsta)) {
+       if (IWL_FW_CHECK(mvm, !mvmsta,
+                        "invalid STA ID %d in BA notif\n",
+                        sta_id)) {
                rcu_read_unlock();
                return;
        }