* [PATCH 1/3] wifi: iwlwifi: prevent NAPI processing after firmware error
From: Cole Leavitt @ 2026-04-05 5:41 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, miriam.rachel.korenblit, johannes, cole, stable
In-Reply-To: <20260405054145.1064152-1-cole@unwrap.rs>
After a firmware error is detected and STATUS_FW_ERROR is set, NAPI can
still be actively polling or get scheduled from a prior interrupt. The
NAPI poll functions (both legacy and MSIX variants) have no check for
STATUS_FW_ERROR and will continue processing stale RX ring entries from
dying firmware. This can dispatch TX completion notifications containing
corrupt SSN values to iwl_mld_handle_tx_resp_notif(), which passes them
to iwl_trans_reclaim(). If the corrupt SSN causes reclaim to walk TX
queue entries that were already freed by a prior correct reclaim, the
result is an skb use-after-free or double-free.
The race window opens when the MSIX IRQ handler schedules NAPI (lines
2319-2321 in rx.c) before processing the error bit (lines 2382-2396),
or when NAPI is already running on another CPU from a previous interrupt
when STATUS_FW_ERROR gets set on the current CPU.
Add STATUS_FW_ERROR checks to both NAPI poll functions to prevent
processing stale RX data after firmware error, and add early-return
guards in the TX response and compressed BA notification handlers as
defense-in-depth. Each check uses WARN_ONCE to log if the race is
actually hit, which aids diagnosis of the hard-to-reproduce skb
use-after-free reported on Intel BE200.
Note that _iwl_trans_pcie_gen2_stop_device() already calls
iwl_pcie_rx_napi_sync() to quiesce NAPI during device teardown, but that
runs much later in the restart sequence. These checks close the window
between error detection and device stop.
Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver")
Cc: stable@vger.kernel.org
Tested-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Cole Leavitt <cole@unwrap.rs>
---
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 202 +++++------
.../wireless/intel/iwlwifi/pcie/gen1_2/rx.c | 337 +++++++++---------
2 files changed, 273 insertions(+), 266 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index 546d09a38dab..e341d12e5233 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -44,8 +44,8 @@ void iwl_mld_toggle_tx_ant(struct iwl_mld *mld, u8 *ant)
*ant = iwl_mld_next_ant(iwl_mld_get_valid_tx_ant(mld), *ant);
}
-static int
-iwl_mld_get_queue_size(struct iwl_mld *mld, struct ieee80211_txq *txq)
+static int iwl_mld_get_queue_size(struct iwl_mld *mld,
+ struct ieee80211_txq *txq)
{
struct ieee80211_sta *sta = txq->sta;
struct ieee80211_link_sta *link_sta;
@@ -74,9 +74,10 @@ static int iwl_mld_allocate_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
/* We can't know when the station is asleep or awake, so we
* must disable the queue hang detection.
*/
- unsigned int watchdog_timeout = txq->vif->type == NL80211_IFTYPE_AP ?
- IWL_WATCHDOG_DISABLED :
- mld->trans->mac_cfg->base->wd_timeout;
+ unsigned int watchdog_timeout =
+ txq->vif->type == NL80211_IFTYPE_AP ?
+ IWL_WATCHDOG_DISABLED :
+ mld->trans->mac_cfg->base->wd_timeout;
int queue, size;
lockdep_assert_wiphy(mld->wiphy);
@@ -91,9 +92,9 @@ static int iwl_mld_allocate_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
watchdog_timeout);
if (queue >= 0)
- IWL_DEBUG_TX_QUEUES(mld,
- "Enabling TXQ #%d for sta mask 0x%x tid %d\n",
- queue, fw_sta_mask, tid);
+ IWL_DEBUG_TX_QUEUES(
+ mld, "Enabling TXQ #%d for sta mask 0x%x tid %d\n",
+ queue, fw_sta_mask, tid);
return queue;
}
@@ -123,9 +124,8 @@ void iwl_mld_add_txq_list(struct iwl_mld *mld)
while (!list_empty(&mld->txqs_to_add)) {
struct ieee80211_txq *txq;
- struct iwl_mld_txq *mld_txq =
- list_first_entry(&mld->txqs_to_add, struct iwl_mld_txq,
- list);
+ struct iwl_mld_txq *mld_txq = list_first_entry(
+ &mld->txqs_to_add, struct iwl_mld_txq, list);
int failed;
txq = container_of((void *)mld_txq, struct ieee80211_txq,
@@ -149,8 +149,7 @@ void iwl_mld_add_txq_list(struct iwl_mld *mld)
void iwl_mld_add_txqs_wk(struct wiphy *wiphy, struct wiphy_work *wk)
{
- struct iwl_mld *mld = container_of(wk, struct iwl_mld,
- add_txqs_wk);
+ struct iwl_mld *mld = container_of(wk, struct iwl_mld, add_txqs_wk);
/* will reschedule to run after restart */
if (mld->fw_status.in_hw_restart)
@@ -159,8 +158,8 @@ void iwl_mld_add_txqs_wk(struct wiphy *wiphy, struct wiphy_work *wk)
iwl_mld_add_txq_list(mld);
}
-void
-iwl_mld_free_txq(struct iwl_mld *mld, u32 fw_sta_mask, u32 tid, u32 queue_id)
+void iwl_mld_free_txq(struct iwl_mld *mld, u32 fw_sta_mask, u32 tid,
+ u32 queue_id)
{
struct iwl_scd_queue_cfg_cmd remove_cmd = {
.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE),
@@ -193,8 +192,7 @@ void iwl_mld_remove_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
sta_msk = iwl_mld_fw_sta_id_mask(mld, txq->sta);
- tid = txq->tid == IEEE80211_NUM_TIDS ? IWL_MGMT_TID :
- txq->tid;
+ tid = txq->tid == IEEE80211_NUM_TIDS ? IWL_MGMT_TID : txq->tid;
iwl_mld_free_txq(mld, sta_msk, tid, mld_txq->fw_id);
@@ -202,11 +200,9 @@ void iwl_mld_remove_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
mld_txq->status.allocated = false;
}
-#define OPT_HDR(type, skb, off) \
- (type *)(skb_network_header(skb) + (off))
+#define OPT_HDR(type, skb, off) (type *)(skb_network_header(skb) + (off))
-static __le32
-iwl_mld_get_offload_assist(struct sk_buff *skb, bool amsdu)
+static __le32 iwl_mld_get_offload_assist(struct sk_buff *skb, bool amsdu)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
@@ -225,7 +221,7 @@ iwl_mld_get_offload_assist(struct sk_buff *skb, bool amsdu)
* the devices we support has this flags?
*/
if (WARN_ONCE(skb->protocol != htons(ETH_P_IP) &&
- skb->protocol != htons(ETH_P_IPV6),
+ skb->protocol != htons(ETH_P_IPV6),
"No support for requested checksum\n")) {
skb_checksum_help(skb);
goto out;
@@ -306,8 +302,8 @@ static void iwl_mld_get_basic_rates_and_band(struct iwl_mld *mld,
unsigned long *basic_rates,
u8 *band)
{
- u32 link_id = u32_get_bits(info->control.flags,
- IEEE80211_TX_CTRL_MLO_LINK);
+ u32 link_id =
+ u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
*basic_rates = vif->bss_conf.basic_rates;
*band = info->band;
@@ -333,8 +329,7 @@ static void iwl_mld_get_basic_rates_and_band(struct iwl_mld *mld,
}
}
-u8 iwl_mld_get_lowest_rate(struct iwl_mld *mld,
- struct ieee80211_tx_info *info,
+u8 iwl_mld_get_lowest_rate(struct iwl_mld *mld, struct ieee80211_tx_info *info,
struct ieee80211_vif *vif)
{
struct ieee80211_supported_band *sband;
@@ -389,8 +384,8 @@ static u32 iwl_mld_mac80211_rate_idx_to_fw(struct iwl_mld *mld,
/* if the rate isn't a well known legacy rate, take the lowest one */
if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY)
- rate_idx = iwl_mld_get_lowest_rate(mld, info,
- info->control.vif);
+ rate_idx =
+ iwl_mld_get_lowest_rate(mld, info, info->control.vif);
WARN_ON_ONCE(rate_idx < 0);
@@ -404,7 +399,8 @@ static u32 iwl_mld_mac80211_rate_idx_to_fw(struct iwl_mld *mld,
* 0 - 3 for CCK and 0 - 7 for OFDM
*/
rate_plcp = (rate_idx >= IWL_FIRST_OFDM_RATE ?
- rate_idx - IWL_FIRST_OFDM_RATE : rate_idx);
+ rate_idx - IWL_FIRST_OFDM_RATE :
+ rate_idx);
return (u32)rate_plcp | rate_flags;
}
@@ -424,8 +420,7 @@ static u32 iwl_mld_get_tx_ant(struct iwl_mld *mld,
static u32 iwl_mld_get_inject_tx_rate(struct iwl_mld *mld,
struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta,
- __le16 fc)
+ struct ieee80211_sta *sta, __le16 fc)
{
struct ieee80211_tx_rate *rate = &info->control.rates[0];
u32 result;
@@ -492,9 +487,8 @@ static __le32 iwl_mld_get_tx_rate_n_flags(struct iwl_mld *mld,
return iwl_v3_rate_to_v2_v3(rate, mld->fw_rates_ver_3);
}
-static void
-iwl_mld_fill_tx_cmd_hdr(struct iwl_tx_cmd *tx_cmd,
- struct sk_buff *skb, bool amsdu)
+static void iwl_mld_fill_tx_cmd_hdr(struct iwl_tx_cmd *tx_cmd,
+ struct sk_buff *skb, bool amsdu)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -530,10 +524,9 @@ iwl_mld_fill_tx_cmd_hdr(struct iwl_tx_cmd *tx_cmd,
}
}
-static void
-iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb,
- struct iwl_device_tx_cmd *dev_tx_cmd,
- struct ieee80211_sta *sta)
+static void iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb,
+ struct iwl_device_tx_cmd *dev_tx_cmd,
+ struct ieee80211_sta *sta)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -561,8 +554,7 @@ iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb,
rate_n_flags = iwl_mld_get_tx_rate_n_flags(mld, info, sta,
hdr->frame_control);
} else if (!ieee80211_is_data(hdr->frame_control) ||
- (mld_sta &&
- mld_sta->sta_state < IEEE80211_STA_AUTHORIZED)) {
+ (mld_sta && mld_sta->sta_state < IEEE80211_STA_AUTHORIZED)) {
/* These are important frames */
flags |= IWL_TX_FLAGS_HIGH_PRI;
}
@@ -587,8 +579,8 @@ iwl_mld_get_link_from_tx_info(struct ieee80211_tx_info *info)
{
struct iwl_mld_vif *mld_vif =
iwl_mld_vif_from_mac80211(info->control.vif);
- u32 link_id = u32_get_bits(info->control.flags,
- IEEE80211_TX_CTRL_MLO_LINK);
+ u32 link_id =
+ u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
if (link_id == IEEE80211_LINK_UNSPECIFIED) {
if (info->control.vif->active_links)
@@ -600,9 +592,9 @@ iwl_mld_get_link_from_tx_info(struct ieee80211_tx_info *info)
return rcu_dereference(mld_vif->link[link_id]);
}
-static int
-iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
- struct sk_buff *skb)
+static int iwl_mld_get_tx_queue_id(struct iwl_mld *mld,
+ struct ieee80211_txq *txq,
+ struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -686,8 +678,7 @@ iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
return IWL_MLD_INVALID_QUEUE;
}
-static void iwl_mld_probe_resp_set_noa(struct iwl_mld *mld,
- struct sk_buff *skb)
+static void iwl_mld_probe_resp_set_noa(struct iwl_mld *mld, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_mld_link *mld_link =
@@ -709,8 +700,7 @@ static void iwl_mld_probe_resp_set_noa(struct iwl_mld *mld,
if (skb_tailroom(skb) < resp_data->noa_len) {
if (pskb_expand_head(skb, 0, resp_data->noa_len, GFP_ATOMIC)) {
- IWL_ERR(mld,
- "Failed to reallocate probe resp\n");
+ IWL_ERR(mld, "Failed to reallocate probe resp\n");
goto out;
}
}
@@ -770,8 +760,7 @@ static int iwl_mld_tx_mpdu(struct iwl_mld *mld, struct sk_buff *skb,
tid = IWL_TID_NON_QOS;
}
- IWL_DEBUG_TX(mld, "TX TID:%d from Q:%d len %d\n",
- tid, queue, skb->len);
+ IWL_DEBUG_TX(mld, "TX TID:%d from Q:%d len %d\n", tid, queue, skb->len);
/* From now on, we cannot access info->control */
memset(&info->status, 0, sizeof(info->status));
@@ -824,7 +813,7 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
*/
if (skb->protocol == htons(ETH_P_IPV6) &&
((struct ipv6hdr *)skb_network_header(skb))->nexthdr !=
- IPPROTO_TCP) {
+ IPPROTO_TCP) {
netdev_flags &= ~NETIF_F_CSUM_MASK;
return iwl_tx_tso_segment(skb, 1, netdev_flags, mpdus_skbs);
}
@@ -851,7 +840,7 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
num_subframes = sta->max_amsdu_subframes;
tcp_payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) -
- tcp_hdrlen(skb) + skb->data_len;
+ tcp_hdrlen(skb) + skb->data_len;
/* Make sure we have enough TBs for the A-MSDU:
* 2 for each subframe
@@ -893,7 +882,7 @@ static int iwl_mld_tx_tso(struct iwl_mld *mld, struct sk_buff *skb,
return -1;
payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) -
- tcp_hdrlen(skb) + skb->data_len;
+ tcp_hdrlen(skb) + skb->data_len;
if (payload_len <= skb_shinfo(skb)->gso_size)
return iwl_mld_tx_mpdu(mld, skb, txq);
@@ -1011,8 +1000,8 @@ static void iwl_mld_hwrate_to_tx_rate(struct iwl_mld *mld,
{
enum nl80211_band band = info->band;
struct ieee80211_tx_rate *tx_rate = &info->status.rates[0];
- u32 rate_n_flags = iwl_v3_rate_from_v2_v3(rate_n_flags_fw,
- mld->fw_rates_ver_3);
+ u32 rate_n_flags =
+ iwl_v3_rate_from_v2_v3(rate_n_flags_fw, mld->fw_rates_ver_3);
u32 sgi = rate_n_flags & RATE_MCS_SGI_MSK;
u32 chan_width = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
@@ -1042,10 +1031,9 @@ static void iwl_mld_hwrate_to_tx_rate(struct iwl_mld *mld,
tx_rate->idx = RATE_HT_MCS_INDEX(rate_n_flags);
break;
case RATE_MCS_MOD_TYPE_VHT:
- ieee80211_rate_set_vht(tx_rate,
- rate_n_flags & RATE_MCS_CODE_MSK,
- u32_get_bits(rate_n_flags,
- RATE_MCS_NSS_MSK) + 1);
+ ieee80211_rate_set_vht(
+ tx_rate, rate_n_flags & RATE_MCS_CODE_MSK,
+ u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1);
tx_rate->flags |= IEEE80211_TX_RC_VHT_MCS;
break;
case RATE_MCS_MOD_TYPE_HE:
@@ -1056,9 +1044,8 @@ static void iwl_mld_hwrate_to_tx_rate(struct iwl_mld *mld,
tx_rate->idx = 0;
break;
default:
- tx_rate->idx =
- iwl_mld_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
- band);
+ tx_rate->idx = iwl_mld_legacy_hw_idx_to_mac80211_idx(
+ rate_n_flags, band);
break;
}
}
@@ -1082,6 +1069,19 @@ void iwl_mld_handle_tx_resp_notif(struct iwl_mld *mld,
bool mgmt = false;
bool tx_failure = (status & TX_STATUS_MSK) != TX_STATUS_SUCCESS;
+ /* Firmware is dead — the TX response may contain corrupt SSN values
+ * from a dying firmware DMA. Processing it could cause
+ * iwl_trans_reclaim() to free the wrong TX queue entries, leading to
+ * skb use-after-free or double-free.
+ */
+ if (unlikely(test_bit(STATUS_FW_ERROR, &mld->trans->status))) {
+ WARN_ONCE(
+ 1,
+ "iwlwifi: TX resp notif (sta=%d txq=%d) after FW error\n",
+ sta_id, txq_id);
+ return;
+ }
+
if (IWL_FW_CHECK(mld, tx_resp->frame_count != 1,
"Invalid tx_resp notif frame_count (%d)\n",
tx_resp->frame_count))
@@ -1093,8 +1093,8 @@ void iwl_mld_handle_tx_resp_notif(struct iwl_mld *mld,
notif_size, pkt_len))
return;
- ssn = le32_to_cpup((__le32 *)agg_status +
- tx_resp->frame_count) & 0xFFFF;
+ ssn = le32_to_cpup((__le32 *)agg_status + tx_resp->frame_count) &
+ 0xFFFF;
__skb_queue_head_init(&skbs);
@@ -1112,7 +1112,8 @@ void iwl_mld_handle_tx_resp_notif(struct iwl_mld *mld,
memset(&info->status, 0, sizeof(info->status));
- info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED);
+ info->flags &= ~(IEEE80211_TX_STAT_ACK |
+ IEEE80211_TX_STAT_TX_FILTERED);
/* inform mac80211 about what happened with the frame */
switch (status & TX_STATUS_MSK) {
@@ -1149,10 +1150,11 @@ void iwl_mld_handle_tx_resp_notif(struct iwl_mld *mld,
ieee80211_tx_status_skb(mld->hw, skb);
}
- IWL_DEBUG_TX_REPLY(mld,
- "TXQ %d status 0x%08x ssn=%d initial_rate 0x%x retries %d\n",
- txq_id, status, ssn, le32_to_cpu(tx_resp->initial_rate),
- tx_resp->failure_frame);
+ IWL_DEBUG_TX_REPLY(
+ mld,
+ "TXQ %d status 0x%08x ssn=%d initial_rate 0x%x retries %d\n",
+ txq_id, status, ssn, le32_to_cpu(tx_resp->initial_rate),
+ tx_resp->failure_frame);
if (tx_failure && mgmt)
iwl_mld_toggle_tx_ant(mld, &mld->mgmt_tx_ant);
@@ -1168,9 +1170,8 @@ void iwl_mld_handle_tx_resp_notif(struct iwl_mld *mld,
/* This can happen if the TX cmd was sent before pre_rcu_remove
* but the TX response was received after
*/
- IWL_DEBUG_TX_REPLY(mld,
- "Got valid sta_id (%d) but sta is NULL\n",
- sta_id);
+ IWL_DEBUG_TX_REPLY(
+ mld, "Got valid sta_id (%d) but sta is NULL\n", sta_id);
goto out;
}
@@ -1246,8 +1247,7 @@ int iwl_mld_flush_link_sta_txqs(struct iwl_mld *mld, u32 fw_sta_id)
resp_len = iwl_rx_packet_payload_len(cmd.resp_pkt);
if (IWL_FW_CHECK(mld, resp_len != sizeof(*rsp),
- "Invalid TXPATH_FLUSH response len: %d\n",
- resp_len)) {
+ "Invalid TXPATH_FLUSH response len: %d\n", resp_len)) {
ret = -EIO;
goto free_rsp;
}
@@ -1273,16 +1273,14 @@ int iwl_mld_flush_link_sta_txqs(struct iwl_mld *mld, u32 fw_sta_id)
int read_after = le16_to_cpu(queue_info->read_after_flush);
int txq_id = le16_to_cpu(queue_info->queue_num);
- if (IWL_FW_CHECK(mld,
- txq_id >= ARRAY_SIZE(mld->fw_id_to_txq),
+ if (IWL_FW_CHECK(mld, txq_id >= ARRAY_SIZE(mld->fw_id_to_txq),
"Invalid txq id %d\n", txq_id))
continue;
- IWL_DEBUG_TX_QUEUES(mld,
- "tid %d txq_id %d read-before %d read-after %d\n",
- le16_to_cpu(queue_info->tid), txq_id,
- le16_to_cpu(queue_info->read_before_flush),
- read_after);
+ IWL_DEBUG_TX_QUEUES(
+ mld, "tid %d txq_id %d read-before %d read-after %d\n",
+ le16_to_cpu(queue_info->tid), txq_id,
+ le16_to_cpu(queue_info->read_before_flush), read_after);
iwl_mld_tx_reclaim_txq(mld, txq_id, read_after, true);
}
@@ -1312,8 +1310,7 @@ int iwl_mld_ensure_queue(struct iwl_mld *mld, struct ieee80211_txq *txq)
return ret;
}
-int iwl_mld_update_sta_txqs(struct iwl_mld *mld,
- struct ieee80211_sta *sta,
+int iwl_mld_update_sta_txqs(struct iwl_mld *mld, struct ieee80211_sta *sta,
u32 old_sta_mask, u32 new_sta_mask)
{
struct iwl_scd_queue_cfg_cmd cmd = {
@@ -1326,10 +1323,9 @@ int iwl_mld_update_sta_txqs(struct iwl_mld *mld,
for (int tid = 0; tid <= IWL_MAX_TID_COUNT; tid++) {
struct ieee80211_txq *txq =
- sta->txq[tid != IWL_MAX_TID_COUNT ?
- tid : IEEE80211_NUM_TIDS];
- struct iwl_mld_txq *mld_txq =
- iwl_mld_txq_from_mac80211(txq);
+ sta->txq[tid != IWL_MAX_TID_COUNT ? tid :
+ IEEE80211_NUM_TIDS];
+ struct iwl_mld_txq *mld_txq = iwl_mld_txq_from_mac80211(txq);
int ret;
if (!mld_txq->status.allocated)
@@ -1340,10 +1336,9 @@ int iwl_mld_update_sta_txqs(struct iwl_mld *mld,
else
cmd.u.modify.tid = cpu_to_le32(tid);
- ret = iwl_mld_send_cmd_pdu(mld,
- WIDE_ID(DATA_PATH_GROUP,
- SCD_QUEUE_CONFIG_CMD),
- &cmd);
+ ret = iwl_mld_send_cmd_pdu(
+ mld, WIDE_ID(DATA_PATH_GROUP, SCD_QUEUE_CONFIG_CMD),
+ &cmd);
if (ret)
return ret;
}
@@ -1360,27 +1355,32 @@ void iwl_mld_handle_compressed_ba_notif(struct iwl_mld *mld,
u8 sta_id = ba_res->sta_id;
struct ieee80211_link_sta *link_sta;
+ if (unlikely(test_bit(STATUS_FW_ERROR, &mld->trans->status))) {
+ WARN_ONCE(1, "iwlwifi: BA notif (sta=%d) after FW error\n",
+ sta_id);
+ return;
+ }
+
if (!tfd_cnt)
return;
if (IWL_FW_CHECK(mld, struct_size(ba_res, tfd, tfd_cnt) > pkt_len,
- "Short BA notif (tfd_cnt=%d, size:0x%x)\n",
- tfd_cnt, pkt_len))
+ "Short BA notif (tfd_cnt=%d, size:0x%x)\n", tfd_cnt,
+ pkt_len))
return;
- IWL_DEBUG_TX_REPLY(mld,
- "BA notif received from sta_id=%d, flags=0x%x, sent:%d, acked:%d\n",
- sta_id, le32_to_cpu(ba_res->flags),
- le16_to_cpu(ba_res->txed),
- le16_to_cpu(ba_res->done));
+ IWL_DEBUG_TX_REPLY(
+ mld,
+ "BA notif received from sta_id=%d, flags=0x%x, sent:%d, acked:%d\n",
+ sta_id, le32_to_cpu(ba_res->flags), le16_to_cpu(ba_res->txed),
+ le16_to_cpu(ba_res->done));
for (int i = 0; i < tfd_cnt; i++) {
struct iwl_compressed_ba_tfd *ba_tfd = &ba_res->tfd[i];
int txq_id = le16_to_cpu(ba_tfd->q_num);
int index = le16_to_cpu(ba_tfd->tfd_index);
- if (IWL_FW_CHECK(mld,
- txq_id >= ARRAY_SIZE(mld->fw_id_to_txq),
+ if (IWL_FW_CHECK(mld, txq_id >= ARRAY_SIZE(mld->fw_id_to_txq),
"Invalid txq id %d\n", txq_id))
continue;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
index fe263cdc2e4f..554c22777ec1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
@@ -151,8 +151,8 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
} else if (trans->mac_cfg->mq_rx_supported) {
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
- return iwl_poll_prph_bit(trans, RFH_GEN_STATUS,
- RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
+ return iwl_poll_prph_bit(trans, RFH_GEN_STATUS, RXF_DMA_IDLE,
+ RXF_DMA_IDLE, 1000);
} else {
iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG,
@@ -181,8 +181,10 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n",
- reg);
+ IWL_DEBUG_INFO(
+ trans,
+ "Rx queue requesting wakeup, GP1 = 0x%x\n",
+ reg);
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
rxq->need_update = true;
@@ -194,8 +196,8 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
if (!trans->mac_cfg->mq_rx_supported)
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
- iwl_write32(trans, HBUS_TARG_WRPTR, rxq->write_actual |
- HBUS_TARG_WRPTR_RX_Q(rxq->id));
+ iwl_write32(trans, HBUS_TARG_WRPTR,
+ rxq->write_actual | HBUS_TARG_WRPTR_RX_Q(rxq->id));
else
iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id),
rxq->write_actual);
@@ -218,8 +220,7 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans)
}
}
-static void iwl_pcie_restock_bd(struct iwl_trans *trans,
- struct iwl_rxq *rxq,
+static void iwl_pcie_restock_bd(struct iwl_trans *trans, struct iwl_rxq *rxq,
struct iwl_rx_mem_buffer *rxb)
{
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
@@ -242,8 +243,7 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans,
/*
* iwl_pcie_rxmq_restock - restock implementation for multi-queue rx
*/
-static void iwl_pcie_rxmq_restock(struct iwl_trans *trans,
- struct iwl_rxq *rxq)
+static void iwl_pcie_rxmq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rx_mem_buffer *rxb;
@@ -289,8 +289,7 @@ static void iwl_pcie_rxmq_restock(struct iwl_trans *trans,
/*
* iwl_pcie_rxsq_restock - restock implementation for single queue rx
*/
-static void iwl_pcie_rxsq_restock(struct iwl_trans *trans,
- struct iwl_rxq *rxq)
+static void iwl_pcie_rxsq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
struct iwl_rx_mem_buffer *rxb;
@@ -346,8 +345,7 @@ static void iwl_pcie_rxsq_restock(struct iwl_trans *trans,
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-static
-void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
+static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
if (trans->mac_cfg->mq_rx_supported)
iwl_pcie_rxmq_restock(trans, rxq);
@@ -359,8 +357,8 @@ void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
* iwl_pcie_rx_alloc_page - allocates and returns a page.
*
*/
-static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans,
- u32 *offset, gfp_t priority)
+static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, u32 *offset,
+ gfp_t priority)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned int allocsize = PAGE_SIZE << trans_pcie->rx_page_order;
@@ -399,8 +397,7 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans,
* buffers.
*/
if (!(gfp_mask & __GFP_NOWARN) && net_ratelimit())
- IWL_CRIT(trans,
- "Failed to alloc_pages\n");
+ IWL_CRIT(trans, "Failed to alloc_pages\n");
return NULL;
}
@@ -464,10 +461,9 @@ void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
rxb->page = page;
rxb->offset = offset;
/* Get physical address of the RB */
- rxb->page_dma =
- dma_map_page(trans->dev, page, rxb->offset,
- trans_pcie->rx_buf_bytes,
- DMA_FROM_DEVICE);
+ rxb->page_dma = dma_map_page(trans->dev, page, rxb->offset,
+ trans_pcie->rx_buf_bytes,
+ DMA_FROM_DEVICE);
if (dma_mapping_error(trans->dev, rxb->page_dma)) {
rxb->page = NULL;
spin_lock_bh(&rxq->lock);
@@ -579,9 +575,10 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
if (!pending) {
pending = atomic_read(&rba->req_pending);
if (pending)
- IWL_DEBUG_TPT(trans,
- "Got more pending allocation requests = %d\n",
- pending);
+ IWL_DEBUG_TPT(
+ trans,
+ "Got more pending allocation requests = %d\n",
+ pending);
}
spin_lock_bh(&rba->lock);
@@ -592,7 +589,6 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
spin_unlock_bh(&rba->lock);
atomic_inc(&rba->req_ready);
-
}
spin_lock_bh(&rba->lock);
@@ -634,9 +630,8 @@ static void iwl_pcie_rx_allocator_get(struct iwl_trans *trans,
spin_lock(&rba->lock);
for (i = 0; i < RX_CLAIM_REQ_ALLOC; i++) {
/* Get next free Rx buffer, remove it from free list */
- struct iwl_rx_mem_buffer *rxb =
- list_first_entry(&rba->rbd_allocated,
- struct iwl_rx_mem_buffer, list);
+ struct iwl_rx_mem_buffer *rxb = list_first_entry(
+ &rba->rbd_allocated, struct iwl_rx_mem_buffer, list);
list_move(&rxb->list, &rxq->rx_free);
}
@@ -661,8 +656,8 @@ static int iwl_pcie_free_bd_size(struct iwl_trans *trans)
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return sizeof(struct iwl_rx_transfer_desc);
- return trans->mac_cfg->mq_rx_supported ?
- sizeof(__le64) : sizeof(__le32);
+ return trans->mac_cfg->mq_rx_supported ? sizeof(__le64) :
+ sizeof(__le32);
}
static int iwl_pcie_used_bd_size(struct iwl_trans *trans)
@@ -676,14 +671,12 @@ static int iwl_pcie_used_bd_size(struct iwl_trans *trans)
return sizeof(__le32);
}
-static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
- struct iwl_rxq *rxq)
+static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
int free_size = iwl_pcie_free_bd_size(trans);
if (rxq->bd)
- dma_free_coherent(trans->dev,
- free_size * rxq->queue_size,
+ dma_free_coherent(trans->dev, free_size * rxq->queue_size,
rxq->bd, rxq->bd_dma);
rxq->bd_dma = 0;
rxq->bd = NULL;
@@ -694,7 +687,7 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
if (rxq->used_bd)
dma_free_coherent(trans->dev,
iwl_pcie_used_bd_size(trans) *
- rxq->queue_size,
+ rxq->queue_size,
rxq->used_bd, rxq->used_bd_dma);
rxq->used_bd_dma = 0;
rxq->used_bd = NULL;
@@ -702,8 +695,8 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
static size_t iwl_pcie_rb_stts_size(struct iwl_trans *trans)
{
- bool use_rx_td = (trans->mac_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210);
+ bool use_rx_td =
+ (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210);
if (use_rx_td)
return sizeof(__le16);
@@ -711,8 +704,7 @@ static size_t iwl_pcie_rb_stts_size(struct iwl_trans *trans)
return sizeof(struct iwl_rb_status);
}
-static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
- struct iwl_rxq *rxq)
+static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
@@ -738,11 +730,9 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
goto err;
if (trans->mac_cfg->mq_rx_supported) {
- rxq->used_bd = dma_alloc_coherent(dev,
- iwl_pcie_used_bd_size(trans) *
- rxq->queue_size,
- &rxq->used_bd_dma,
- GFP_KERNEL);
+ rxq->used_bd = dma_alloc_coherent(
+ dev, iwl_pcie_used_bd_size(trans) * rxq->queue_size,
+ &rxq->used_bd_dma, GFP_KERNEL);
if (!rxq->used_bd)
goto err;
}
@@ -774,8 +764,8 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
return -EINVAL;
trans_pcie->rxq = kzalloc_objs(struct iwl_rxq, trans->info.num_rxqs);
- trans_pcie->rx_pool = kzalloc_objs(trans_pcie->rx_pool[0],
- RX_POOL_SIZE(trans_pcie->num_rx_bufs));
+ trans_pcie->rx_pool = kzalloc_objs(
+ trans_pcie->rx_pool[0], RX_POOL_SIZE(trans_pcie->num_rx_bufs));
trans_pcie->global_table =
kzalloc_objs(trans_pcie->global_table[0],
RX_POOL_SIZE(trans_pcie->num_rx_bufs));
@@ -791,11 +781,9 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
* Allocate the driver's pointer to receive buffer status.
* Allocate for all queues continuously (HW requirement).
*/
- trans_pcie->base_rb_stts =
- dma_alloc_coherent(trans->dev,
- rb_stts_size * trans->info.num_rxqs,
- &trans_pcie->base_rb_stts_dma,
- GFP_KERNEL);
+ trans_pcie->base_rb_stts = dma_alloc_coherent(
+ trans->dev, rb_stts_size * trans->info.num_rxqs,
+ &trans_pcie->base_rb_stts_dma, GFP_KERNEL);
if (!trans_pcie->base_rb_stts) {
ret = -ENOMEM;
goto err;
@@ -868,8 +856,7 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
(u32)(rxq->bd_dma >> 8));
/* Tell device where in DRAM to update its Rx status */
- iwl_write32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG,
- rxq->rb_stts_dma >> 4);
+ iwl_write32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4);
/* Enable Rx DMA
* FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
@@ -881,11 +868,12 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
*/
iwl_write32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
- FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
- FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
- rb_size |
- (RX_RB_TIMEOUT << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
- (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+ FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
+ FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+ rb_size |
+ (RX_RB_TIMEOUT
+ << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
+ (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
iwl_trans_release_nic_access(trans);
@@ -931,16 +919,13 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
for (i = 0; i < trans->info.num_rxqs; i++) {
/* Tell device where to find RBD free table in DRAM */
- iwl_write_prph64_no_grab(trans,
- RFH_Q_FRBDCB_BA_LSB(i),
+ iwl_write_prph64_no_grab(trans, RFH_Q_FRBDCB_BA_LSB(i),
trans_pcie->rxq[i].bd_dma);
/* Tell device where to find RBD used table in DRAM */
- iwl_write_prph64_no_grab(trans,
- RFH_Q_URBDCB_BA_LSB(i),
+ iwl_write_prph64_no_grab(trans, RFH_Q_URBDCB_BA_LSB(i),
trans_pcie->rxq[i].used_bd_dma);
/* Tell device where in DRAM to update its Rx status */
- iwl_write_prph64_no_grab(trans,
- RFH_Q_URBD_STTS_WPTR_LSB(i),
+ iwl_write_prph64_no_grab(trans, RFH_Q_URBD_STTS_WPTR_LSB(i),
trans_pcie->rxq[i].rb_stts_dma);
/* Reset device indice tables */
iwl_write_prph_no_grab(trans, RFH_Q_FRBDCB_WIDX(i), 0);
@@ -959,23 +944,24 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
*/
iwl_write_prph_no_grab(trans, RFH_RXF_DMA_CFG,
RFH_DMA_EN_ENABLE_VAL | rb_size |
- RFH_RXF_DMA_MIN_RB_4_8 |
- RFH_RXF_DMA_DROP_TOO_LARGE_MASK |
- RFH_RXF_DMA_RBDCB_SIZE_512);
+ RFH_RXF_DMA_MIN_RB_4_8 |
+ RFH_RXF_DMA_DROP_TOO_LARGE_MASK |
+ RFH_RXF_DMA_RBDCB_SIZE_512);
/*
* Activate DMA snooping.
* Set RX DMA chunk size to 64B for IOSF and 128B for PCIe
* Default queue is 0
*/
- iwl_write_prph_no_grab(trans, RFH_GEN_CFG,
- RFH_GEN_CFG_RFH_DMA_SNOOP |
- RFH_GEN_CFG_VAL(DEFAULT_RXQ_NUM, 0) |
- RFH_GEN_CFG_SERVICE_DMA_SNOOP |
- RFH_GEN_CFG_VAL(RB_CHUNK_SIZE,
- trans->mac_cfg->integrated ?
- RFH_GEN_CFG_RB_CHUNK_SIZE_64 :
- RFH_GEN_CFG_RB_CHUNK_SIZE_128));
+ iwl_write_prph_no_grab(
+ trans, RFH_GEN_CFG,
+ RFH_GEN_CFG_RFH_DMA_SNOOP |
+ RFH_GEN_CFG_VAL(DEFAULT_RXQ_NUM, 0) |
+ RFH_GEN_CFG_SERVICE_DMA_SNOOP |
+ RFH_GEN_CFG_VAL(RB_CHUNK_SIZE,
+ trans->mac_cfg->integrated ?
+ RFH_GEN_CFG_RB_CHUNK_SIZE_64 :
+ RFH_GEN_CFG_RB_CHUNK_SIZE_128));
/* Enable the relevant rx queues */
iwl_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, enabled);
@@ -997,7 +983,8 @@ void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget);
-static inline struct iwl_trans_pcie *iwl_netdev_to_trans_pcie(struct net_device *dev)
+static inline struct iwl_trans_pcie *
+iwl_netdev_to_trans_pcie(struct net_device *dev)
{
return *(struct iwl_trans_pcie **)netdev_priv(dev);
}
@@ -1012,10 +999,21 @@ static int iwl_pcie_napi_poll(struct napi_struct *napi, int budget)
trans_pcie = iwl_netdev_to_trans_pcie(napi->dev);
trans = trans_pcie->trans;
+ /* Stop processing RX if firmware has crashed. Stale notifications
+ * from dying firmware (e.g. TX completions with corrupt SSN values)
+ * can cause use-after-free in reclaim paths.
+ */
+ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) {
+ WARN_ONCE(1, "iwlwifi: NAPI poll[%d] invoked after FW error\n",
+ rxq->id);
+ napi_complete_done(napi, 0);
+ return 0;
+ }
+
ret = iwl_pcie_rx_handle(trans, rxq->id, budget);
- IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n",
- rxq->id, ret, budget);
+ IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n", rxq->id, ret,
+ budget);
if (ret < budget) {
spin_lock(&trans_pcie->irq_lock);
@@ -1039,6 +1037,15 @@ static int iwl_pcie_napi_poll_msix(struct napi_struct *napi, int budget)
trans_pcie = iwl_netdev_to_trans_pcie(napi->dev);
trans = trans_pcie->trans;
+ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) {
+ WARN_ONCE(
+ 1,
+ "iwlwifi: NAPI MSIX poll[%d] invoked after FW error\n",
+ rxq->id);
+ napi_complete_done(napi, 0);
+ return 0;
+ }
+
ret = iwl_pcie_rx_handle(trans, rxq->id, budget);
IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n", rxq->id, ret,
budget);
@@ -1121,30 +1128,31 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
memset(rxq->rb_stts, 0,
(trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_AX210) ?
- sizeof(__le16) : sizeof(struct iwl_rb_status));
+ sizeof(__le16) :
+ sizeof(struct iwl_rb_status));
iwl_pcie_rx_init_rxb_lists(rxq);
spin_unlock_bh(&rxq->lock);
if (!rxq->napi.poll) {
- int (*poll)(struct napi_struct *, int) = iwl_pcie_napi_poll;
+ int (*poll)(struct napi_struct *, int) =
+ iwl_pcie_napi_poll;
if (trans_pcie->msix_enabled)
poll = iwl_pcie_napi_poll_msix;
- netif_napi_add(trans_pcie->napi_dev, &rxq->napi,
- poll);
+ netif_napi_add(trans_pcie->napi_dev, &rxq->napi, poll);
napi_enable(&rxq->napi);
}
-
}
/* move the pool to the default queue and allocator ownerships */
queue_size = trans->mac_cfg->mq_rx_supported ?
- trans_pcie->num_rx_bufs - 1 : RX_QUEUE_SIZE;
- allocator_pool_size = trans->info.num_rxqs *
- (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC);
+ trans_pcie->num_rx_bufs - 1 :
+ RX_QUEUE_SIZE;
+ allocator_pool_size =
+ trans->info.num_rxqs * (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC);
num_alloc = queue_size + allocator_pool_size;
for (i = 0; i < num_alloc; i++) {
@@ -1291,11 +1299,9 @@ static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans,
}
}
-static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
- struct iwl_rxq *rxq,
- struct iwl_rx_mem_buffer *rxb,
- bool emergency,
- int i)
+static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, struct iwl_rxq *rxq,
+ struct iwl_rx_mem_buffer *rxb, bool emergency,
+ int i)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
@@ -1330,19 +1336,21 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
}
WARN((le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_RXQ_MASK) >>
- FH_RSCSR_RXQ_POS != rxq->id,
+ FH_RSCSR_RXQ_POS !=
+ rxq->id,
"frame on invalid queue - is on %d and indicates %d\n",
rxq->id,
(le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_RXQ_MASK) >>
- FH_RSCSR_RXQ_POS);
+ FH_RSCSR_RXQ_POS);
- IWL_DEBUG_RX(trans,
- "Q %d: cmd at offset %d: %s (%.2x.%2x, seq 0x%x)\n",
- rxq->id, offset,
- iwl_get_cmd_string(trans,
- WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)),
- pkt->hdr.group_id, pkt->hdr.cmd,
- le16_to_cpu(pkt->hdr.sequence));
+ IWL_DEBUG_RX(
+ trans,
+ "Q %d: cmd at offset %d: %s (%.2x.%2x, seq 0x%x)\n",
+ rxq->id, offset,
+ iwl_get_cmd_string(trans, WIDE_ID(pkt->hdr.group_id,
+ pkt->hdr.cmd)),
+ pkt->hdr.group_id, pkt->hdr.cmd,
+ le16_to_cpu(pkt->hdr.sequence));
len = iwl_rx_packet_len(pkt);
len += sizeof(u32); /* account for status word */
@@ -1367,7 +1375,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
for (i = 0; i < trans->conf.n_no_reclaim_cmds; i++) {
if (trans->conf.no_reclaim_cmds[i] ==
- pkt->hdr.cmd) {
+ pkt->hdr.cmd) {
reclaim = false;
break;
}
@@ -1375,11 +1383,10 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
}
if (rxq->id == IWL_DEFAULT_RX_QUEUE)
- iwl_op_mode_rx(trans->op_mode, &rxq->napi,
- &rxcb);
+ iwl_op_mode_rx(trans->op_mode, &rxq->napi, &rxcb);
else
- iwl_op_mode_rx_rss(trans->op_mode, &rxq->napi,
- &rxcb, rxq->id);
+ iwl_op_mode_rx_rss(trans->op_mode, &rxq->napi, &rxcb,
+ rxq->id);
/*
* After here, we should always check rxcb._page_stolen,
@@ -1419,10 +1426,9 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
* SKBs that fail to Rx correctly, add them back into the
* rx_free list for reuse later. */
if (rxb->page != NULL) {
- rxb->page_dma =
- dma_map_page(trans->dev, rxb->page, rxb->offset,
- trans_pcie->rx_buf_bytes,
- DMA_FROM_DEVICE);
+ rxb->page_dma = dma_map_page(trans->dev, rxb->page, rxb->offset,
+ trans_pcie->rx_buf_bytes,
+ DMA_FROM_DEVICE);
if (dma_mapping_error(trans->dev, rxb->page_dma)) {
/*
* free the page(s) as well to not break
@@ -1534,9 +1540,10 @@ static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget)
!emergency)) {
iwl_pcie_rx_move_to_allocator(rxq, rba);
emergency = true;
- IWL_DEBUG_TPT(trans,
- "RX path is in emergency. Pending allocations %d\n",
- rb_pending_alloc);
+ IWL_DEBUG_TPT(
+ trans,
+ "RX path is in emergency. Pending allocations %d\n",
+ rb_pending_alloc);
}
IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i);
@@ -1585,9 +1592,10 @@ static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget)
if (count == 8) {
count = 0;
if (rb_pending_alloc < rxq->queue_size / 3) {
- IWL_DEBUG_TPT(trans,
- "RX path exited emergency. Pending allocations %d\n",
- rb_pending_alloc);
+ IWL_DEBUG_TPT(
+ trans,
+ "RX path exited emergency. Pending allocations %d\n",
+ rb_pending_alloc);
emergency = false;
}
@@ -1682,9 +1690,9 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
if (trans->cfg->internal_wimax_coex &&
!trans->mac_cfg->base->apmg_not_supported &&
(!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) &
- APMS_CLK_VAL_MRB_FUNC_MODE) ||
+ APMS_CLK_VAL_MRB_FUNC_MODE) ||
(iwl_read_prph(trans, APMG_PS_CTRL_REG) &
- APMG_PS_CTRL_VAL_RESET_REQ))) {
+ APMG_PS_CTRL_VAL_RESET_REQ))) {
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
iwl_op_mode_wimax_active(trans->op_mode);
wake_up(&trans_pcie->wait_command_queue);
@@ -1730,9 +1738,9 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
}
/* a device (PCI-E) page is 4096 bytes long */
-#define ICT_SHIFT 12
-#define ICT_SIZE (1 << ICT_SHIFT)
-#define ICT_COUNT (ICT_SIZE / sizeof(u32))
+#define ICT_SHIFT 12
+#define ICT_SIZE (1 << ICT_SHIFT)
+#define ICT_COUNT (ICT_SIZE / sizeof(u32))
/* interrupt handler using ict table, with this interrupt driver will
* stop using INTA register to get device's interrupt, reading this register
@@ -1766,7 +1774,7 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
do {
val |= read;
IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
- trans_pcie->ict_index, read);
+ trans_pcie->ict_index, read);
trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
trans_pcie->ict_index =
((trans_pcie->ict_index + 1) & (ICT_COUNT - 1));
@@ -1822,8 +1830,7 @@ void iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans, bool from_irq)
mutex_unlock(&trans_pcie->mutex);
if (hw_rfkill) {
- if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
- &trans->status))
+ if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status))
IWL_DEBUG_RF_KILL(trans,
"Rfkill while SYNC HCMD in flight\n");
wake_up(&trans_pcie->wait_command_queue);
@@ -1866,9 +1873,8 @@ static void iwl_trans_pcie_handle_reset_interrupt(struct iwl_trans *trans)
}
fallthrough;
case CSR_IPC_STATE_RESET_NONE:
- IWL_FW_CHECK_FAILED(trans,
- "Invalid reset interrupt (state=%d)!\n",
- state);
+ IWL_FW_CHECK_FAILED(
+ trans, "Invalid reset interrupt (state=%d)!\n", state);
break;
case CSR_IPC_STATE_RESET_TOP_FOLLOWER:
if (trans_pcie->fw_reset_state == FW_RESET_REQUESTED) {
@@ -1909,11 +1915,12 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
inta = iwl_pcie_int_cause_non_ict(trans);
if (iwl_have_debug_level(IWL_DL_ISR)) {
- IWL_DEBUG_ISR(trans,
- "ISR inta 0x%08x, enabled 0x%08x(sw), enabled(hw) 0x%08x, fh 0x%08x\n",
- inta, trans_pcie->inta_mask,
- iwl_read32(trans, CSR_INT_MASK),
- iwl_read32(trans, CSR_FH_INT_STATUS));
+ IWL_DEBUG_ISR(
+ trans,
+ "ISR inta 0x%08x, enabled 0x%08x(sw), enabled(hw) 0x%08x, fh 0x%08x\n",
+ inta, trans_pcie->inta_mask,
+ iwl_read32(trans, CSR_INT_MASK),
+ iwl_read32(trans, CSR_FH_INT_STATUS));
if (inta & (~trans_pcie->inta_mask))
IWL_DEBUG_ISR(trans,
"We got a masked interrupt (0x%08x)\n",
@@ -1964,8 +1971,8 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
iwl_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask);
if (iwl_have_debug_level(IWL_DL_ISR))
- IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
- inta, iwl_read32(trans, CSR_INT_MASK));
+ IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", inta,
+ iwl_read32(trans, CSR_INT_MASK));
spin_unlock_bh(&trans_pcie->irq_lock);
@@ -1986,8 +1993,9 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
- IWL_DEBUG_ISR(trans,
- "Scheduler finished to transmit the frame/frames.\n");
+ IWL_DEBUG_ISR(
+ trans,
+ "Scheduler finished to transmit the frame/frames.\n");
isr_stats->sch++;
}
@@ -2029,8 +2037,10 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
/* Error detected by uCode */
if (inta & CSR_INT_BIT_SW_ERR) {
- IWL_ERR(trans, "Microcode SW error detected. "
- " Restarting 0x%X.\n", inta);
+ IWL_ERR(trans,
+ "Microcode SW error detected. "
+ " Restarting 0x%X.\n",
+ inta);
isr_stats->sw++;
if (trans_pcie->fw_reset_state == FW_RESET_REQUESTED) {
trans_pcie->fw_reset_state = FW_RESET_ERROR;
@@ -2055,18 +2065,17 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
/* All uCode command responses, including Tx command responses,
* Rx "responses" (frame-received notification), and other
* notifications from uCode come through here*/
- if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
- CSR_INT_BIT_RX_PERIODIC)) {
+ if (inta &
+ (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | CSR_INT_BIT_RX_PERIODIC)) {
IWL_DEBUG_ISR(trans, "Rx interrupt\n");
if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
iwl_write32(trans, CSR_FH_INT_STATUS,
- CSR_FH_INT_RX_MASK);
+ CSR_FH_INT_RX_MASK);
}
if (inta & CSR_INT_BIT_RX_PERIODIC) {
handled |= CSR_INT_BIT_RX_PERIODIC;
- iwl_write32(trans,
- CSR_INT, CSR_INT_BIT_RX_PERIODIC);
+ iwl_write32(trans, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
}
/* Sending RX interrupt require many steps to be done in the
* device:
@@ -2080,8 +2089,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
*/
/* Disable periodic interrupt; we use it as just a one-shot. */
- iwl_write8(trans, CSR_INT_PERIODIC_REG,
- CSR_INT_PERIODIC_DIS);
+ iwl_write8(trans, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS);
/*
* Enable periodic interrupt in 8 msec only if we received
@@ -2164,8 +2172,7 @@ void iwl_pcie_free_ict(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (trans_pcie->ict_tbl) {
- dma_free_coherent(trans->dev, ICT_SIZE,
- trans_pcie->ict_tbl,
+ dma_free_coherent(trans->dev, ICT_SIZE, trans_pcie->ict_tbl,
trans_pcie->ict_tbl_dma);
trans_pcie->ict_tbl = NULL;
trans_pcie->ict_tbl_dma = 0;
@@ -2181,9 +2188,8 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- trans_pcie->ict_tbl =
- dma_alloc_coherent(trans->dev, ICT_SIZE,
- &trans_pcie->ict_tbl_dma, GFP_KERNEL);
+ trans_pcie->ict_tbl = dma_alloc_coherent(
+ trans->dev, ICT_SIZE, &trans_pcie->ict_tbl_dma, GFP_KERNEL);
if (!trans_pcie->ict_tbl)
return -ENOMEM;
@@ -2214,8 +2220,7 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans)
val = trans_pcie->ict_tbl_dma >> ICT_SHIFT;
- val |= CSR_DRAM_INT_TBL_ENABLE |
- CSR_DRAM_INIT_TBL_WRAP_CHECK |
+ val |= CSR_DRAM_INT_TBL_ENABLE | CSR_DRAM_INIT_TBL_WRAP_CHECK |
CSR_DRAM_INIT_TBL_WRITE_POINTER;
IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val);
@@ -2298,10 +2303,11 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
}
if (iwl_have_debug_level(IWL_DL_ISR)) {
- IWL_DEBUG_ISR(trans,
- "ISR[%d] inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
- entry->entry, inta_fh, trans_pcie->fh_mask,
- iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD));
+ IWL_DEBUG_ISR(
+ trans,
+ "ISR[%d] inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
+ entry->entry, inta_fh, trans_pcie->fh_mask,
+ iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD));
if (inta_fh & ~trans_pcie->fh_mask)
IWL_DEBUG_ISR(trans,
"We got a masked interrupt (0x%08x)\n",
@@ -2400,10 +2406,11 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
/* After checking FH register check HW register */
if (iwl_have_debug_level(IWL_DL_ISR)) {
- IWL_DEBUG_ISR(trans,
- "ISR[%d] inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
- entry->entry, inta_hw, trans_pcie->hw_mask,
- iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD));
+ IWL_DEBUG_ISR(
+ trans,
+ "ISR[%d] inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
+ entry->entry, inta_hw, trans_pcie->hw_mask,
+ iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD));
if (inta_hw & ~trans_pcie->hw_mask)
IWL_DEBUG_ISR(trans,
"We got a masked interrupt 0x%08x\n",
@@ -2433,9 +2440,10 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
if (sleep_notif == IWL_D3_SLEEP_STATUS_SUSPEND ||
sleep_notif == IWL_D3_SLEEP_STATUS_RESUME) {
- IWL_DEBUG_ISR(trans,
- "Sx interrupt: sleep notification = 0x%x\n",
- sleep_notif);
+ IWL_DEBUG_ISR(
+ trans,
+ "Sx interrupt: sleep notification = 0x%x\n",
+ sleep_notif);
if (trans_pcie->sx_state == IWL_SX_WAITING) {
trans_pcie->sx_state = IWL_SX_COMPLETE;
wake_up(&trans_pcie->sx_waitq);
@@ -2465,8 +2473,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
iwl_pcie_handle_rfkill_irq(trans, true);
if (inta_hw & MSIX_HW_INT_CAUSES_REG_HW_ERR) {
- IWL_ERR(trans,
- "Hardware error detected. Restarting.\n");
+ IWL_ERR(trans, "Hardware error detected. Restarting.\n");
isr_stats->hw++;
trans->dbg.hw_error = true;
--
2.52.0
^ permalink raw reply related
* [PATCH 2/3] wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is disabled
From: Cole Leavitt @ 2026-04-05 5:41 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, miriam.rachel.korenblit, johannes, cole
In-Reply-To: <20260405054145.1064152-1-cole@unwrap.rs>
When the TLC notification disables AMSDU for a TID, the MLD driver sets
max_tid_amsdu_len to the sentinel value 1. The TSO segmentation path in
iwl_mld_tx_tso_segment() checks for zero but not for this sentinel,
allowing it to reach the num_subframes calculation:
num_subframes = (max_tid_amsdu_len + pad) / (subf_len + pad)
= (1 + 2) / (1534 + 2) = 0
This zero propagates to iwl_tx_tso_segment() which sets:
gso_size = num_subframes * mss = 0
Calling skb_gso_segment() with gso_size=0 creates over 32000 tiny
segments from a single GSO skb. This floods the TX ring with ~1024
micro-frames (the rest are purged), creating a massive burst of TX
completion events that can lead to memory corruption and a subsequent
use-after-free in TCP's retransmit queue (refcount underflow in
tcp_shifted_skb, NULL deref in tcp_rack_detect_loss).
The MVM driver is immune because it checks mvmsta->amsdu_enabled before
reaching the num_subframes calculation. The MLD driver has no equivalent
bitmap check and relies solely on max_tid_amsdu_len, which does not
catch the sentinel value.
Fix this by detecting the sentinel value (max_tid_amsdu_len == 1) at the
existing check and falling back to non-AMSDU TSO segmentation. Also add
a WARN_ON_ONCE guard after the num_subframes division as defense-in-depth
to catch any future code paths that produce zero through a different
mechanism.
Suggested-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver")
Signed-off-by: Cole Leavitt <cole@unwrap.rs>
---
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index e341d12e5233..8af58aabcd68 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -823,7 +823,7 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
return -EINVAL;
max_tid_amsdu_len = sta->cur->max_tid_amsdu_len[tid];
- if (!max_tid_amsdu_len)
+ if (!max_tid_amsdu_len || max_tid_amsdu_len == 1)
return iwl_tx_tso_segment(skb, 1, netdev_flags, mpdus_skbs);
/* Sub frame header + SNAP + IP header + TCP header + MSS */
@@ -835,6 +835,9 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
*/
num_subframes = (max_tid_amsdu_len + pad) / (subf_len + pad);
+ if (WARN_ON_ONCE(!num_subframes))
+ return iwl_tx_tso_segment(skb, 1, netdev_flags, mpdus_skbs);
+
if (sta->max_amsdu_subframes &&
num_subframes > sta->max_amsdu_subframes)
num_subframes = sta->max_amsdu_subframes;
--
2.52.0
^ permalink raw reply related
* [PATCH v2 0/3] wifi: iwlwifi: mld: fix UAF and soft lockup on firmware error
From: Cole Leavitt @ 2026-04-05 5:41 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, miriam.rachel.korenblit, johannes, cole
Three fixes for the iwlmld sub-driver addressing use-after-free,
TSO segmentation explosion, and soft lockups during firmware error
recovery on Intel BE200 (WiFi7).
1/3 closes the NAPI race window where stale RX data from dying
firmware reaches the TX completion handlers, causing corrupt SSN
values to trigger skb use-after-free in iwl_trans_reclaim().
Ben Greear confirmed the WARN_ONCE fires on his test systems.
2/3 fixes the TSO segmentation explosion when AMSDU is disabled
for a TID. The TLC notification sets max_tid_amsdu_len to the
sentinel value 1, which slips past the existing zero check and
produces num_subframes=0, causing skb_gso_segment() to create
32000+ tiny segments. Revised per Miriam Korenblit's feedback to
check for the sentinel value directly and add a WARN_ON_ONCE
guard after the division as defense-in-depth.
3/3 adds STATUS_FW_ERROR checks in the TX pull path to stop
feeding frames to dead firmware. Revised per Johannes Berg's
feedback to use status bit checks instead of stop_queues/wake_queues,
which doesn't interact well with TXQ-based APIs.
Changes since v1:
- 1/3: Added Tested-by from Ben Greear
- 2/3: Check max_tid_amsdu_len == 1 (sentinel) instead of
guarding !num_subframes after division; added WARN_ON_ONCE
defense-in-depth (Suggested-by: Miriam Korenblit)
- 3/3: Replaced ieee80211_stop_queues()/wake_queues() with
STATUS_FW_ERROR checks in TX pull path (per Johannes Berg)
Cole Leavitt (3):
wifi: iwlwifi: prevent NAPI processing after firmware error
wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is
disabled
wifi: iwlwifi: mld: skip TX when firmware is dead
.../net/wireless/intel/iwlwifi/mld/mac80211.c | 4 +
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 210 +++++------
.../wireless/intel/iwlwifi/pcie/gen1_2/rx.c | 337 +++++++++---------
3 files changed, 284 insertions(+), 267 deletions(-)
base-commit: 3aae9383f42f687221c011d7ee87529398e826b3
--
2.52.0
^ permalink raw reply
* [PATCH 3/3] wifi: iwlwifi: mld: skip TX when firmware is dead
From: Cole Leavitt @ 2026-04-05 5:41 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, miriam.rachel.korenblit, johannes, cole
In-Reply-To: <20260405054145.1064152-1-cole@unwrap.rs>
When firmware encounters an error, STATUS_FW_ERROR is set but the
mac80211 TX path continues pulling frames from TXQs. Each frame
fails at iwl_trans_tx() which checks STATUS_FW_ERROR and returns
-EIO, but iwl_mld_tx_from_txq() keeps looping over every queued
frame. This burns CPU in a tight loop on dead firmware and can
cause soft lockups during firmware error recovery.
Add a STATUS_FW_ERROR check at the top of iwl_mld_tx_from_txq()
to stop pulling frames from mac80211 TXQs when firmware is dead.
Also guard iwl_mld_mac80211_tx() which bypasses the TXQ path
entirely and would otherwise continue feeding frames to dead
firmware.
Once STATUS_FW_ERROR is cleared during firmware restart, TX
resumes naturally with no explicit wake needed.
Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver")
Signed-off-by: Cole Leavitt <cole@unwrap.rs>
---
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 4 ++++
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 3 +++
2 files changed, 7 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 71a9a72c9ac0..0df3be3089c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -519,6 +519,10 @@ iwl_mld_mac80211_tx(struct ieee80211_hw *hw,
u32 link_id = u32_get_bits(info->control.flags,
IEEE80211_TX_CTRL_MLO_LINK);
+ if (unlikely(test_bit(STATUS_FW_ERROR, &mld->trans->status))) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
/* In AP mode, mgmt frames are sent on the bcast station,
* so the FW can't translate the MLD addr to the link addr. Do it here
*/
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index 8af58aabcd68..33bd2e336166 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -962,6 +962,9 @@ void iwl_mld_tx_from_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
struct sk_buff *skb = NULL;
u8 zero_addr[ETH_ALEN] = {};
+ if (unlikely(test_bit(STATUS_FW_ERROR, &mld->trans->status)))
+ return;
+
/*
* No need for threads to be pending here, they can leave the first
* taker all the work.
--
2.52.0
^ permalink raw reply related
* [PATCH wireless-next 6/6] crypto: Remove michael_mic from crypto_shash API
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
In-Reply-To: <20260405052734.130368-1-ebiggers@kernel.org>
Remove the "michael_mic" crypto_shash algorithm, since it's no longer
used. Its only users were wireless drivers, which have now been
converted to use the michael_mic() function instead.
It makes sense that no other users ever appeared: Michael MIC is an
insecure algorithm that is specific to WPA TKIP, which itself was an
interim security solution to replace the broken WEP standard.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/arm/configs/omap2plus_defconfig | 1 -
arch/arm/configs/spitz_defconfig | 1 -
arch/arm64/configs/defconfig | 1 -
arch/m68k/configs/amiga_defconfig | 1 -
arch/m68k/configs/apollo_defconfig | 1 -
arch/m68k/configs/atari_defconfig | 1 -
arch/m68k/configs/bvme6000_defconfig | 1 -
arch/m68k/configs/hp300_defconfig | 1 -
arch/m68k/configs/mac_defconfig | 1 -
arch/m68k/configs/multi_defconfig | 1 -
arch/m68k/configs/mvme147_defconfig | 1 -
arch/m68k/configs/mvme16x_defconfig | 1 -
arch/m68k/configs/q40_defconfig | 1 -
arch/m68k/configs/sun3_defconfig | 1 -
arch/m68k/configs/sun3x_defconfig | 1 -
arch/mips/configs/bigsur_defconfig | 1 -
arch/mips/configs/decstation_64_defconfig | 1 -
arch/mips/configs/decstation_defconfig | 1 -
arch/mips/configs/decstation_r4k_defconfig | 1 -
arch/mips/configs/gpr_defconfig | 1 -
arch/mips/configs/ip32_defconfig | 1 -
arch/mips/configs/lemote2f_defconfig | 1 -
arch/mips/configs/malta_qemu_32r6_defconfig | 1 -
arch/mips/configs/maltaaprp_defconfig | 1 -
arch/mips/configs/maltasmvp_defconfig | 1 -
arch/mips/configs/maltasmvp_eva_defconfig | 1 -
arch/mips/configs/maltaup_defconfig | 1 -
arch/mips/configs/mtx1_defconfig | 1 -
arch/mips/configs/rm200_defconfig | 1 -
arch/mips/configs/sb1250_swarm_defconfig | 1 -
arch/parisc/configs/generic-32bit_defconfig | 1 -
arch/parisc/configs/generic-64bit_defconfig | 1 -
arch/powerpc/configs/g5_defconfig | 1 -
arch/powerpc/configs/linkstation_defconfig | 1 -
arch/powerpc/configs/mvme5100_defconfig | 1 -
arch/powerpc/configs/powernv_defconfig | 1 -
arch/powerpc/configs/ppc64_defconfig | 1 -
arch/powerpc/configs/ppc64e_defconfig | 1 -
arch/powerpc/configs/ppc6xx_defconfig | 1 -
arch/powerpc/configs/ps3_defconfig | 1 -
arch/s390/configs/debug_defconfig | 1 -
arch/s390/configs/defconfig | 1 -
arch/sh/configs/sh2007_defconfig | 1 -
arch/sh/configs/titan_defconfig | 1 -
arch/sh/configs/ul2_defconfig | 1 -
arch/sparc/configs/sparc32_defconfig | 1 -
arch/sparc/configs/sparc64_defconfig | 1 -
crypto/Kconfig | 12 --
crypto/Makefile | 1 -
crypto/michael_mic.c | 176 --------------------
crypto/tcrypt.c | 4 -
crypto/testmgr.c | 6 -
crypto/testmgr.h | 50 ------
53 files changed, 296 deletions(-)
delete mode 100644 crypto/michael_mic.c
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 0464f6552169b..ae2883d3ff0ea 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -702,11 +702,10 @@ CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_GHASH_ARM_CE=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_AES_ARM_BS=m
CONFIG_CRYPTO_DEV_OMAP=m
CONFIG_CRYPTO_DEV_OMAP_SHAM=m
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index c130af6d44d48..f116a01c3f5f1 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -228,11 +228,10 @@ CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index b67d5b1fc45b0..a2a5884f0ac82 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1912,11 +1912,10 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_CHACHA20=m
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_ECHAINIV=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_SM3_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 31d16cba9879f..c4230232634a3 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -576,11 +576,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index c0c419ec9a9e9..740edd4f3ca14 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -533,11 +533,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 2b7547ecc4c41..1773533ead702 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -553,11 +553,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 0b63787cff0da..6aaf126a646ea 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -525,11 +525,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 308836b60bba4..9a2076458de8f 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -535,11 +535,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 97e108c0d24f2..76bac1bedf1c6 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -552,11 +552,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 7e9f83af9af46..9d3b9b9d0c15e 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -639,11 +639,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 2fe33271d2494..e705aff2fa200 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -525,11 +525,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 4308daaa7f74c..286f7c949fcb2 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -526,11 +526,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 36eb29ec54eeb..3cedc6a76bc9f 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -542,11 +542,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 524a89fa69531..91c6060f42922 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -523,11 +523,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index f4fbc65c52d9a..8bb0ac877f652 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -523,11 +523,10 @@ CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 349e9e0b4f547..3b64e151e187f 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -220,11 +220,10 @@ CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
diff --git a/arch/mips/configs/decstation_64_defconfig b/arch/mips/configs/decstation_64_defconfig
index dad98c5752928..7c43352fac6bd 100644
--- a/arch/mips/configs/decstation_64_defconfig
+++ b/arch/mips/configs/decstation_64_defconfig
@@ -178,11 +178,10 @@ CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_CMAC=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_CRC32=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_ARC4=m
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 4e1b51a4ad900..aee10274f0488 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -173,11 +173,10 @@ CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_CMAC=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_CRC32=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_ARC4=m
diff --git a/arch/mips/configs/decstation_r4k_defconfig b/arch/mips/configs/decstation_r4k_defconfig
index 4e550dffc23df..a1698049aa7a7 100644
--- a/arch/mips/configs/decstation_r4k_defconfig
+++ b/arch/mips/configs/decstation_r4k_defconfig
@@ -173,11 +173,10 @@ CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_CMAC=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_CRC32=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_ARC4=m
diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig
index 437ef6dc0b4c2..fdd28a89e3369 100644
--- a/arch/mips/configs/gpr_defconfig
+++ b/arch/mips/configs/gpr_defconfig
@@ -273,11 +273,10 @@ CONFIG_NLS_CODEPAGE_850=y
CONFIG_NLS_ISO8859_1=y
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 7568838eb08b2..68558d0d3f52c 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -157,11 +157,10 @@ CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_WP512=y
CONFIG_CRYPTO_ANUBIS=y
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
index 8d3f20ed19b56..eb3565a3f292c 100644
--- a/arch/mips/configs/lemote2f_defconfig
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -306,11 +306,10 @@ CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_DEFLATE=m
diff --git a/arch/mips/configs/malta_qemu_32r6_defconfig b/arch/mips/configs/malta_qemu_32r6_defconfig
index accb471a1d93f..46a69e8984c5a 100644
--- a/arch/mips/configs/malta_qemu_32r6_defconfig
+++ b/arch/mips/configs/malta_qemu_32r6_defconfig
@@ -165,11 +165,10 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig
index 6bda67c5f68f8..74a0e5f6a8860 100644
--- a/arch/mips/configs/maltaaprp_defconfig
+++ b/arch/mips/configs/maltaaprp_defconfig
@@ -166,11 +166,10 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig
index e4082537f80fb..873bfc59623b8 100644
--- a/arch/mips/configs/maltasmvp_defconfig
+++ b/arch/mips/configs/maltasmvp_defconfig
@@ -167,11 +167,10 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/mips/configs/maltasmvp_eva_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig
index 58f5af45fa983..c9230b2c4ea8d 100644
--- a/arch/mips/configs/maltasmvp_eva_defconfig
+++ b/arch/mips/configs/maltasmvp_eva_defconfig
@@ -169,11 +169,10 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig
index 9bfef7de0d1cf..79fd3ccab3393 100644
--- a/arch/mips/configs/maltaup_defconfig
+++ b/arch/mips/configs/maltaup_defconfig
@@ -165,11 +165,10 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 77050ae3945fc..930c0178cc670 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -661,11 +661,10 @@ CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_KHAZAD=m
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index b507dc4dddd48..b1e67ff0c4f08 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -380,11 +380,10 @@ CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig
index ae2afff00e01a..4a25b8d3e5078 100644
--- a/arch/mips/configs/sb1250_swarm_defconfig
+++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -83,11 +83,10 @@ CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig
index 5444ce6405f3a..a2cb2a7a02db8 100644
--- a/arch/parisc/configs/generic-32bit_defconfig
+++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -257,11 +257,10 @@ CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_DEFLATE=y
CONFIG_FONTS=y
CONFIG_PRINTK_TIME=y
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
index ce91f9d1fdbfb..4dd6cf6a2cb9b 100644
--- a/arch/parisc/configs/generic-64bit_defconfig
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -285,11 +285,10 @@ CONFIG_NLS_UTF8=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_HW is not set
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_KERNEL=y
CONFIG_STRIP_ASM_SYMS=y
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 428f17b455132..466f196ee8b29 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -236,11 +236,10 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_BOOTX_TEXT=y
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index b564f9e33a0df..31f84d08b6efe 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -127,11 +127,10 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_DEFLATE=m
diff --git a/arch/powerpc/configs/mvme5100_defconfig b/arch/powerpc/configs/mvme5100_defconfig
index fa2b3b9c59452..c82754c14e15e 100644
--- a/arch/powerpc/configs/mvme5100_defconfig
+++ b/arch/powerpc/configs/mvme5100_defconfig
@@ -113,11 +113,10 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
index 9ac746cfb4be3..675462b783200 100644
--- a/arch/powerpc/configs/powernv_defconfig
+++ b/arch/powerpc/configs/powernv_defconfig
@@ -317,11 +317,10 @@ CONFIG_FTR_FIXUP_SELFTEST=y
CONFIG_MSI_BITMAP_SELFTEST=y
CONFIG_XMON=y
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 2b0720f2753bc..e3e1cad668d9a 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -380,11 +380,10 @@ CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_AES_GCM_P10=m
CONFIG_CRYPTO_DEV_NX=y
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 90247b2a0ab0c..e877598fe3562 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -223,11 +223,10 @@ CONFIG_XMON=y
CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST6=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 3c08f46f3d41f..27d4350e8fdbe 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -1075,11 +1075,10 @@ CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_ANUBIS=m
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 0b48d2b776c44..7cfae0b7b2f35 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -144,11 +144,10 @@ CONFIG_ROOT_NFS=y
CONFIG_CIFS=m
CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_LZO=m
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_MEMORY_INIT=y
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 98fd0a2f51c6a..b74f96eec4658 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -792,11 +792,10 @@ CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index 0f4cedcab3cef..0c831481e43fd 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -776,11 +776,10 @@ CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_XCBC=m
diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig
index e32d2ce72699f..5d90804994857 100644
--- a/arch/sh/configs/sh2007_defconfig
+++ b/arch/sh/configs/sh2007_defconfig
@@ -168,11 +168,10 @@ CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_TGR192=y
CONFIG_CRYPTO_WP512=y
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
index 896e980d04e14..00863ecb228e8 100644
--- a/arch/sh/configs/titan_defconfig
+++ b/arch/sh/configs/titan_defconfig
@@ -244,11 +244,10 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
diff --git a/arch/sh/configs/ul2_defconfig b/arch/sh/configs/ul2_defconfig
index 0d1c858754dbb..00a37944b043c 100644
--- a/arch/sh/configs/ul2_defconfig
+++ b/arch/sh/configs/ul2_defconfig
@@ -77,6 +77,5 @@ CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_932=y
CONFIG_NLS_ISO8859_1=y
# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_CRYPTO_MICHAEL_MIC=y
diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig
index e021ecfb5a771..48d834acafb4a 100644
--- a/arch/sparc/configs/sparc32_defconfig
+++ b/arch/sparc/configs/sparc32_defconfig
@@ -80,11 +80,10 @@ CONFIG_KGDB=y
CONFIG_KGDB_TESTS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 9f3f41246ae6d..632081a262bae 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -208,11 +208,10 @@ CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=m
diff --git a/crypto/Kconfig b/crypto/Kconfig
index b4bb85e8e2261..769aef52a7851 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -914,22 +914,10 @@ config CRYPTO_MD5
select CRYPTO_HASH
select CRYPTO_LIB_MD5
help
MD5 message digest algorithm (RFC1321), including HMAC support.
-config CRYPTO_MICHAEL_MIC
- tristate "Michael MIC"
- select CRYPTO_HASH
- help
- Michael MIC (Message Integrity Code) (IEEE 802.11i)
-
- Defined by the IEEE 802.11i TKIP (Temporal Key Integrity Protocol),
- known as WPA (Wif-Fi Protected Access).
-
- This algorithm is required for TKIP, but it should not be used for
- other purposes because of the weakness of the algorithm.
-
config CRYPTO_RMD160
tristate "RIPEMD-160"
select CRYPTO_HASH
help
RIPEMD-160 hash function (ISO/IEC 10118-3)
diff --git a/crypto/Makefile b/crypto/Makefile
index 04e269117589a..aa35ba03222f7 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -148,11 +148,10 @@ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
obj-$(CONFIG_CRYPTO_SEED) += seed.o
obj-$(CONFIG_CRYPTO_ARIA) += aria_generic.o
obj-$(CONFIG_CRYPTO_CHACHA20) += chacha.o
CFLAGS_chacha.o += -DARCH=$(ARCH)
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
-obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c-cryptoapi.o
crc32c-cryptoapi-y := crc32c.o
obj-$(CONFIG_CRYPTO_CRC32) += crc32-cryptoapi.o
crc32-cryptoapi-y := crc32.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
deleted file mode 100644
index 69ad35f524d7b..0000000000000
--- a/crypto/michael_mic.c
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Cryptographic API
- *
- * Michael MIC (IEEE 802.11i/TKIP) keyed digest
- *
- * Copyright (c) 2004 Jouni Malinen <j@w1.fi>
- */
-#include <crypto/internal/hash.h>
-#include <linux/unaligned.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-
-struct michael_mic_ctx {
- u32 l, r;
-};
-
-struct michael_mic_desc_ctx {
- __le32 pending;
- size_t pending_len;
-
- u32 l, r;
-};
-
-static inline u32 xswap(u32 val)
-{
- return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
-}
-
-
-#define michael_block(l, r) \
-do { \
- r ^= rol32(l, 17); \
- l += r; \
- r ^= xswap(l); \
- l += r; \
- r ^= rol32(l, 3); \
- l += r; \
- r ^= ror32(l, 2); \
- l += r; \
-} while (0)
-
-
-static int michael_init(struct shash_desc *desc)
-{
- struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc);
- struct michael_mic_ctx *ctx = crypto_shash_ctx(desc->tfm);
- mctx->pending_len = 0;
- mctx->l = ctx->l;
- mctx->r = ctx->r;
-
- return 0;
-}
-
-
-static int michael_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc);
-
- if (mctx->pending_len) {
- int flen = 4 - mctx->pending_len;
- if (flen > len)
- flen = len;
- memcpy((u8 *)&mctx->pending + mctx->pending_len, data, flen);
- mctx->pending_len += flen;
- data += flen;
- len -= flen;
-
- if (mctx->pending_len < 4)
- return 0;
-
- mctx->l ^= le32_to_cpu(mctx->pending);
- michael_block(mctx->l, mctx->r);
- mctx->pending_len = 0;
- }
-
- while (len >= 4) {
- mctx->l ^= get_unaligned_le32(data);
- michael_block(mctx->l, mctx->r);
- data += 4;
- len -= 4;
- }
-
- if (len > 0) {
- mctx->pending_len = len;
- memcpy(&mctx->pending, data, len);
- }
-
- return 0;
-}
-
-
-static int michael_final(struct shash_desc *desc, u8 *out)
-{
- struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc);
- u8 *data = (u8 *)&mctx->pending;
-
- /* Last block and padding (0x5a, 4..7 x 0) */
- switch (mctx->pending_len) {
- case 0:
- mctx->l ^= 0x5a;
- break;
- case 1:
- mctx->l ^= data[0] | 0x5a00;
- break;
- case 2:
- mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
- break;
- case 3:
- mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
- 0x5a000000;
- break;
- }
- michael_block(mctx->l, mctx->r);
- /* l ^= 0; */
- michael_block(mctx->l, mctx->r);
-
- put_unaligned_le32(mctx->l, out);
- put_unaligned_le32(mctx->r, out + 4);
-
- return 0;
-}
-
-
-static int michael_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct michael_mic_ctx *mctx = crypto_shash_ctx(tfm);
-
- if (keylen != 8)
- return -EINVAL;
-
- mctx->l = get_unaligned_le32(key);
- mctx->r = get_unaligned_le32(key + 4);
- return 0;
-}
-
-static struct shash_alg alg = {
- .digestsize = 8,
- .setkey = michael_setkey,
- .init = michael_init,
- .update = michael_update,
- .final = michael_final,
- .descsize = sizeof(struct michael_mic_desc_ctx),
- .base = {
- .cra_name = "michael_mic",
- .cra_driver_name = "michael_mic-generic",
- .cra_blocksize = 8,
- .cra_ctxsize = sizeof(struct michael_mic_ctx),
- .cra_module = THIS_MODULE,
- }
-};
-
-static int __init michael_mic_init(void)
-{
- return crypto_register_shash(&alg);
-}
-
-
-static void __exit michael_mic_exit(void)
-{
- crypto_unregister_shash(&alg);
-}
-
-
-module_init(michael_mic_init);
-module_exit(michael_mic_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Michael MIC");
-MODULE_AUTHOR("Jouni Malinen <j@w1.fi>");
-MODULE_ALIAS_CRYPTO("michael_mic");
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index aded375461374..24f0ccc767961 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1555,14 +1555,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
case 16:
ret = min(ret, tcrypt_test("ecb(arc4)"));
break;
- case 17:
- ret = min(ret, tcrypt_test("michael_mic"));
- break;
-
case 18:
ret = min(ret, tcrypt_test("crc32c"));
break;
case 19:
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 4985411dedaec..d5c38683bf46f 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5195,16 +5195,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.generic_driver = "md5-lib",
.test = alg_test_hash,
.suite = {
.hash = __VECS(md5_tv_template)
}
- }, {
- .alg = "michael_mic",
- .test = alg_test_hash,
- .suite = {
- .hash = __VECS(michael_mic_tv_template)
- }
}, {
.alg = "p1363(ecdsa-nist-p192)",
.test = alg_test_null,
}, {
.alg = "p1363(ecdsa-nist-p256)",
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 1c69c11c0cdb4..11911bff5f793 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -32806,60 +32806,10 @@ static const struct comp_testvec lzorle_decomp_tv_template[] = {
.output = "Join us now and share the software "
"Join us now and share the software ",
},
};
-/*
- * Michael MIC test vectors from IEEE 802.11i
- */
-#define MICHAEL_MIC_TEST_VECTORS 6
-
-static const struct hash_testvec michael_mic_tv_template[] = {
- {
- .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
- .ksize = 8,
- .plaintext = zeroed_string,
- .psize = 0,
- .digest = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8",
- },
- {
- .key = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8",
- .ksize = 8,
- .plaintext = "M",
- .psize = 1,
- .digest = "\x43\x47\x21\xca\x40\x63\x9b\x3f",
- },
- {
- .key = "\x43\x47\x21\xca\x40\x63\x9b\x3f",
- .ksize = 8,
- .plaintext = "Mi",
- .psize = 2,
- .digest = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29",
- },
- {
- .key = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29",
- .ksize = 8,
- .plaintext = "Mic",
- .psize = 3,
- .digest = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb",
- },
- {
- .key = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb",
- .ksize = 8,
- .plaintext = "Mich",
- .psize = 4,
- .digest = "\xd5\x5e\x10\x05\x10\x12\x89\x86",
- },
- {
- .key = "\xd5\x5e\x10\x05\x10\x12\x89\x86",
- .ksize = 8,
- .plaintext = "Michael",
- .psize = 7,
- .digest = "\x0a\x94\x2b\x12\x4e\xca\xa5\x46",
- }
-};
-
/*
* CRC32 test vectors
*/
static const struct hash_testvec crc32_tv_template[] = {
{
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 5/6] wifi: ipw2x00: Use michael_mic() from mac80211
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
In-Reply-To: <20260405052734.130368-1-ebiggers@kernel.org>
Just use the michael_mic() function from mac80211 instead of a local
implementation of it on top of the crypto_shash API.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
drivers/net/wireless/intel/ipw2x00/Kconfig | 1 -
.../intel/ipw2x00/libipw_crypto_tkip.c | 120 +-----------------
2 files changed, 5 insertions(+), 116 deletions(-)
diff --git a/drivers/net/wireless/intel/ipw2x00/Kconfig b/drivers/net/wireless/intel/ipw2x00/Kconfig
index 13d69f94c889a..20d1392e1d61c 100644
--- a/drivers/net/wireless/intel/ipw2x00/Kconfig
+++ b/drivers/net/wireless/intel/ipw2x00/Kconfig
@@ -152,11 +152,10 @@ config IPW2200_DEBUG
config LIBIPW
tristate
depends on PCI && MAC80211
select WIRELESS_EXT
select CRYPTO
- select CRYPTO_MICHAEL_MIC
select CRYPTO_LIB_ARC4
select CRC32
help
This option enables the hardware independent IEEE 802.11
networking stack. This component is deprecated in favor of the
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
index c6b0de8d91aea..24bb28ab7a49b 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
@@ -23,12 +23,10 @@
#include <asm/string.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
#include <crypto/arc4.h>
-#include <crypto/hash.h>
-#include <linux/crypto.h>
#include <linux/crc32.h>
#include "libipw.h"
#define TKIP_HDR_LEN 8
@@ -55,15 +53,10 @@ struct libipw_tkip_data {
int key_idx;
struct arc4_ctx rx_ctx_arc4;
struct arc4_ctx tx_ctx_arc4;
- struct crypto_shash *rx_tfm_michael;
- struct crypto_shash *tx_tfm_michael;
-
- /* scratch buffers for virt_to_page() (crypto API) */
- u8 rx_hdr[16], tx_hdr[16];
unsigned long flags;
};
static unsigned long libipw_tkip_set_flags(unsigned long flags, void *priv)
@@ -87,45 +80,18 @@ static void *libipw_tkip_init(int key_idx)
if (fips_enabled)
return NULL;
priv = kzalloc_obj(*priv, GFP_ATOMIC);
if (priv == NULL)
- goto fail;
+ return priv;
priv->key_idx = key_idx;
-
- priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
- if (IS_ERR(priv->tx_tfm_michael)) {
- priv->tx_tfm_michael = NULL;
- goto fail;
- }
-
- priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
- if (IS_ERR(priv->rx_tfm_michael)) {
- priv->rx_tfm_michael = NULL;
- goto fail;
- }
-
return priv;
-
- fail:
- if (priv) {
- crypto_free_shash(priv->tx_tfm_michael);
- crypto_free_shash(priv->rx_tfm_michael);
- kfree(priv);
- }
-
- return NULL;
}
static void libipw_tkip_deinit(void *priv)
{
- struct libipw_tkip_data *_priv = priv;
- if (_priv) {
- crypto_free_shash(_priv->tx_tfm_michael);
- crypto_free_shash(_priv->rx_tfm_michael);
- }
kfree_sensitive(priv);
}
static inline u16 RotR1(u16 val)
{
@@ -462,77 +428,10 @@ static int libipw_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
skb_trim(skb, skb->len - 4);
return keyidx;
}
-static int michael_mic(struct crypto_shash *tfm_michael, u8 *key, u8 *hdr,
- u8 *data, size_t data_len, u8 *mic)
-{
- SHASH_DESC_ON_STACK(desc, tfm_michael);
- int err;
-
- if (tfm_michael == NULL) {
- pr_warn("%s(): tfm_michael == NULL\n", __func__);
- return -1;
- }
-
- desc->tfm = tfm_michael;
-
- if (crypto_shash_setkey(tfm_michael, key, 8))
- return -1;
-
- err = crypto_shash_init(desc);
- if (err)
- goto out;
- err = crypto_shash_update(desc, hdr, 16);
- if (err)
- goto out;
- err = crypto_shash_update(desc, data, data_len);
- if (err)
- goto out;
- err = crypto_shash_final(desc, mic);
-
-out:
- shash_desc_zero(desc);
- return err;
-}
-
-static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
-{
- struct ieee80211_hdr *hdr11;
-
- hdr11 = (struct ieee80211_hdr *)skb->data;
-
- switch (le16_to_cpu(hdr11->frame_control) &
- (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
- case IEEE80211_FCTL_TODS:
- memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
- break;
- case IEEE80211_FCTL_FROMDS:
- memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
- break;
- case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
- memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
- break;
- default:
- memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
- break;
- }
-
- if (ieee80211_is_data_qos(hdr11->frame_control)) {
- hdr[12] = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(hdr11)))
- & IEEE80211_QOS_CTL_TID_MASK;
- } else
- hdr[12] = 0; /* priority */
-
- hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
-}
-
static int libipw_michael_mic_add(struct sk_buff *skb, int hdr_len,
void *priv)
{
struct libipw_tkip_data *tkey = priv;
u8 *pos;
@@ -542,16 +441,13 @@ static int libipw_michael_mic_add(struct sk_buff *skb, int hdr_len,
"(tailroom=%d hdr_len=%d skb->len=%d)\n",
skb_tailroom(skb), hdr_len, skb->len);
return -1;
}
- michael_mic_hdr(skb, tkey->tx_hdr);
pos = skb_put(skb, 8);
- if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
- skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
- return -1;
-
+ michael_mic(&tkey->key[16], (struct ieee80211_hdr *)skb->data,
+ skb->data + hdr_len, skb->len - 8 - hdr_len, pos);
return 0;
}
static void libipw_michael_mic_failure(struct net_device *dev,
struct ieee80211_hdr *hdr,
@@ -581,14 +477,12 @@ static int libipw_michael_mic_verify(struct sk_buff *skb, int keyidx,
u8 mic[8];
if (!tkey->key_set)
return -1;
- michael_mic_hdr(skb, tkey->rx_hdr);
- if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
- skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
- return -1;
+ michael_mic(&tkey->key[24], (struct ieee80211_hdr *)skb->data,
+ skb->data + hdr_len, skb->len - 8 - hdr_len, mic);
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
struct ieee80211_hdr *hdr;
hdr = (struct ieee80211_hdr *)skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
"MSDU from %pM keyidx=%d\n",
@@ -612,21 +506,17 @@ static int libipw_michael_mic_verify(struct sk_buff *skb, int keyidx,
static int libipw_tkip_set_key(void *key, int len, u8 * seq, void *priv)
{
struct libipw_tkip_data *tkey = priv;
int keyidx;
- struct crypto_shash *tfm = tkey->tx_tfm_michael;
struct arc4_ctx *tfm2 = &tkey->tx_ctx_arc4;
- struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
struct arc4_ctx *tfm4 = &tkey->rx_ctx_arc4;
keyidx = tkey->key_idx;
memset(tkey, 0, sizeof(*tkey));
tkey->key_idx = keyidx;
- tkey->tx_tfm_michael = tfm;
tkey->tx_ctx_arc4 = *tfm2;
- tkey->rx_tfm_michael = tfm3;
tkey->rx_ctx_arc4 = *tfm4;
if (len == TKIP_KEY_LEN) {
memcpy(tkey->key, key, TKIP_KEY_LEN);
tkey->key_set = 1;
tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 4/6] wifi: ipw2x00: Depend on MAC80211
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
In-Reply-To: <20260405052734.130368-1-ebiggers@kernel.org>
While the ipw2100 and ipw2200 hardware is "Full MAC" in the sense that
it handles management frames (like association and scanning), it doesn't
implement various cryptographic protocols, such as the Michael MIC
algorithm used in the (deprecated) TKIP.
Currently ipw2x00 accesses Michael MIC via the crypto_shash API. Yet,
the mac80211 module already has its own Michael MIC implementation.
ipw2x00 is the only code in the kernel tree that needs a Michael MIC
implementation that doesn't already depend on CONFIG_MAC80211.
Just add the dependency on MAC80211 so that we'll be able to consolidate
the Michael MIC code in mac80211 and remove it from crypto_shash.
Alternatives considered:
- Move michael_mic() from mac80211 to cfg80211. Probably not worth it
just for ipw2x00.
- Move michael_mic() to its own independent module. Again, probably
not worth it just for ipw2x00.
- Copy michael_mic() into ipw2x00. It seems better to avoid the
duplicate copy.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
drivers/net/wireless/intel/ipw2x00/Kconfig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/ipw2x00/Kconfig b/drivers/net/wireless/intel/ipw2x00/Kconfig
index b92df91adb3a4..13d69f94c889a 100644
--- a/drivers/net/wireless/intel/ipw2x00/Kconfig
+++ b/drivers/net/wireless/intel/ipw2x00/Kconfig
@@ -3,11 +3,11 @@
# Intel Centrino wireless drivers
#
config IPW2100
tristate "Intel PRO/Wireless 2100 Network Connection"
- depends on PCI && CFG80211
+ depends on PCI && MAC80211
select WIRELESS_EXT
select WEXT_PRIV
select FW_LOADER
select LIBIPW
help
@@ -62,11 +62,11 @@ config IPW2100_DEBUG
If you are not trying to debug or develop the IPW2100 driver, you
most likely want to say N here.
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
- depends on PCI && CFG80211
+ depends on PCI && MAC80211
select WIRELESS_EXT
select WEXT_PRIV
select FW_LOADER
select LIBIPW
help
@@ -149,11 +149,11 @@ config IPW2200_DEBUG
If you are not sure, say N here.
config LIBIPW
tristate
- depends on PCI && CFG80211
+ depends on PCI && MAC80211
select WIRELESS_EXT
select CRYPTO
select CRYPTO_MICHAEL_MIC
select CRYPTO_LIB_ARC4
select CRC32
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 3/6] wifi: ath12k: Use michael_mic() from mac80211
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
In-Reply-To: <20260405052734.130368-1-ebiggers@kernel.org>
Just use the michael_mic() function from mac80211 instead of a local
implementation of it on top of the crypto_shash API.
Preserve the check for fips_enabled which was present implicitly in the
crypto_shash-based code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
drivers/net/wireless/ath/ath12k/Kconfig | 1 -
drivers/net/wireless/ath/ath12k/dp.c | 2 -
drivers/net/wireless/ath/ath12k/dp_peer.h | 1 -
drivers/net/wireless/ath/ath12k/dp_rx.c | 55 ++-----------------
drivers/net/wireless/ath/ath12k/dp_rx.h | 4 --
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 7 +--
6 files changed, 8 insertions(+), 62 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/Kconfig b/drivers/net/wireless/ath/ath12k/Kconfig
index 1ea1af1b8f6c5..d39c075758bda 100644
--- a/drivers/net/wireless/ath/ath12k/Kconfig
+++ b/drivers/net/wireless/ath/ath12k/Kconfig
@@ -1,10 +1,9 @@
# SPDX-License-Identifier: BSD-3-Clause-Clear
config ATH12K
tristate "Qualcomm Technologies Wi-Fi 7 support (ath12k)"
depends on MAC80211 && HAS_DMA && PCI
- select CRYPTO_MICHAEL_MIC
select QCOM_QMI_HELPERS
select MHI_BUS
select QRTR
select QRTR_MHI
select PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 1c82d927d27b2..90802ed1aa59f 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -2,11 +2,10 @@
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
-#include <crypto/hash.h>
#include "core.h"
#include "dp_tx.h"
#include "hif.h"
#include "hal.h"
#include "debug.h"
@@ -39,11 +38,10 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr)
spin_unlock_bh(&dp->dp_lock);
return;
}
ath12k_dp_rx_peer_tid_cleanup(ar, peer);
- crypto_free_shash(peer->dp_peer->tfm_mmic);
peer->dp_peer->dp_setup_done = false;
spin_unlock_bh(&dp->dp_lock);
}
int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h
index 20294ff095131..113b8040010fa 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.h
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.h
@@ -137,11 +137,10 @@ struct ath12k_dp_peer {
u16 sec_type_grp;
u16 sec_type;
/* Info used in MMIC verification of * RX fragments */
- struct crypto_shash *tfm_mmic;
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
};
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index f0b4f607b8452..1272fd6c69860 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -2,14 +2,14 @@
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
+#include <linux/fips.h>
#include <linux/ieee80211.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
-#include <crypto/hash.h>
#include "core.h"
#include "debug.h"
#include "hw.h"
#include "dp_rx.h"
#include "dp_tx.h"
@@ -1429,92 +1429,47 @@ static void ath12k_dp_rx_frag_timer(struct timer_list *timer)
}
int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id)
{
struct ath12k_base *ab = ar->ab;
- struct crypto_shash *tfm;
struct ath12k_dp_link_peer *peer;
struct ath12k_dp_rx_tid *rx_tid;
int i;
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
- tfm = crypto_alloc_shash("michael_mic", 0, 0);
- if (IS_ERR(tfm))
- return PTR_ERR(tfm);
+ if (fips_enabled) {
+ ath12k_warn(ab, "Michael MIC is not FIPS-allowed");
+ return -ENOENT;
+ }
spin_lock_bh(&dp->dp_lock);
peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac);
if (!peer || !peer->dp_peer) {
spin_unlock_bh(&dp->dp_lock);
- crypto_free_shash(tfm);
ath12k_warn(ab, "failed to find the peer to set up fragment info\n");
return -ENOENT;
}
if (!peer->primary_link) {
spin_unlock_bh(&dp->dp_lock);
- crypto_free_shash(tfm);
return 0;
}
for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
rx_tid = &peer->dp_peer->rx_tid[i];
rx_tid->dp = dp;
timer_setup(&rx_tid->frag_timer, ath12k_dp_rx_frag_timer, 0);
skb_queue_head_init(&rx_tid->rx_frags);
}
- peer->dp_peer->tfm_mmic = tfm;
peer->dp_peer->dp_setup_done = true;
spin_unlock_bh(&dp->dp_lock);
return 0;
}
-int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
- struct ieee80211_hdr *hdr, u8 *data,
- size_t data_len, u8 *mic)
-{
- SHASH_DESC_ON_STACK(desc, tfm);
- u8 mic_hdr[16] = {};
- u8 tid = 0;
- int ret;
-
- if (!tfm)
- return -EINVAL;
-
- desc->tfm = tfm;
-
- ret = crypto_shash_setkey(tfm, key, 8);
- if (ret)
- goto out;
-
- ret = crypto_shash_init(desc);
- if (ret)
- goto out;
-
- /* TKIP MIC header */
- memcpy(mic_hdr, ieee80211_get_DA(hdr), ETH_ALEN);
- memcpy(mic_hdr + ETH_ALEN, ieee80211_get_SA(hdr), ETH_ALEN);
- if (ieee80211_is_data_qos(hdr->frame_control))
- tid = ieee80211_get_tid(hdr);
- mic_hdr[12] = tid;
-
- ret = crypto_shash_update(desc, mic_hdr, 16);
- if (ret)
- goto out;
- ret = crypto_shash_update(desc, data, data_len);
- if (ret)
- goto out;
- ret = crypto_shash_final(desc, mic);
-out:
- shash_desc_zero(desc);
- return ret;
-}
-EXPORT_SYMBOL(ath12k_dp_rx_h_michael_mic);
-
void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
enum hal_encrypt_type enctype, u32 flags)
{
struct ath12k_dp *dp = dp_pdev->dp;
struct ieee80211_hdr *hdr;
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index bd62af0c80d46..55a31e669b3b0 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -4,11 +4,10 @@
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_RX_H
#define ATH12K_DP_RX_H
-#include <crypto/hash.h>
#include "core.h"
#include "debug.h"
#define DP_MAX_NWIFI_HDR_LEN 30
@@ -202,13 +201,10 @@ u64 ath12k_dp_rx_h_get_pn(struct ath12k_dp *dp, struct sk_buff *skb);
void ath12k_dp_rx_h_sort_frags(struct ath12k_hal *hal,
struct sk_buff_head *frag_list,
struct sk_buff *cur_frag);
void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
enum hal_encrypt_type enctype, u32 flags);
-int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
- struct ieee80211_hdr *hdr, u8 *data,
- size_t data_len, u8 *mic);
int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params,
u8 link_id);
int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
struct ieee80211_ampdu_params *params,
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index e6a934d74e85d..945680b3ebdfc 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -981,11 +981,11 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu);
struct ieee80211_key_conf *key_conf;
struct ieee80211_hdr *hdr;
u8 mic[IEEE80211_CCMP_MIC_LEN];
- int head_len, tail_len, ret;
+ int head_len, tail_len;
size_t data_len;
u32 hdr_len, hal_rx_desc_sz = hal->hal_desc_sz;
u8 *key, *data;
u8 key_idx;
@@ -1009,13 +1009,12 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
data = msdu->data + head_len;
data_len = msdu->len - head_len - tail_len;
key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
- ret = ath12k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data,
- data_len, mic);
- if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
+ michael_mic(key, hdr, data, data_len, mic);
+ if (memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
goto mic_fail;
return 0;
mic_fail:
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 2/6] wifi: ath11k: Use michael_mic() from mac80211
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
In-Reply-To: <20260405052734.130368-1-ebiggers@kernel.org>
Just use the michael_mic() function from mac80211 instead of a local
implementation of it on top of the crypto_shash API.
Preserve the check for fips_enabled which was present implicitly in the
crypto_shash-based code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
drivers/net/wireless/ath/ath11k/Kconfig | 1 -
drivers/net/wireless/ath/ath11k/dp.c | 2 -
drivers/net/wireless/ath/ath11k/dp_rx.c | 60 +++----------------------
drivers/net/wireless/ath/ath11k/peer.h | 1 -
4 files changed, 7 insertions(+), 57 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig
index 47dfd39caa89a..385513cfdc30e 100644
--- a/drivers/net/wireless/ath/ath11k/Kconfig
+++ b/drivers/net/wireless/ath/ath11k/Kconfig
@@ -1,10 +1,9 @@
# SPDX-License-Identifier: BSD-3-Clause-Clear
config ATH11K
tristate "Qualcomm Technologies 802.11ax chipset support"
depends on MAC80211 && HAS_DMA
- select CRYPTO_MICHAEL_MIC
select ATH_COMMON
select QCOM_QMI_HELPERS
help
This module adds support for Qualcomm Technologies 802.11ax family of
chipsets.
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index c940de285276d..bbb86f1651419 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -3,11 +3,10 @@
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
-#include <crypto/hash.h>
#include <linux/export.h>
#include "core.h"
#include "dp_tx.h"
#include "hal_tx.h"
#include "hif.h"
@@ -37,11 +36,10 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)
return;
}
ath11k_peer_rx_tid_cleanup(ar, peer);
peer->dp_setup_done = false;
- crypto_free_shash(peer->tfm_mmic);
spin_unlock_bh(&ab->base_lock);
}
int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)
{
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 49d959b2e1480..00df93e41fa80 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -2,14 +2,14 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <linux/fips.h>
#include <linux/ieee80211.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
-#include <crypto/hash.h>
#include "core.h"
#include "debug.h"
#include "debugfs_htt_stats.h"
#include "debugfs_sta.h"
#include "hal_desc.h"
@@ -3181,96 +3181,50 @@ static void ath11k_dp_rx_frag_timer(struct timer_list *timer)
}
int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id)
{
struct ath11k_base *ab = ar->ab;
- struct crypto_shash *tfm;
struct ath11k_peer *peer;
struct dp_rx_tid *rx_tid;
int i;
- tfm = crypto_alloc_shash("michael_mic", 0, 0);
- if (IS_ERR(tfm)) {
- ath11k_warn(ab, "failed to allocate michael_mic shash: %ld\n",
- PTR_ERR(tfm));
- return PTR_ERR(tfm);
+ if (fips_enabled) {
+ ath11k_warn(ab, "Michael MIC is not FIPS-allowed");
+ return -ENOENT;
}
spin_lock_bh(&ab->base_lock);
peer = ath11k_peer_find(ab, vdev_id, peer_mac);
if (!peer) {
ath11k_warn(ab, "failed to find the peer to set up fragment info\n");
spin_unlock_bh(&ab->base_lock);
- crypto_free_shash(tfm);
return -ENOENT;
}
for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
rx_tid = &peer->rx_tid[i];
rx_tid->ab = ab;
timer_setup(&rx_tid->frag_timer, ath11k_dp_rx_frag_timer, 0);
skb_queue_head_init(&rx_tid->rx_frags);
}
- peer->tfm_mmic = tfm;
peer->dp_setup_done = true;
spin_unlock_bh(&ab->base_lock);
return 0;
}
-static int ath11k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
- struct ieee80211_hdr *hdr, u8 *data,
- size_t data_len, u8 *mic)
-{
- SHASH_DESC_ON_STACK(desc, tfm);
- u8 mic_hdr[16] = {};
- u8 tid = 0;
- int ret;
-
- if (!tfm)
- return -EINVAL;
-
- desc->tfm = tfm;
-
- ret = crypto_shash_setkey(tfm, key, 8);
- if (ret)
- goto out;
-
- ret = crypto_shash_init(desc);
- if (ret)
- goto out;
-
- /* TKIP MIC header */
- memcpy(mic_hdr, ieee80211_get_DA(hdr), ETH_ALEN);
- memcpy(mic_hdr + ETH_ALEN, ieee80211_get_SA(hdr), ETH_ALEN);
- if (ieee80211_is_data_qos(hdr->frame_control))
- tid = ieee80211_get_tid(hdr);
- mic_hdr[12] = tid;
-
- ret = crypto_shash_update(desc, mic_hdr, 16);
- if (ret)
- goto out;
- ret = crypto_shash_update(desc, data, data_len);
- if (ret)
- goto out;
- ret = crypto_shash_final(desc, mic);
-out:
- shash_desc_zero(desc);
- return ret;
-}
-
static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer *peer,
struct sk_buff *msdu)
{
struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu);
struct ieee80211_key_conf *key_conf;
struct ieee80211_hdr *hdr;
u8 mic[IEEE80211_CCMP_MIC_LEN];
- int head_len, tail_len, ret;
+ int head_len, tail_len;
size_t data_len;
u32 hdr_len, hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz;
u8 *key, *data;
u8 key_idx;
@@ -3292,12 +3246,12 @@ static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer
data = msdu->data + head_len;
data_len = msdu->len - head_len - tail_len;
key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
- ret = ath11k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data, data_len, mic);
- if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
+ michael_mic(key, hdr, data, data_len, mic);
+ if (memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
goto mic_fail;
return 0;
mic_fail:
diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h
index 3ad2f3355b14f..f5ef1a27f8f25 100644
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -27,11 +27,10 @@ struct ath11k_peer {
struct rhash_head rhash_addr;
/* Info used in MMIC verification of
* RX fragments
*/
- struct crypto_shash *tfm_mmic;
u8 mcast_keyidx;
u8 ucast_keyidx;
u16 sec_type;
u16 sec_type_grp;
bool is_authorized;
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 1/6] wifi: mac80211: Export michael_mic()
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
In-Reply-To: <20260405052734.130368-1-ebiggers@kernel.org>
Export the michael_mic() function so that it can be reused by the
ath11k, ath12k, and ipw2x00 drivers. Currently they have their own
local implementations of it based on crypto_shash, which is redundant
and inefficient.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/linux/ieee80211.h | 5 +++++
net/mac80211/michael.c | 5 ++++-
net/mac80211/michael.h | 22 ----------------------
net/mac80211/wpa.c | 1 -
4 files changed, 9 insertions(+), 24 deletions(-)
delete mode 100644 net/mac80211/michael.h
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index b5d649db123fe..da6fcdc742e7c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1919,10 +1919,15 @@ enum ieee80211_radio_measurement_actioncode {
#define FILS_ERP_MAX_RRK_LEN 64
#define PMK_MAX_LEN 64
#define SAE_PASSWORD_MAX_LEN 128
+#define MICHAEL_MIC_LEN 8
+
+void michael_mic(const u8 *key, struct ieee80211_hdr *hdr,
+ const u8 *data, size_t data_len, u8 *mic);
+
/* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */
enum ieee80211_pub_actioncode {
WLAN_PUB_ACTION_20_40_BSS_COEX = 0,
WLAN_PUB_ACTION_DSE_ENABLEMENT = 1,
WLAN_PUB_ACTION_DSE_DEENABLEMENT = 2,
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c
index 8a1afc93e7499..50cdb67f0503d 100644
--- a/net/mac80211/michael.c
+++ b/net/mac80211/michael.c
@@ -6,11 +6,13 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/ieee80211.h>
#include <linux/unaligned.h>
-#include "michael.h"
+struct michael_mic_ctx {
+ u32 l, r;
+};
static void michael_block(struct michael_mic_ctx *mctx, u32 val)
{
mctx->l ^= val;
mctx->r ^= rol32(mctx->l, 17);
@@ -79,5 +81,6 @@ void michael_mic(const u8 *key, struct ieee80211_hdr *hdr,
michael_block(&mctx, 0);
put_unaligned_le32(mctx.l, mic);
put_unaligned_le32(mctx.r, mic + 4);
}
+EXPORT_SYMBOL_GPL(michael_mic);
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h
deleted file mode 100644
index a7fdb8e84615a..0000000000000
--- a/net/mac80211/michael.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Michael MIC implementation - optimized for TKIP MIC operations
- * Copyright 2002-2003, Instant802 Networks, Inc.
- */
-
-#ifndef MICHAEL_H
-#define MICHAEL_H
-
-#include <linux/types.h>
-#include <linux/ieee80211.h>
-
-#define MICHAEL_MIC_LEN 8
-
-struct michael_mic_ctx {
- u32 l, r;
-};
-
-void michael_mic(const u8 *key, struct ieee80211_hdr *hdr,
- const u8 *data, size_t data_len, u8 *mic);
-
-#endif /* MICHAEL_H */
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 64a57475ce506..724ec831a8857 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -16,11 +16,10 @@
#include <net/mac80211.h>
#include <crypto/aes.h>
#include <crypto/utils.h>
#include "ieee80211_i.h"
-#include "michael.h"
#include "tkip.h"
#include "aes_ccm.h"
#include "aes_cmac.h"
#include "aes_gmac.h"
#include "aes_gcm.h"
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 0/6] Consolidate Michael MIC code into mac80211
From: Eric Biggers @ 2026-04-05 5:27 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: linux-crypto, linux-kernel, Herbert Xu, Eric Biggers
Michael MIC is an inherently weak algorithm that is specific to WPA
TKIP, which itself was an interim security solution to replace the
broken WEP standard.
Currently, the primary implementation of Michael MIC in the kernel is
the one in the mac80211 module. But there's also a duplicate
implementation in crypto/michael_mic.c which is exposed via the
crypto_shash API. It's used only by a few wireless drivers.
Seeing as Michael MIC is specific to WPA TKIP and should never be used
elsewhere, this series migrates those few drivers to the mac80211
implementation of Michael MIC, then removes the crypto implementation of
Michael MIC. This consolidates duplicate code and prevents other kernel
subsystems from accidentally using this insecure algorithm.
This series is targeting wireless-next.
Eric Biggers (6):
wifi: mac80211: Export michael_mic()
wifi: ath11k: Use michael_mic() from mac80211
wifi: ath12k: Use michael_mic() from mac80211
wifi: ipw2x00: Depend on MAC80211
wifi: ipw2x00: Use michael_mic() from mac80211
crypto: Remove michael_mic from crypto_shash API
arch/arm/configs/omap2plus_defconfig | 1 -
arch/arm/configs/spitz_defconfig | 1 -
arch/arm64/configs/defconfig | 1 -
arch/m68k/configs/amiga_defconfig | 1 -
arch/m68k/configs/apollo_defconfig | 1 -
arch/m68k/configs/atari_defconfig | 1 -
arch/m68k/configs/bvme6000_defconfig | 1 -
arch/m68k/configs/hp300_defconfig | 1 -
arch/m68k/configs/mac_defconfig | 1 -
arch/m68k/configs/multi_defconfig | 1 -
arch/m68k/configs/mvme147_defconfig | 1 -
arch/m68k/configs/mvme16x_defconfig | 1 -
arch/m68k/configs/q40_defconfig | 1 -
arch/m68k/configs/sun3_defconfig | 1 -
arch/m68k/configs/sun3x_defconfig | 1 -
arch/mips/configs/bigsur_defconfig | 1 -
arch/mips/configs/decstation_64_defconfig | 1 -
arch/mips/configs/decstation_defconfig | 1 -
arch/mips/configs/decstation_r4k_defconfig | 1 -
arch/mips/configs/gpr_defconfig | 1 -
arch/mips/configs/ip32_defconfig | 1 -
arch/mips/configs/lemote2f_defconfig | 1 -
arch/mips/configs/malta_qemu_32r6_defconfig | 1 -
arch/mips/configs/maltaaprp_defconfig | 1 -
arch/mips/configs/maltasmvp_defconfig | 1 -
arch/mips/configs/maltasmvp_eva_defconfig | 1 -
arch/mips/configs/maltaup_defconfig | 1 -
arch/mips/configs/mtx1_defconfig | 1 -
arch/mips/configs/rm200_defconfig | 1 -
arch/mips/configs/sb1250_swarm_defconfig | 1 -
arch/parisc/configs/generic-32bit_defconfig | 1 -
arch/parisc/configs/generic-64bit_defconfig | 1 -
arch/powerpc/configs/g5_defconfig | 1 -
arch/powerpc/configs/linkstation_defconfig | 1 -
arch/powerpc/configs/mvme5100_defconfig | 1 -
arch/powerpc/configs/powernv_defconfig | 1 -
arch/powerpc/configs/ppc64_defconfig | 1 -
arch/powerpc/configs/ppc64e_defconfig | 1 -
arch/powerpc/configs/ppc6xx_defconfig | 1 -
arch/powerpc/configs/ps3_defconfig | 1 -
arch/s390/configs/debug_defconfig | 1 -
arch/s390/configs/defconfig | 1 -
arch/sh/configs/sh2007_defconfig | 1 -
arch/sh/configs/titan_defconfig | 1 -
arch/sh/configs/ul2_defconfig | 1 -
arch/sparc/configs/sparc32_defconfig | 1 -
arch/sparc/configs/sparc64_defconfig | 1 -
crypto/Kconfig | 12 --
crypto/Makefile | 1 -
crypto/michael_mic.c | 176 ------------------
crypto/tcrypt.c | 4 -
crypto/testmgr.c | 6 -
crypto/testmgr.h | 50 -----
drivers/net/wireless/ath/ath11k/Kconfig | 1 -
drivers/net/wireless/ath/ath11k/dp.c | 2 -
drivers/net/wireless/ath/ath11k/dp_rx.c | 60 +-----
drivers/net/wireless/ath/ath11k/peer.h | 1 -
drivers/net/wireless/ath/ath12k/Kconfig | 1 -
drivers/net/wireless/ath/ath12k/dp.c | 2 -
drivers/net/wireless/ath/ath12k/dp_peer.h | 1 -
drivers/net/wireless/ath/ath12k/dp_rx.c | 55 +-----
drivers/net/wireless/ath/ath12k/dp_rx.h | 4 -
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 7 +-
drivers/net/wireless/intel/ipw2x00/Kconfig | 7 +-
.../intel/ipw2x00/libipw_crypto_tkip.c | 120 +-----------
include/linux/ieee80211.h | 5 +
net/mac80211/michael.c | 5 +-
net/mac80211/michael.h | 22 ---
net/mac80211/wpa.c | 1 -
69 files changed, 32 insertions(+), 558 deletions(-)
delete mode 100644 crypto/michael_mic.c
delete mode 100644 net/mac80211/michael.h
base-commit: dbd94b9831bc52a1efb7ff3de841ffc3457428ce
--
2.53.0
^ permalink raw reply
* Re: [PATCH rtw-next 01/12] wifi: rtw89: usb: Disable MLO for now
From: Bitterblue Smith @ 2026-04-04 14:07 UTC (permalink / raw)
To: Ping-Ke Shih, linux-wireless@vger.kernel.org
In-Reply-To: <dbd41cc160504b8daeb93b7967101c7f@realtek.com>
On 30/03/2026 05:59, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> It's not yet clear how the TX queue/channel selection is supposed to
>> work for RTL8922AU with MLO, and I can't test MLO anyway.
>
> Currently, rtw89 work in MLSR mode by default, which means it works like
> legacy mode, so it's probably fine to enable MLO.
>
Someone tested MLO now (5 GHz + 6 GHz) so I will drop this patch from v2.
> The debugfs can switch eMLSR mode, but it doesn't work very well for now.
>
>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
>> drivers/net/wireless/realtek/rtw89/usb.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c
>> b/drivers/net/wireless/realtek/rtw89/usb.c
>> index 581b8c05f930..7a46ace34c25 100644
>> --- a/drivers/net/wireless/realtek/rtw89/usb.c
>> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
>> @@ -1029,6 +1029,10 @@ int rtw89_usb_probe(struct usb_interface *intf,
>> return -ENOMEM;
>> }
>>
>> + rtw89_debug(rtwdev, RTW89_DBG_CHAN,
>> + "%s: disable MLO for now\n", __func__);
>> + rtwdev->support_mlo = false;
>> +
>> rtwusb = rtw89_usb_priv(rtwdev);
>> rtwusb->rtwdev = rtwdev;
>> rtwusb->info = info->bus.usb;
>> --
>> 2.53.0
>
^ permalink raw reply
* Re: [PATCH v2 3/7] dt-bindings: net: wireless: ath11k: Document WCN6755 WiFi
From: Krzysztof Kozlowski @ 2026-04-04 11:03 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-3-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:49PM +0200, Luca Weiss wrote:
> Document the WCN6755 WiFi using a fallback to WCN6750 since the two
> chips seem to be completely pin and software compatible. In fact the
> original downstream kernel just pretends the WCN6755 is a WCN6750.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> .../devicetree/bindings/net/wireless/qcom,ath11k.yaml | 16 +++++++++++-----
> 1 file changed, 11 insertions(+), 5 deletions(-)
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/7] dt-bindings: bluetooth: qcom,wcn6750-bt: Document WCN6755 Bluetooth
From: Krzysztof Kozlowski @ 2026-04-04 10:58 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-2-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:48PM +0200, Luca Weiss wrote:
> Document the WCN6755 Bluetooth using a fallback to WCN6750 since the two
> chips seem to be completely pin and software compatible. In fact the
> original downstream kernel just pretends the WCN6755 is a WCN6750.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> .../devicetree/bindings/net/bluetooth/qcom,wcn6750-bt.yaml | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 1/7] regulator: dt-bindings: qcom,qca6390-pmu: Document WCN6755 PMU
From: Krzysztof Kozlowski @ 2026-04-04 10:57 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-1-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:47PM +0200, Luca Weiss wrote:
> Document the WCN6755 PMU using a fallback to WCN6750 since the two chips
> seem to be completely pin and software compatible. In fact the original
> downstream kernel just pretends the WCN6755 is a WCN6750.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> .../devicetree/bindings/regulator/qcom,qca6390-pmu.yaml | 16 +++++++++++-----
> 1 file changed, 11 insertions(+), 5 deletions(-)
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [BUG] wifi: rtw88: Hard system freeze on RTL8821CE when power_save is enabled (LPS/ASPM conflict)
From: LB F @ 2026-04-04 10:44 UTC (permalink / raw)
To: Ping-Ke Shih
Cc: Bitterblue Smith, linux-wireless@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <CALdGYqThUD1DSAcsshC0y4Lm=uG=EDvBccMqkL=qr2+Jajp4tg@mail.gmail.com>
Hi Bitterblue, Ping-Ke,
I need to correct an error in my previous message. I wrote that
Ping-Ke's rate validation v2 patch (DESC_RATE_MAX clamp in
rtw_rx_query_rx_desc) was applied during the crash — it was not.
When I checked the source with `git diff`, rx.c turned out to be
completely unmodified. I sincerely apologize for the confusion.
At the time of the April 3rd crash, only two patches were active:
- Ping-Ke's DMI quirk (ASPM + LPS Deep disabled)
- Bitterblue's diagnostic hex dump in query_phy_status
The rate validation patch has now been re-applied and verified
in the running system.
That said, I believe this particular crash was not caused by the
missing rate validation. The mac80211 WARNING in the crash fires
at rx.c:896 (ieee80211_rx_list+0x1033), not at rx.c:5491 (the
VHT NSS=0 check that rate validation addresses). The system hang
itself was caused by the DMA tag mismatch loop in
rtw_pci_dma_check(), which is independent of rate handling.
Again, I am very sorry for the inaccuracy. I will be more careful
verifying applied patches before reporting in the future.
Best regards,
Oleksandr Havrylov
^ permalink raw reply
* Re: [PATCH ath-next v6] wifi: ath12k: avoid dynamic alloc when parsing wmi tb
From: Rameshkumar Sundaram @ 2026-04-04 9:48 UTC (permalink / raw)
To: Nicolas Escande, ath12k; +Cc: linux-wireless
In-Reply-To: <20260403142841.1105780-1-nico.escande@gmail.com>
On 4/3/2026 7:58 PM, Nicolas Escande wrote:
> On each WMI message received from the hardware, we alloc a temporary array
> of WMI_TAG_MAX entries of type void *. This array is then populated with
> pointers of parsed structs depending on the WMI type, and then freed. This
> alloc can fail when memory pressure in the system is high enough.
>
> Given the fact that it is scheduled in softirq with the system_bh_wq, we
> should not be able to parse more than one WMI message per CPU at any time.
>
> So instead lets move to a per cpu allocated array, that is reused across
> calls. This memory is allocated as needed and refcounted to exist only
> as long as one struct ath12k_base lives.
>
> ath12k_wmi_tlv_parse_alloc() and ath12k_wmi_tlv_parse() are merged
> together as it no longer allocs mem but returns the existing per-cpu one.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
> ---
> changes from v4:
> - moved to a single instance, refcounted per cpu memory alloc
>
> changes from v3:
> - simplified ath12k_core_init() with a single statement
> - move perpcu.h include directly to wmi.c
>
> changes from v2:
> - removed now superfluous return in ath12k_wmi_event_teardown_complete()
> - moved ath12k_wmi_tb declaration to wmi.c & added two functions to
> alloc / free it
> - removed useless error message on memory allocation failure
>
> changes from v1:
> - rebased on ath-next 27401c9b1432
> - changed wording according to Jeff's comment
> - moved alloc/cleanup to new module_init/exit functions in the
> ath12k module as per Baochen's comment
>
> changes from RFC:
> - rebased on ath-next 8e0ab5b9adb7
> - converted missing call sites ath12k_wmi_obss_color_collision_event()
> & ath12k_wmi_pdev_temperature_event()
> - changed alloc order & cleanup path in ath12k_core_alloc() as it seems
> it confused people
> - used sizeof(*tb) in ath12k_wmi_tlv_parse()
> ---
> drivers/net/wireless/ath/ath12k/core.c | 6 +
> drivers/net/wireless/ath/ath12k/wmi.c | 214 +++++++++----------------
> drivers/net/wireless/ath/ath12k/wmi.h | 3 +
> 3 files changed, 84 insertions(+), 139 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
> index c31c47fb5a73..6f0f4bfbf699 100644
> --- a/drivers/net/wireless/ath/ath12k/core.c
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -2256,6 +2256,7 @@ void ath12k_core_deinit(struct ath12k_base *ab)
> void ath12k_core_free(struct ath12k_base *ab)
> {
> timer_delete_sync(&ab->rx_replenish_retry);
> + ath12k_wmi_free();
> destroy_workqueue(ab->workqueue_aux);
> destroy_workqueue(ab->workqueue);
> kfree(ab);
> @@ -2280,6 +2281,9 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
> if (!ab->workqueue_aux)
> goto err_free_wq;
>
> + if (ath12k_wmi_alloc() < 0)
> + goto err_free_wq_aux;
> +
> mutex_init(&ab->core_lock);
> spin_lock_init(&ab->base_lock);
> init_completion(&ab->reset_complete);
> @@ -2314,6 +2318,8 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
>
> return ab;
>
> +err_free_wq_aux:
> + destroy_workqueue(ab->workqueue_aux);
> err_free_wq:
> destroy_workqueue(ab->workqueue);
> err_sc_free:
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> index 65a05a9520ff..2641a76e9543 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.c
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -15,6 +15,8 @@
> #include <linux/time.h>
> #include <linux/of.h>
> #include <linux/cleanup.h>
> +#include <linux/percpu.h>
> +#include <linux/refcount.h>
> #include "core.h"
> #include "debugfs.h"
> #include "debug.h"
> @@ -134,6 +136,10 @@ struct wmi_pdev_set_obss_bitmap_arg {
> const char *label;
> };
>
> +static DEFINE_MUTEX(ath12k_wmi_mutex);
> +static refcount_t ath12k_wmi_refcount = REFCOUNT_INIT(0);
> +static void __percpu *ath12k_wmi_tb = NULL;
Checkpatch complains:
drivers/net/wireless/ath/ath12k/wmi.c:141: do not initialise statics to NULL
> +
> static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = {
> [WMI_TAG_ARRAY_BYTE] = { .min_len = 0 },
> [WMI_TAG_ARRAY_UINT32] = { .min_len = 0 },
> @@ -289,29 +295,19 @@ static int ath12k_wmi_tlv_iter_parse(struct ath12k_base *ab, u16 tag, u16 len,
> return 0;
> }
>
{...}
> #ifdef CONFIG_ATH12K_DEBUGFS
> @@ -11239,3 +11150,28 @@ int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
> dev_kfree_skb(skb);
> return ret;
> }
> +
> +int ath12k_wmi_alloc(void)
> +{
> + guard(mutex)(&ath12k_wmi_mutex);
> +
> + if (!ath12k_wmi_tb) {
> + ath12k_wmi_tb = __alloc_percpu(WMI_TAG_MAX * sizeof(void *),
> + __alignof__(void *));
> + if (!ath12k_wmi_tb)
> + return -ENOMEM;
> + }
> +
> + refcount_inc(&ath12k_wmi_refcount);
With ath12k_wmi_refcount initialized to zero, this will trigger addition
on 0 - use-after-free warning in refcount.
We may have to do refcount_set(&ath12k_wmi_refcount, 1); on tb alloc.
> + return 0;
> +}
> +
> +void ath12k_wmi_free(void)
> +{
> + guard(mutex)(&ath12k_wmi_mutex);
> +
> + if (refcount_dec_and_test(&ath12k_wmi_refcount)) {
> + free_percpu(ath12k_wmi_tb);
> + ath12k_wmi_tb = NULL;
> + }
> +}
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
> index 5ba9b7d3a888..4a34b2ca99ea 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.h
> +++ b/drivers/net/wireless/ath/ath12k/wmi.h
> @@ -6576,4 +6576,7 @@ int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
> struct ath12k_reg_tpc_power_info *param);
> int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
> struct wmi_mlo_link_set_active_arg *param);
> +int ath12k_wmi_alloc(void);
> +void ath12k_wmi_free(void);
> +
> #endif
--
Ramesh
^ permalink raw reply
* Re: [PATCH ath-next v4 0/6] wifi: ath12k: Enable IPQ5424 AHB WiFi device
From: Krzysztof Kozlowski @ 2026-04-04 5:23 UTC (permalink / raw)
To: Baochen Qiang, Raj Kumar Bhagat, Johannes Berg, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jeff Johnson
Cc: linux-wireless, devicetree, linux-kernel, ath12k,
Saravanakumar Duraisamy, Sowmiya Sree Elavalagan
In-Reply-To: <5a606f7d-6665-4b0c-bbbe-32538b2315b6@oss.qualcomm.com>
On 03/04/2026 11:13, Baochen Qiang wrote:
>>
>> .../bindings/net/wireless/qcom,ipq5332-wifi.yaml | 1 +
>> drivers/net/wireless/ath/ath12k/ahb.c | 36 +++++----
>> drivers/net/wireless/ath/ath12k/ahb.h | 1 +
>> drivers/net/wireless/ath/ath12k/ce.h | 13 ++-
>> drivers/net/wireless/ath/ath12k/core.h | 1 +
>> drivers/net/wireless/ath/ath12k/wifi7/ahb.c | 8 ++
>> drivers/net/wireless/ath/ath12k/wifi7/hal.c | 7 ++
>> drivers/net/wireless/ath/ath12k/wifi7/hal.h | 3 +
>> .../net/wireless/ath/ath12k/wifi7/hal_qcn9274.c | 88 ++++++++++++++++++++
>> .../net/wireless/ath/ath12k/wifi7/hal_qcn9274.h | 1 +
>> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 93 +++++++++++++++++++++-
>> 11 files changed, 231 insertions(+), 21 deletions(-)
>> ---
>> base-commit: 15551ababf6d4e857f2101366a0c3eaa86dd822c
>> change-id: 20260331-ath12k-ipq5424-cddb63a46a97
>>
>
> only nit in patch 2/6, so for patches 2-6/6:
>
> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
It does not work like this. Replying to cover letter causes that all
patches will get it. Provide detailed review and response to each email
in such case.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH ath-next] wifi: ath11k: cancel SSR work items during PCI shutdown
From: Wei Zhang @ 2026-04-04 4:30 UTC (permalink / raw)
To: jeff.johnson; +Cc: ath11k, linux-wireless, linux-kernel, Wei Zhang
A reboot can crash the kernel if it overlaps with WLAN firmware crash
recovery (SSR). The crash is a NULL pointer dereference in the MHI teardown
path while freeing DMA-backed MHI contexts.
Simplified trace:
dma_free_attrs
mhi_deinit_dev_ctxt [mhi]
ath11k_pci_power_down [ath11k_pci]
ath11k_pci_shutdown [ath11k_pci]
device_shutdown
kernel_restart
On the host side, SSR is driven by the MHI RDDM callback, which queues
reset_work to perform device recovery. reset_work power-cycles the device
by calling ath11k_hif_power_down() followed by ath11k_hif_power_up(). The
power-down phase deinitializes MHI and frees DMA resources.
Shutdown/reboot runs fully asynchronously with this RDDM-driven SSR
recovery flow. As a result, the shutdown path
(ath11k_pci_shutdown() -> ath11k_pci_power_down()) can race with the SSR
recovery sequence.
Fix this by canceling SSR-related work items during PCI shutdown, marking
the device as unregistering, and serializing the RDDM callback path that
checks and queues reset_work. This ensures that no new SSR recovery work
can be queued once teardown has started, and that any in-flight recovery
work is fully synchronized before device power-down, preventing MHI
teardown and DMA resource freeing from running more than once.
Note: This issue only affects PCI/MHI-based devices. AHB-based ath11k
devices do not queue reset_work in normal SSR flows.
Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04866.5-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1
Fixes: 13da397f884d ("ath11k: add support for device recovery for QCA6390/WCN6855")
Fixes: 5edbb148bc57 ("wifi: ath11k: Add firmware coredump collection support")
Signed-off-by: Wei Zhang <wei.zhang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath11k/mhi.c | 4 +++-
drivers/net/wireless/ath/ath11k/pci.c | 8 ++++++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index f994233df2bb..a6c9ff112c68 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/msi.h>
@@ -282,8 +282,10 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
break;
}
+ spin_lock_bh(&ab->base_lock);
if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)))
queue_work(ab->workqueue_aux, &ab->reset_work);
+ spin_unlock_bh(&ab->base_lock);
break;
default:
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 7114eca8810d..35bb9e7a63a2 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -1210,6 +1210,14 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
+
+ spin_lock_bh(&ab->base_lock);
+ set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
+ spin_unlock_bh(&ab->base_lock);
+
+ cancel_work_sync(&ab->reset_work);
+ cancel_work_sync(&ab->dump_work);
+
ath11k_pci_power_down(ab, false);
}
base-commit: 15551ababf6d4e857f2101366a0c3eaa86dd822c
--
2.34.1
^ permalink raw reply related
* Re: [BUG] wifi: rtw88: Hard system freeze on RTL8821CE when power_save is enabled (LPS/ASPM conflict)
From: LB F @ 2026-04-03 21:47 UTC (permalink / raw)
To: Ping-Ke Shih
Cc: Bitterblue Smith, linux-wireless@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <5fb2f699626b483b8a0a537960b274f0@realtek.com>
Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> If we can't find the reason for these weird frames, maybe the best
> way to filter them out is to check RTW_RX_DESC_W0_DRV_INFO_SIZE.
Hi Bitterblue, Ping-Ke,
I have a new crash to report that shows a different failure mode
from the garbage RX data, with some characteristics I haven't
seen before.
=== NEW INCIDENT: 2026-04-03 ===
The system froze approximately 1 second after Wi-Fi association
on a fresh cold boot (not resume from hibernation). Hard power-off
was required.
Timeline:
17:16:16 Cold boot (PM: Image not found — no hibernation image)
17:16:38 wlan0 associated with AP (6c:68:a4:1c:97:5b)
17:16:39 First "pci bus timeout" + mac80211 WARNING
17:16:39-17:17:00 System frozen, hard reset required
Kernel: 6.19.10-1-cachyos (PREEMPT full, Clang/LLVM)
Patches applied: DMI quirk (ASPM+LPS disabled), rate validation v2,
Bitterblue's diagnostic hex dump in query_phy_status.
=== THREE DIFFERENCES FROM PREVIOUS CRASHES ===
1) Zero "unused phy status page" events.
Every previous incident had a burst of these messages before
or during the crash. This time there were none at all. The
corrupted data appears to have gone straight to mac80211 without
triggering query_phy_status — likely because PHYST=0 in the
corrupted descriptors, so the diagnostic hex dump never fired.
2) Cold boot, 1 second after initial association.
All previous crashes occurred after minutes to hours of uptime
or shortly after hibernation resume. This one happened on a
fresh boot before any power-state transition. ASPM and LPS Deep
were already disabled by the DMI quirk.
3) Hang mechanism: infinite "pci bus timeout" loop.
Not the NULL dereference (Bug 221286) and not the ASPM deadlock
(Bug 221195). The loop produced 547 "pci bus timeout" messages
and 41 mac80211 WARNINGs over 21 seconds.
=== HANG MECHANISM (my reading of the code, please correct if wrong) ===
The crash appears to follow this sequence in rtw_pci_rx_napi():
while (count--) {
rtw_pci_dma_check(rtwdev, ring, cur_rp); // [A]
...
rtw_rx_query_rx_desc(rtwdev, rx_desc, ...); // [B]
...
ieee80211_rx_napi(rtwdev->hw, NULL, new, napi); // [C]
}
At [A], rtw_pci_dma_check() detects an RX tag mismatch and prints
the warning, but returns void and the loop continues. At [B], since
PHYST=0, query_phy_status is not called. At [C], the garbage frame
reaches ieee80211_rx_list(), triggering WARNING at rx.c:896.
The RBP values across the 41 WARNING traces form a monotonically
increasing sequence from 0x55 to 0x1FF, which looks like cur_rp
cycling through the ring. Once exhausted, rtw_pci_get_hw_rx_ring_nr()
reads more entries from hardware (which is in a bad state), and the
loop restarts. The NAPI poll never returns.
The execution context migrated from irq/58-rtw_pci (PID 635,
170 traces) to ksoftirqd/1 (PID 26, 216 traces) as the softirq
was deferred, but the loop continued in both.
=== FIRST WARNING (full trace) ===
WARNING: net/mac80211/rx.c:896 at ieee80211_rx_list+0x1033/0x1040
[mac80211], CPU#1: irq/58-rtw_pci/635
RAX: 0000000000020100 RBX: 0000000000000000 RCX: 0000000000000004
RDX: 0000000000000000 RSI: ffff8e56c7bb2f18 RDI: 0000000000000000
RBP: 0000000000000055 R08: 0000000000000004 R09: 0000000000000000
Call Trace:
<IRQ>
ieee80211_rx_napi+0x51/0xe0 [mac80211]
rtw_pci_rx_napi+0x2fd/0x400 [rtw_pci]
rtw_pci_napi_poll+0x79/0x1d0 [rtw_pci]
net_rx_action+0x195/0x290
handle_softirqs+0x12d/0x1c0
do_softirq+0x56/0x70
</IRQ>
<TASK>
__local_bh_enable_ip.cold+0xc/0x11
rtw_pci_interrupt_threadfn+0x270/0x360 [rtw_pci]
irq_thread_fn+0x24/0x50
irq_thread+0xbc/0x160
kthread+0x205/0x280
</TASK>
=== NAIVE HARDENING IDEA (please ignore if this is wrong) ===
I am not a kernel developer and I may be misreading the code, but
I wondered if making rtw_pci_dma_check() return a value and
skipping the frame on tag mismatch might prevent the infinite loop,
independently of the DRV_INFO_SIZE filter. Something along these
lines:
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
-static void rtw_pci_dma_check(struct rtw_dev *rtwdev,
+static bool rtw_pci_dma_check(struct rtw_dev *rtwdev,
struct rtw_pci_rx_ring *rx_ring,
u32 idx)
{
- if (total_pkt_size != rtwpci->rx_tag)
+ if (total_pkt_size != rtwpci->rx_tag) {
rtw_warn(rtwdev, "pci bus timeout, check dma status\n");
+ return false;
+ }
rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX;
+ return true;
}
while (count--) {
- rtw_pci_dma_check(rtwdev, ring, cur_rp);
+ if (!rtw_pci_dma_check(rtwdev, ring, cur_rp))
+ goto next_rp;
I am sure there are considerations I am missing. Please treat this
only as a description of what I observed, not as a proposed patch.
=== SUMMARY ===
The garbage RX data from this chip now appears to cause at least
three distinct failure modes:
1) Bug 221195: ASPM/LPS deadlock (fixed by DMI quirk)
2) Bug 221286: NULL dereference via C2H_ADAPTIVITY misinterpretation
3) This incident: infinite loop triggered by DMA tag mismatch
I wanted to report this new failure mode in case it is useful for
your work on the DRV_INFO_SIZE filter. I can provide the full dmesg
from this crash (7828 lines) if it would be helpful — just let me
know.
Best regards,
Oleksandr Havrylov
^ permalink raw reply
* Re: [PATCH v2 7/7] arm64: dts: qcom: milos-fairphone-fp6: Enable WiFi
From: Dmitry Baryshkov @ 2026-04-03 19:35 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-7-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:53PM +0200, Luca Weiss wrote:
> Configure and enable the WiFi node, and add the required pinctrl to
> provide the sleep clock from the PMK8550 (PMK7635) to WCN6755.
>
> Thanks to Alexander Koskovich for helping with the bringup, adding
> the missing pinctrl to make the WPSS stop crashing.
>
> Link: https://lore.kernel.org/linux-arm-msm/DBF7OWAWQ94M.FSCP4DPF8ZJY@fairphone.com/
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> index db72418b7195..d8ac495ca7c8 100644
> --- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> +++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> @@ -242,7 +242,7 @@ wcn6750-pmu {
>
> clocks = <&rpmhcc RPMH_RF_CLK1>;
>
> - pinctrl-0 = <&bluetooth_enable_default>;
> + pinctrl-0 = <&bluetooth_enable_default>, <&pmk8550_sleep_clk_default>;
> pinctrl-names = "default";
>
> regulators {
> @@ -766,6 +766,17 @@ &pmiv0104_eusb2_repeater {
> qcom,tune-usb2-preem = /bits/ 8 <0x6>;
> };
>
> +&pmk8550_gpios {
> + pmk8550_sleep_clk_default: sleep-clk-default-state {
> + pins = "gpio5";
> + function = "func1";
> + input-disable;
> + output-enable;
Hmm, if it's a sleep_clk, should it not be handled via the power
sequencer?
> + bias-disable;
> + power-source = <0>;
> + };
> +};
> +
> &pmr735b_gpios {
> s1j_enable_default: s1j-enable-default-state {
> pins = "gpio1";
> @@ -1049,3 +1060,9 @@ &usb_1_hsphy {
>
> status = "okay";
> };
> +
> +&wifi {
> + qcom,calibration-variant = "Fairphone_Gen_6";
> +
> + status = "okay";
> +};
>
> --
> 2.53.0
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v2 6/7] arm64: dts: qcom: milos-fairphone-fp6: Enable Bluetooth
From: Dmitry Baryshkov @ 2026-04-03 19:33 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-6-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:52PM +0200, Luca Weiss wrote:
> Add the nodes to describe the WCN6755 chip with its PMU and Bluetooth
> parts.
>
> Thanks to Alexander Koskovich for helping with the bringup, adding
> 'clocks' to the PMU node to make Bluetooth work.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 174 +++++++++++++++++++++++
> 1 file changed, 174 insertions(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH] wifi: brcmsmac: phy_lcn: Remove dead code in wlc_lcnphy_radio_2064_channel_tune_4313()
From: Chelsy Ratnawat @ 2026-04-03 19:33 UTC (permalink / raw)
To: arend.vanspriel
Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl,
Chelsy Ratnawat
The variable rfpll_doubler is initialized to 0 and then unconditionally
set to 1 on the very next line, making the subsequent check for
!rfpll_doubler always evaluate to false. This results in logically
dead code that has never been executed.
Remove the unused variable, the unreachable conditional branch, and
simplify the fpfd calculation to directly use the PLL doubler values.
Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
---
.../broadcom/brcm80211/brcmsmac/phy/phy_lcn.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
index 8cec5ad79fda..d65a68045ca8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1607,7 +1607,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
{
uint i;
const struct chan_info_2064_lcnphy *ci;
- u8 rfpll_doubler = 0;
u8 pll_pwrup, pll_pwrup_ovr;
s32 qFcal;
u8 d15, d16, f16, e44, e45;
@@ -1618,18 +1617,12 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
u16 g30, d28;
ci = &chan_info_2064_lcnphy[0];
- rfpll_doubler = 1;
mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
- if (!rfpll_doubler) {
- loop_bw = PLL_2064_LOOP_BW;
- d30 = PLL_2064_D30;
- } else {
- loop_bw = PLL_2064_LOOP_BW_DOUBLER;
- d30 = PLL_2064_D30_DOUBLER;
- }
+ loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+ d30 = PLL_2064_D30_DOUBLER;
if (CHSPEC_IS2G(pi->radio_chanspec)) {
for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
@@ -1669,7 +1662,7 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
e44 = 0;
e45 = 0;
- fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+ fpfd = pi->xtalfreq << 1;
if (pi->xtalfreq > 26000000)
e44 = 1;
if (pi->xtalfreq > 52000000)
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 5/7] arm64: dts: qcom: milos: Add WCN6755 WiFi node
From: Dmitry Baryshkov @ 2026-04-03 19:33 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-5-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:51PM +0200, Luca Weiss wrote:
> Add a node for the WCN6755 WiFi found with the Milos SoC.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos.dtsi | 46 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 46 insertions(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v2 4/7] arm64: dts: qcom: milos: Split up uart11 pinctrl
From: Dmitry Baryshkov @ 2026-04-03 19:32 UTC (permalink / raw)
To: Luca Weiss
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
~postmarketos/upstreaming, phone-devel, linux-arm-msm,
linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-4-393322b27c5f@fairphone.com>
On Fri, Apr 03, 2026 at 03:52:50PM +0200, Luca Weiss wrote:
> In order to set the pinctrl for the individual CTS, RTS, TX and RX pins,
> split up the pinctrl configuration into 4 nodes so that boards can set
> some properties separately.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos.dtsi | 28 ++++++++++++++++++----------
> 1 file changed, 18 insertions(+), 10 deletions(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox