Commit d02af27f authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'wireless-2024-12-10' of...

Merge tag 'wireless-2024-12-10' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

Johannes Berg says:

====================
A small set of fixes:
 - avoid CSA warnings during link removal
   (by changing link bitmap after remove)
 - fix # of spatial streams initialisation
 - fix queues getting stuck in some CSA cases
   and resume failures
 - fix interface address when switching monitor mode
 - fix MBSS change flags 32-bit stack corruption
 - more UBSAN __counted_by "fixes" ...
 - fix link ID netlink validation

* tag 'wireless-2024-12-10' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless:
  wifi: cfg80211: sme: init n_channels before channels[] access
  wifi: mac80211: fix station NSS capability initialization order
  wifi: mac80211: fix vif addr when switching from monitor to station
  wifi: mac80211: fix a queue stall in certain cases of CSA
  wifi: mac80211: wake the queues in case of failure in resume
  wifi: cfg80211: clear link ID from bitmap during link delete after clean up
  wifi: mac80211: init cnt before accessing elem in ieee80211_copy_mbssid_beacon
  wifi: mac80211: fix mbss changed flags corruption on 32 bit systems
  wifi: nl80211: fix NL80211_ATTR_MLO_LINK_ID off-by-one
====================

Link: https://patch.msgid.link/20241210130145.28618-3-johannes@sipsolutions.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 06d64ab4 f1d3334d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1972,7 +1972,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
	if (csa_err_mask & (CS_ERR_COUNT_ERROR |
			    CS_ERR_LONG_DELAY_AFTER_CS |
			    CS_ERR_TX_BLOCK_TIMER_EXPIRED))
		ieee80211_channel_switch_disconnect(vif, true);
		ieee80211_channel_switch_disconnect(vif);
	rcu_read_unlock();
}

+4 −3
Original line number Diff line number Diff line
@@ -1987,6 +1987,8 @@ enum ieee80211_neg_ttlm_res {
 * @neg_ttlm: negotiated TID to link mapping info.
 *	see &struct ieee80211_neg_ttlm.
 * @addr: address of this interface
 * @addr_valid: indicates if the address is actively used. Set to false for
 *	passive monitor interfaces, true in all other cases.
 * @p2p: indicates whether this AP or STA interface is a p2p
 *	interface, i.e. a GO or p2p-sta respectively
 * @netdev_features: tx netdev features supported by the hardware for this
@@ -2026,6 +2028,7 @@ struct ieee80211_vif {
	u16 valid_links, active_links, dormant_links, suspended_links;
	struct ieee80211_neg_ttlm neg_ttlm;
	u8 addr[ETH_ALEN] __aligned(2);
	bool addr_valid;
	bool p2p;

	u8 cab_queue;
@@ -6795,14 +6798,12 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
/**
 * ieee80211_channel_switch_disconnect - disconnect due to channel switch error
 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
 * @block_tx: if %true, do not send deauth frame.
 *
 * Instruct mac80211 to disconnect due to a channel switch error. The channel
 * switch can request to block the tx and so, we need to make sure we do not send
 * a deauth frame in this case.
 */
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
					 bool block_tx);
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif);

/**
 * ieee80211_request_smps - request SM PS transition
+11 −6
Original line number Diff line number Diff line
@@ -1088,13 +1088,13 @@ ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
{
	int i, offset = 0;

	dst->cnt = src->cnt;
	for (i = 0; i < src->cnt; i++) {
		memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
		dst->elem[i].len = src->elem[i].len;
		dst->elem[i].data = pos + offset;
		offset += dst->elem[i].len;
	}
	dst->cnt = src->cnt;

	return offset;
}
@@ -1935,6 +1935,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
						    params->eht_capa_len,
						    link_sta);

	ieee80211_sta_init_nss(link_sta);

	if (params->opmode_notif_used) {
		/* returned value is only needed for rc update, but the
		 * rc isn't initialized here yet, so ignore it
@@ -1944,8 +1946,6 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
					      sband->band);
	}

	ieee80211_sta_init_nss(link_sta);

	return 0;
}

@@ -3726,13 +3726,12 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
}
EXPORT_SYMBOL(ieee80211_csa_finish);

void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_local *local = sdata->local;

	sdata->csa_blocked_queues = block_tx;
	sdata_info(sdata, "channel switch failed, disconnecting\n");
	wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work);
}
@@ -5046,10 +5045,16 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
				    unsigned int link_id)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
	u16 new_links = wdev->valid_links & ~BIT(link_id);

	lockdep_assert_wiphy(sdata->local->hw.wiphy);

	ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
	/* During the link teardown process, certain functions require the
	 * link_id to remain in the valid_links bitmap. Therefore, instead
	 * of removing the link_id from the bitmap, pass a masked value to
	 * simulate as if link_id does not exist anymore.
	 */
	ieee80211_vif_set_links(sdata, new_links, 0);
}

static int
+40 −9
Original line number Diff line number Diff line
@@ -1104,8 +1104,6 @@ struct ieee80211_sub_if_data {

	unsigned long state;

	bool csa_blocked_queues;

	char name[IFNAMSIZ];

	struct ieee80211_fragment_cache frags;
@@ -2412,17 +2410,13 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
				   struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_hdr *hdr, bool ack, u16 tx_time);

unsigned int
ieee80211_get_vif_queues(struct ieee80211_local *local,
			 struct ieee80211_sub_if_data *sdata);
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
				     unsigned long queues,
				     enum queue_stop_reason reason,
				     bool refcounted);
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
			       struct ieee80211_sub_if_data *sdata,
			       enum queue_stop_reason reason);
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
			       struct ieee80211_sub_if_data *sdata,
			       enum queue_stop_reason reason);
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
				     unsigned long queues,
				     enum queue_stop_reason reason,
@@ -2433,6 +2427,43 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
				    enum queue_stop_reason reason,
				    bool refcounted);
static inline void
ieee80211_stop_vif_queues(struct ieee80211_local *local,
			  struct ieee80211_sub_if_data *sdata,
			  enum queue_stop_reason reason)
{
	ieee80211_stop_queues_by_reason(&local->hw,
					ieee80211_get_vif_queues(local, sdata),
					reason, true);
}

static inline void
ieee80211_wake_vif_queues(struct ieee80211_local *local,
			  struct ieee80211_sub_if_data *sdata,
			  enum queue_stop_reason reason)
{
	ieee80211_wake_queues_by_reason(&local->hw,
					ieee80211_get_vif_queues(local, sdata),
					reason, true);
}
static inline void
ieee80211_stop_vif_queues_norefcount(struct ieee80211_local *local,
				     struct ieee80211_sub_if_data *sdata,
				     enum queue_stop_reason reason)
{
	ieee80211_stop_queues_by_reason(&local->hw,
					ieee80211_get_vif_queues(local, sdata),
					reason, false);
}
static inline void
ieee80211_wake_vif_queues_norefcount(struct ieee80211_local *local,
				     struct ieee80211_sub_if_data *sdata,
				     enum queue_stop_reason reason)
{
	ieee80211_wake_queues_by_reason(&local->hw,
					ieee80211_get_vif_queues(local, sdata),
					reason, false);
}
void ieee80211_add_pending_skb(struct ieee80211_local *local,
			       struct sk_buff *skb);
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
+8 −15
Original line number Diff line number Diff line
@@ -278,13 +278,8 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata,
	ret = eth_mac_addr(sdata->dev, sa);

	if (ret == 0) {
		if (check_dup) {
		memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
		ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
		} else {
			memset(sdata->vif.addr, 0, ETH_ALEN);
			memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
		}
	}

	/* Regardless of eth_mac_addr() return we still want to add the
@@ -1323,6 +1318,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
		}
	}

	sdata->vif.addr_valid = sdata->vif.type != NL80211_IFTYPE_MONITOR ||
				(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE);
	switch (sdata->vif.type) {
	case NL80211_IFTYPE_AP_VLAN:
		/* no need to tell driver, but set carrier and chanctx */
@@ -2374,18 +2371,14 @@ void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata)
	if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA))
		return;

	ieee80211_stop_vif_queues(local, sdata,
	ieee80211_stop_vif_queues_norefcount(local, sdata,
					     IEEE80211_QUEUE_STOP_REASON_CSA);
	sdata->csa_blocked_queues = true;
}

void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;

	if (sdata->csa_blocked_queues) {
		ieee80211_wake_vif_queues(local, sdata,
	ieee80211_wake_vif_queues_norefcount(local, sdata,
					     IEEE80211_QUEUE_STOP_REASON_CSA);
		sdata->csa_blocked_queues = false;
	}
}
Loading