From patchwork Thu Apr 18 09:52:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 790168 Received: from sipsolutions.net (s3.sipsolutions.net [168.119.38.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5748715B13A for ; Thu, 18 Apr 2024 09:52:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.38.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713433948; cv=none; b=lb1sgib8SqjXErxFph88la4q/Ai5kugu8UFLRshQjaT2nVpIbqGw6q3lwuazzG7Lk7NMbfK0biUFX7lsP8R6zxy7leIumECcZOQyDZTfK6ELg2tiPQLSNYr6bhWII65/WOOtJE/BmkaumvO9eXUUK1RZxVvNs+Yu3p/Y7BlD16Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713433948; c=relaxed/simple; bh=y0E/XH/beM4W1Lq+ROyL0RRrLz52zl3EjQfFc+22CKc=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=SSWTDzYj7fNeSzS8dA8XR/8QQSPPw5UWBu1CvOH3WtbFpCCAW34S9mgB04ZKe1YwN4kblhApAUB5saoW/V/yvsTLCn1yKbZy3wpGq02/RIkssj/qBup2Wg5qzNGUzYjICvu7MSlGYMAEBkguIv4K3kSG7dfNsZfdnzGsaBL0orA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net; spf=pass smtp.mailfrom=sipsolutions.net; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b=jg8ISTSZ; arc=none smtp.client-ip=168.119.38.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b="jg8ISTSZ" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-To:Resent-Cc: Resent-Message-ID:In-Reply-To:References; bh=m9/z3tJCZh8Mj88/v5Ebby07LUtRPK+nJ0OiyEm+F08=; t=1713433946; x=1714643546; b=jg8ISTSZrRruj44NCEAcWKZA8CajNHrV1jTNQP1z9mKmR4SzWsvcTei8JyTgjK8qr8lfbW+liek WIxqUg6KPakjIhdNA19a5hP03Gqpy9KEipuHnrX+FD7OD0BH3U2ApBV6XJdNiwTIp3eo7FxTA0Rpj lkk5nLSudWQouo4XsUv4r0ghfJqxrFtruXTqvpX6SxqqNlolVAqnIO4xty9z8UyXdMlEH3nb03EmW 1LivwNvoyVQ6JWkSEFX9YNeggwYhSTYuSXACrBkVh0r/V16OaowaDBDwyEK6f+6FWj/v/l0HwxGGl jl/oPPWxR4WEpUj///Fk5sswWNwPFwGEgosw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1rxORL-0000000CM0y-2YnK; Thu, 18 Apr 2024 11:52:23 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg , Miriam Rachel Korenblit Subject: [PATCH wireless-next 1/3] wifi: mac80211: reserve chanctx during find Date: Thu, 18 Apr 2024 11:52:19 +0200 Message-ID: <20240418115219.94ea84c8ee1e.I0b247dbc0cd937ae6367bc0fc7e8d156b5d5f9b1@changeid> X-Mailer: git-send-email 2.44.0 Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Johannes Berg When searching for a chanctx for re-use, it's later adjusted and assigned. It may also be that another one is already assigned to the link in question, so unassign can also happen. In short, the driver is called multiple times. During these callbacks, it may thus change active links (on another interface), which then can in turn cause the found chanctx (that's going to be reused) to get removed and freed. To avoid this, temporarily assign it to the reserved chanctx and track the link that wants to use it in the reserved_links list. This causes the ieee80211_chanctx_refcount() to be increased by one during these operations, thus avoiding the free. Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 5a7fb0e4f89d..6d0148dea126 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -547,8 +547,10 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, _ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL); } +/* Note: if successful, the returned chanctx is reserved for the link */ static struct ieee80211_chanctx * ieee80211_find_chanctx(struct ieee80211_local *local, + struct ieee80211_link_data *link, const struct ieee80211_chan_req *chanreq, enum ieee80211_chanctx_mode mode) { @@ -560,6 +562,9 @@ ieee80211_find_chanctx(struct ieee80211_local *local, if (mode == IEEE80211_CHANCTX_EXCLUSIVE) return NULL; + if (WARN_ON(link->reserved_chanctx)) + return NULL; + list_for_each_entry(ctx, &local->chanctx_list, list) { const struct ieee80211_chan_req *compat; @@ -578,6 +583,16 @@ ieee80211_find_chanctx(struct ieee80211_local *local, if (!compat) continue; + /* + * Reserve the chanctx temporarily, as the driver might change + * active links during callbacks we make into it below and/or + * later during assignment, which could (otherwise) cause the + * context to actually be removed. + */ + link->reserved_chanctx = ctx; + list_add(&link->reserved_chanctx_list, + &ctx->reserved_links); + ieee80211_change_chanctx(local, ctx, ctx, compat); return ctx; @@ -1701,6 +1716,7 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link, struct ieee80211_local *local = sdata->local; struct ieee80211_chanctx *ctx; u8 radar_detect_width = 0; + bool reserved = false; int ret; lockdep_assert_wiphy(local->hw.wiphy); @@ -1727,8 +1743,11 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link, __ieee80211_link_release_channel(link, false); - ctx = ieee80211_find_chanctx(local, chanreq, mode); - if (!ctx) + ctx = ieee80211_find_chanctx(local, link, chanreq, mode); + /* Note: context is now reserved */ + if (ctx) + reserved = true; + else ctx = ieee80211_new_chanctx(local, chanreq, mode); if (IS_ERR(ctx)) { ret = PTR_ERR(ctx); @@ -1738,6 +1757,14 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link, ieee80211_link_update_chanreq(link, chanreq); ret = ieee80211_assign_link_chanctx(link, ctx); + + if (reserved) { + /* remove reservation */ + WARN_ON(link->reserved_chanctx != ctx); + link->reserved_chanctx = NULL; + list_del(&link->reserved_chanctx_list); + } + if (ret) { /* if assign fails refcount stays the same */ if (ieee80211_chanctx_refcount(local, ctx) == 0) From patchwork Thu Apr 18 09:52:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 790467 Received: from sipsolutions.net (s3.sipsolutions.net [168.119.38.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48E9015B13E for ; Thu, 18 Apr 2024 09:52:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.38.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713433949; cv=none; b=feuqpE3AtkJczLVMe7GKtz4yX6tcVZjXOQ2onav5/QN+w9R05oXqhRJafseG9CgznaJNo4/KKoiyKEoD5b3WAOYTfA6CVdvUYlVHDgV5gQYt8ZnP9t5/VKQarZotmbPxZ/jVmG/pWeY+Y0BsUctGoqkFb6+PgZBPjnHUNDKKSOM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713433949; c=relaxed/simple; bh=/1W3PiXHzqbOZG2JKIHP2M+KebXTpikrXK0Ib7Wtsno=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Cs1N37eJuGAwbRSdhwCFUb6bnKACQYN+3bYUwdUmmpNmujzoS8V5bP1x56Jr+byE58yIMo+QF4mhYcSBK8KgxK9OzO+PBEb4v6qXDsuX9LbR0+5b4uHxDGXPKPuCQXHkvqA2fDmGn+ugT9pc7ZrY1tXbNS+SCobad4iPkblV6JY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net; spf=pass smtp.mailfrom=sipsolutions.net; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b=Td9wij3o; arc=none smtp.client-ip=168.119.38.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b="Td9wij3o" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=/FijGTmv8297S/TPXCMqkXvfkD7Pmh038la17TVCxpo=; t=1713433947; x=1714643547; b=Td9wij3oP1kMuzJdb1RQbuyHMS+d3e08JKWI01qTITZqVek TZYwqYF8XMhCTm5EIk9Q2mMxVZE1hBVyWvnsWY7qqcjJ07x7kvO80i2EFhT53SoZtwil5ipYzjr4y wFKYGSKt0YTmz1qnZJRtZxfhVG22KJ0jb1LqbV93xok2WvVqlQ1QKbq3NOo1u+MrHGWaY5TRaLMFI QWf9onaolEYOPZqI0pyEX9ay6RCiSsK21CqpSJ3fJCQhvl68tuC8yDJybSqvhTmxCiJ7vLN1LROV0 yPqsOjRGJtUQk6kf0xZBdkdY5f74loTM8iP5ntHwK+n30CKFcnC1ujD4HK4lycig==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1rxORM-0000000CM0y-1Hm8; Thu, 18 Apr 2024 11:52:24 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg , Miriam Rachel Korenblit Subject: [PATCH wireless-next 2/3] wifi: mac80211: simplify ieee80211_assign_link_chanctx() Date: Thu, 18 Apr 2024 11:52:20 +0200 Message-ID: <20240418115219.a94852030d33.I9d647178ab25636372ed79e5312c68a06e0bf60c@changeid> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240418115219.94ea84c8ee1e.I0b247dbc0cd937ae6367bc0fc7e8d156b5d5f9b1@changeid> References: <20240418115219.94ea84c8ee1e.I0b247dbc0cd937ae6367bc0fc7e8d156b5d5f9b1@changeid> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Johannes Berg There's no need for a label/goto here, the only thing is that drv_assign_vif_chanctx() must succeed to set 'conf' and add the new context to the list, the remaining code is (and must be) the same regardless. Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 6d0148dea126..2c338014ded5 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -815,7 +815,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, struct ieee80211_local *local = sdata->local; struct ieee80211_chanctx_conf *conf; struct ieee80211_chanctx *curr_ctx = NULL; - int ret = 0; + int ret; if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN)) return -EOPNOTSUPP; @@ -836,15 +836,16 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, ieee80211_recalc_chanctx_min_def(local, new_ctx, link); ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx); - if (ret) - goto out; - - conf = &new_ctx->conf; - list_add(&link->assigned_chanctx_list, - &new_ctx->assigned_links); + if (!ret) { + /* succeeded, so commit it to the data structures */ + conf = &new_ctx->conf; + list_add(&link->assigned_chanctx_list, + &new_ctx->assigned_links); + } + } else { + ret = 0; } -out: rcu_assign_pointer(link->conf->chanctx_conf, conf); sdata->vif.cfg.idle = !conf; From patchwork Thu Apr 18 09:52:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 790167 Received: from sipsolutions.net (s3.sipsolutions.net [168.119.38.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF9647D3F4 for ; Thu, 18 Apr 2024 09:52:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.38.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713433949; cv=none; b=WE7AL5tLh8X/NySn4fv1QpvXHqGhLUac9Qa0yGP3n532MTnPssl/aOMw1vp117y0/ToFh4BYz0HuibU0fs/CJTK9XraU8Zs3sD6I6ojCP7T+mf61PRZzGAv2WxZUkykeeIpeq146VOSHkgR+noBbg62EM5Y2sBUG2Riqo6GLJVg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713433949; c=relaxed/simple; bh=MGqDm7cEQtVMPiIluCZ1f+2BDUCC3L535CNKEMd1HdQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nCtumsIHws2XXacJfE1csnqslM/qY6sB49pHvmZMcbGRiMVhnZfU2U+YCvDAeCyYIawH5CY5ZwcLUZm+zkTXo7ij7p4z3ZsMgvCQZ7bdjeAJ4KwFKfg2Op7/tgFtTFmq0ini0sxKTFJwiwMARoQkefxPPMH3furYMYLy8VyqdHI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net; spf=pass smtp.mailfrom=sipsolutions.net; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b=UozJv7/A; arc=none smtp.client-ip=168.119.38.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b="UozJv7/A" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=lVYYvRN8hZ2D3mejaFz5xMJsV70q9KWlkis0OVyKy5Q=; t=1713433948; x=1714643548; b=UozJv7/AHVsY2KKr9zQjmfpMRpcDoQgKVbLUMQ42uP5hcQ8 mNqBeAV+ojrYWFgpMvA7Lo3F2fPWy7j+krI2O3HOxrKAEU8hXvR5nucypxQrea5/mrKG0d7e1b5Ab MX07WJq/o6YaFkXoLAvN6cBScsJ9vm+qxCwnLnXn5mgr6/HpcaUtgAM6ZMz97ww3WbH6i6hUFenHu 8HKOYtXOnJaGjk8ERSmOSA0s0ehL3S05rX86kylni3lCqewcUqV078GENg6BOuITDsp7F9R+hqHtg k4LOoEe7awSFt40PaKV7efcpWXQI91WHP5bfsArQQIdw4L1bHWVFYQroKmJdiZ8Q==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1rxORM-0000000CM0y-47MX; Thu, 18 Apr 2024 11:52:25 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Benjamin Berg , Miriam Rachel Korenblit Subject: [PATCH wireless-next 3/3] wifi: mac80211: keep mac80211 consistent on link activation failure Date: Thu, 18 Apr 2024 11:52:21 +0200 Message-ID: <20240418115219.1129e89f4b55.I6299678353e50e88b55c99b0bce15c64b52c2804@changeid> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240418115219.94ea84c8ee1e.I0b247dbc0cd937ae6367bc0fc7e8d156b5d5f9b1@changeid> References: <20240418115219.94ea84c8ee1e.I0b247dbc0cd937ae6367bc0fc7e8d156b5d5f9b1@changeid> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Benjamin Berg In the unlikely event that link_use_channel fails while activating a link, mac80211 would go into a bad state. Unfortunately, we cannot completely avoid failures from drivers in this case. However, what we can do is to just continue internally anyway and assume the driver is going to trigger a recovery flow from its side. Doing that means that we at least have a consistent state in mac80211 allowing such a recovery flow to succeed. Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Benjamin Berg Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 35 +++++++++++++++++++++++------------ net/mac80211/ieee80211_i.h | 12 +++++++++++- net/mac80211/link.c | 21 ++++++++++++++++++--- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 2c338014ded5..dedf11eeb43c 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -688,7 +688,8 @@ static int ieee80211_add_chanctx(struct ieee80211_local *local, static struct ieee80211_chanctx * ieee80211_new_chanctx(struct ieee80211_local *local, const struct ieee80211_chan_req *chanreq, - enum ieee80211_chanctx_mode mode) + enum ieee80211_chanctx_mode mode, + bool assign_on_failure) { struct ieee80211_chanctx *ctx; int err; @@ -700,10 +701,12 @@ ieee80211_new_chanctx(struct ieee80211_local *local, return ERR_PTR(-ENOMEM); err = ieee80211_add_chanctx(local, ctx); - if (err) { + if (!assign_on_failure && err) { kfree(ctx); return ERR_PTR(err); } + /* We ignored a driver error, see _ieee80211_set_active_links */ + WARN_ON_ONCE(err && !local->in_reconfig); list_add_rcu(&ctx->list, &local->chanctx_list); return ctx; @@ -809,7 +812,8 @@ static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, } static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, - struct ieee80211_chanctx *new_ctx) + struct ieee80211_chanctx *new_ctx, + bool assign_on_failure) { struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_local *local = sdata->local; @@ -836,7 +840,11 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, ieee80211_recalc_chanctx_min_def(local, new_ctx, link); ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx); - if (!ret) { + if (assign_on_failure || !ret) { + /* Need to continue, see _ieee80211_set_active_links */ + WARN_ON_ONCE(ret && !local->in_reconfig); + ret = 0; + /* succeeded, so commit it to the data structures */ conf = &new_ctx->conf; list_add(&link->assigned_chanctx_list, @@ -1046,7 +1054,8 @@ int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode); if (!new_ctx) { if (ieee80211_can_create_new_chanctx(local)) { - new_ctx = ieee80211_new_chanctx(local, chanreq, mode); + new_ctx = ieee80211_new_chanctx(local, chanreq, mode, + false); if (IS_ERR(new_ctx)) return PTR_ERR(new_ctx); } else { @@ -1302,7 +1311,7 @@ ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link) list_del(&link->reserved_chanctx_list); link->reserved_chanctx = NULL; - err = ieee80211_assign_link_chanctx(link, new_ctx); + err = ieee80211_assign_link_chanctx(link, new_ctx, false); if (err) { if (ieee80211_chanctx_refcount(local, new_ctx) == 0) ieee80211_free_chanctx(local, new_ctx, false); @@ -1698,7 +1707,7 @@ void __ieee80211_link_release_channel(struct ieee80211_link_data *link, ieee80211_link_unreserve_chanctx(link); } - ieee80211_assign_link_chanctx(link, NULL); + ieee80211_assign_link_chanctx(link, NULL, false); if (ieee80211_chanctx_refcount(local, ctx) == 0) ieee80211_free_chanctx(local, ctx, skip_idle_recalc); @@ -1709,9 +1718,10 @@ void __ieee80211_link_release_channel(struct ieee80211_link_data *link, ieee80211_vif_use_reserved_switch(local); } -int ieee80211_link_use_channel(struct ieee80211_link_data *link, - const struct ieee80211_chan_req *chanreq, - enum ieee80211_chanctx_mode mode) +int _ieee80211_link_use_channel(struct ieee80211_link_data *link, + const struct ieee80211_chan_req *chanreq, + enum ieee80211_chanctx_mode mode, + bool assign_on_failure) { struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_local *local = sdata->local; @@ -1749,7 +1759,8 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link, if (ctx) reserved = true; else - ctx = ieee80211_new_chanctx(local, chanreq, mode); + ctx = ieee80211_new_chanctx(local, chanreq, mode, + assign_on_failure); if (IS_ERR(ctx)) { ret = PTR_ERR(ctx); goto out; @@ -1757,7 +1768,7 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link, ieee80211_link_update_chanreq(link, chanreq); - ret = ieee80211_assign_link_chanctx(link, ctx); + ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure); if (reserved) { /* remove reservation */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 81a9c5b7642d..317164219e02 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2553,9 +2553,19 @@ bool ieee80211_chanreq_identical(const struct ieee80211_chan_req *a, const struct ieee80211_chan_req *b); int __must_check +_ieee80211_link_use_channel(struct ieee80211_link_data *link, + const struct ieee80211_chan_req *req, + enum ieee80211_chanctx_mode mode, + bool assign_on_failure); + +static inline int __must_check ieee80211_link_use_channel(struct ieee80211_link_data *link, const struct ieee80211_chan_req *req, - enum ieee80211_chanctx_mode mode); + enum ieee80211_chanctx_mode mode) +{ + return _ieee80211_link_use_channel(link, req, mode, false); +} + int __must_check ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, const struct ieee80211_chan_req *req, diff --git a/net/mac80211/link.c b/net/mac80211/link.c index 43f9672fc7f1..af0321408a97 100644 --- a/net/mac80211/link.c +++ b/net/mac80211/link.c @@ -404,9 +404,24 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata, link = sdata_dereference(sdata->link[link_id], sdata); - ret = ieee80211_link_use_channel(link, - &link->conf->chanreq, - IEEE80211_CHANCTX_SHARED); + /* + * This call really should not fail. Unfortunately, it appears + * that this may happen occasionally with some drivers. Should + * it happen, we are stuck in a bad place as going backwards is + * not really feasible. + * + * So lets just tell link_use_channel that it must not fail to + * assign the channel context (from mac80211's perspective) and + * assume the driver is going to trigger a recovery flow if it + * had a failure. + * That really is not great nor guaranteed to work. But at least + * the internal mac80211 state remains consistent and there is + * a chance that we can recover. + */ + ret = _ieee80211_link_use_channel(link, + &link->conf->chanreq, + IEEE80211_CHANCTX_SHARED, + true); WARN_ON_ONCE(ret); ieee80211_mgd_set_link_qos_params(link);