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

Merge tag 'wireless-2025-10-30' of...

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

Johannes Berg says:

====================
Couple of new fixes:

 - ath10k: revert a patch that had caused issues on some devices
 - cfg80211/mac80211: use hrtimers for some things where the
                      precise timing matters
 - zd1211rw: fix a long-standing potential leak

* tag 'wireless-2025-10-30' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless:
  wifi: zd1211rw: fix potential memory leak in __zd_usb_enable_rx()
  wifi: mac80211: use wiphy_hrtimer_work for csa.switch_work
  wifi: mac80211: use wiphy_hrtimer_work for ml_reconf_work
  wifi: mac80211: use wiphy_hrtimer_work for ttlm_work
  wifi: cfg80211: add an hrtimer based delayed work item
  Revert "wifi: ath10k: avoid unnecessary wait for service ready message"
====================

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


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e5763491 70e83354
Loading
Loading
Loading
Loading
+20 −19
Original line number Diff line number Diff line
@@ -1764,34 +1764,35 @@ void ath10k_wmi_put_wmi_channel(struct ath10k *ar, struct wmi_channel *ch,

int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
	unsigned long timeout = jiffies + WMI_SERVICE_READY_TIMEOUT_HZ;
	unsigned long time_left, i;

	time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
						WMI_SERVICE_READY_TIMEOUT_HZ);
	if (!time_left) {
		/* Sometimes the PCI HIF doesn't receive interrupt
		 * for the service ready message even if the buffer
		 * was completed. PCIe sniffer shows that it's
		 * because the corresponding CE ring doesn't fires
	 * it. Workaround here by polling CE rings. Since
	 * the message could arrive at any time, continue
	 * polling until timeout.
		 * it. Workaround here by polling CE rings once.
		 */
	do {
		ath10k_warn(ar, "failed to receive service ready completion, polling..\n");

		for (i = 0; i < CE_COUNT; i++)
			ath10k_hif_send_complete_check(ar, i, 1);

		/* The 100 ms granularity is a tradeoff considering scheduler
		 * overhead and response latency
		 */
		time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
							msecs_to_jiffies(100));
		if (time_left)
			return 0;
	} while (time_before(jiffies, timeout));

	ath10k_warn(ar, "failed to receive service ready completion\n");
							WMI_SERVICE_READY_TIMEOUT_HZ);
		if (!time_left) {
			ath10k_warn(ar, "polling timed out\n");
			return -ETIMEDOUT;
		}

		ath10k_warn(ar, "service ready completion received, continuing normally\n");
	}

	return 0;
}

int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
{
	unsigned long time_left;
+1 −0
Original line number Diff line number Diff line
@@ -791,6 +791,7 @@ static int __zd_usb_enable_rx(struct zd_usb *usb)
	if (urbs) {
		for (i = 0; i < RX_URBS_COUNT; i++)
			free_rx_urb(urbs[i]);
		kfree(urbs);
	}
	return r;
}
+78 −0
Original line number Diff line number Diff line
@@ -6435,6 +6435,11 @@ static inline void wiphy_delayed_work_init(struct wiphy_delayed_work *dwork,
 * after wiphy_lock() was called. Therefore, wiphy_cancel_work() can
 * use just cancel_work() instead of cancel_work_sync(), it requires
 * being in a section protected by wiphy_lock().
 *
 * Note that these are scheduled with a timer where the accuracy
 * becomes less the longer in the future the scheduled timer is. Use
 * wiphy_hrtimer_work_queue() if the timer must be not be late by more
 * than approximately 10 percent.
 */
void wiphy_delayed_work_queue(struct wiphy *wiphy,
			      struct wiphy_delayed_work *dwork,
@@ -6506,6 +6511,79 @@ void wiphy_delayed_work_flush(struct wiphy *wiphy,
bool wiphy_delayed_work_pending(struct wiphy *wiphy,
				struct wiphy_delayed_work *dwork);

struct wiphy_hrtimer_work {
	struct wiphy_work work;
	struct wiphy *wiphy;
	struct hrtimer timer;
};

enum hrtimer_restart wiphy_hrtimer_work_timer(struct hrtimer *t);

static inline void wiphy_hrtimer_work_init(struct wiphy_hrtimer_work *hrwork,
					   wiphy_work_func_t func)
{
	hrtimer_setup(&hrwork->timer, wiphy_hrtimer_work_timer,
		      CLOCK_BOOTTIME, HRTIMER_MODE_REL);
	wiphy_work_init(&hrwork->work, func);
}

/**
 * wiphy_hrtimer_work_queue - queue hrtimer work for the wiphy
 * @wiphy: the wiphy to queue for
 * @hrwork: the high resolution timer worker
 * @delay: the delay given as a ktime_t
 *
 * Please refer to wiphy_delayed_work_queue(). The difference is that
 * the hrtimer work uses a high resolution timer for scheduling. This
 * may be needed if timeouts might be scheduled further in the future
 * and the accuracy of the normal timer is not sufficient.
 *
 * Expect a delay of a few milliseconds as the timer is scheduled
 * with some slack and some more time may pass between queueing the
 * work and its start.
 */
void wiphy_hrtimer_work_queue(struct wiphy *wiphy,
			      struct wiphy_hrtimer_work *hrwork,
			      ktime_t delay);

/**
 * wiphy_hrtimer_work_cancel - cancel previously queued hrtimer work
 * @wiphy: the wiphy, for debug purposes
 * @hrtimer: the hrtimer work to cancel
 *
 * Cancel the work *without* waiting for it, this assumes being
 * called under the wiphy mutex acquired by wiphy_lock().
 */
void wiphy_hrtimer_work_cancel(struct wiphy *wiphy,
			       struct wiphy_hrtimer_work *hrtimer);

/**
 * wiphy_hrtimer_work_flush - flush previously queued hrtimer work
 * @wiphy: the wiphy, for debug purposes
 * @hrwork: the hrtimer work to flush
 *
 * Flush the work (i.e. run it if pending). This must be called
 * under the wiphy mutex acquired by wiphy_lock().
 */
void wiphy_hrtimer_work_flush(struct wiphy *wiphy,
			      struct wiphy_hrtimer_work *hrwork);

/**
 * wiphy_hrtimer_work_pending - Find out whether a wiphy hrtimer
 * work item is currently pending.
 *
 * @wiphy: the wiphy, for debug purposes
 * @hrwork: the hrtimer work in question
 *
 * Return: true if timer is pending, false otherwise
 *
 * Please refer to the wiphy_delayed_work_pending() documentation as
 * this is the equivalent function for hrtimer based delayed work
 * items.
 */
bool wiphy_hrtimer_work_pending(struct wiphy *wiphy,
				struct wiphy_hrtimer_work *hrwork);

/**
 * enum ieee80211_ap_reg_power - regulatory power for an Access Point
 *
+1 −1
Original line number Diff line number Diff line
@@ -1290,7 +1290,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
				 &link->csa.finalize_work);
		break;
	case NL80211_IFTYPE_STATION:
		wiphy_delayed_work_queue(sdata->local->hw.wiphy,
		wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
					 &link->u.mgd.csa.switch_work, 0);
		break;
	case NL80211_IFTYPE_UNSPECIFIED:
+4 −4
Original line number Diff line number Diff line
@@ -612,11 +612,11 @@ struct ieee80211_if_managed {
	u8 *assoc_req_ies;
	size_t assoc_req_ies_len;

	struct wiphy_delayed_work ml_reconf_work;
	struct wiphy_hrtimer_work ml_reconf_work;
	u16 removed_links;

	/* TID-to-link mapping support */
	struct wiphy_delayed_work ttlm_work;
	struct wiphy_hrtimer_work ttlm_work;
	struct ieee80211_adv_ttlm_info ttlm_info;
	struct wiphy_work teardown_ttlm_work;

@@ -1017,10 +1017,10 @@ struct ieee80211_link_data_managed {
	bool operating_11g_mode;

	struct {
		struct wiphy_delayed_work switch_work;
		struct wiphy_hrtimer_work switch_work;
		struct cfg80211_chan_def ap_chandef;
		struct ieee80211_parsed_tpe tpe;
		unsigned long time;
		ktime_t time;
		bool waiting_bcn;
		bool ignored_same_chan;
		bool blocked_tx;
Loading