return val & 0xFFF;
}
+static inline size_t iwl_mvm_tx_resp_min_len(struct iwl_mvm *mvm,
+ struct iwl_tx_resp *tx_resp)
+{
+ struct agg_tx_status *agg_status =
+ iwl_mvm_get_agg_status(mvm, tx_resp);
+
+ /* The aggregate response ends with a trailing SCD SSN __le32 word. */
+ return (u8 *)(agg_status + tx_resp->frame_count) - (u8 *)tx_resp +
+ sizeof(__le32);
+}
+
static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
int queue = SEQ_TO_QUEUE(sequence);
struct ieee80211_sta *sta;
+ if (WARN_ON_ONCE(iwl_mvm_has_new_tx_api(mvm)))
+ return;
+
if (WARN_ON_ONCE(queue < IWL_MVM_DQA_MIN_DATA_QUEUE &&
(queue != IWL_MVM_DQA_BSS_CLIENT_QUEUE)))
return;
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_tx_resp *tx_resp = (void *)pkt->data;
+ size_t min_len;
+
+ if (IWL_FW_CHECK(mvm, !tx_resp->frame_count,
+ "invalid TX_CMD frame_count %u\n",
+ tx_resp->frame_count))
+ return;
+
+ if (IWL_FW_CHECK(mvm,
+ iwl_mvm_has_new_tx_api(mvm) &&
+ tx_resp->frame_count != 1,
+ "invalid TX_CMD frame_count %u for new TX API\n",
+ tx_resp->frame_count))
+ return;
+
+ min_len = iwl_mvm_tx_resp_min_len(mvm, tx_resp);
+ if (IWL_FW_CHECK(mvm, iwl_rx_packet_payload_len(pkt) < min_len,
+ "invalid TX_CMD len %u (frame_count %u, min %zu)\n",
+ iwl_rx_packet_payload_len(pkt), tx_resp->frame_count,
+ min_len))
+ return;
if (tx_resp->frame_count == 1)
iwl_mvm_rx_tx_cmd_single(mvm, pkt);