On Sat, Dec 04, 2021 at 09:32:40PM +0300, Vitaliy Makkoveev wrote:
> I think rtm_80211info() could follow the if_link_state_change()
> way and use task for that.
Indeed. I did not realize that if_link_state_change() schedules a task.
This means ieee80211_set_link_state() is already deferring some of its
work to a task. The patch below defers sending the 80211info message
to a task as well.
I am keeping things simple for now and use systq (kernel-locked) instead
of copying the argument-passing approach used by if_link_state_change().
Tested on iwm(4) 8265 with 'route monitor'.
ok?
diff 0b61c8235787960f0010ef627ea5b2c6309a81f0
de98c050ea709bdb8e26be40ab0cc82ef9afed80
blob - 7bb68194dd78417b06c59f81d1ebbff4165203d8
blob + 5b9a969258074fde29e21a33ac035cf170ec3b03
--- sys/net80211/ieee80211.c
+++ sys/net80211/ieee80211.c
@@ -193,6 +193,7 @@ ieee80211_ifattach(struct ifnet *ifp)
if_addgroup(ifp, "wlan");
ifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY;
+ task_set(&ic->ic_rtm_80211info_task, ieee80211_rtm_80211info_task, ic);
ieee80211_set_link_state(ic, LINK_STATE_DOWN);
timeout_set(&ic->ic_bgscan_timeout, ieee80211_bgscan_timeout, ifp);
@@ -203,6 +204,7 @@ ieee80211_ifdetach(struct ifnet *ifp)
{
struct ieee80211com *ic = (void *)ifp;
+ task_del(systq, &ic->ic_rtm_80211info_task);
timeout_del(&ic->ic_bgscan_timeout);
/*
blob - 447a2676bfb250b7f917206549679d6ae68de1f6
blob + 7e10fc1336067542c13d5607602e658ce2b3926b
--- sys/net80211/ieee80211_proto.c
+++ sys/net80211/ieee80211_proto.c
@@ -1288,6 +1288,31 @@ justcleanup:
}
void
+ieee80211_rtm_80211info_task(void *arg)
+{
+ struct ieee80211com *ic = arg;
+ struct ifnet *ifp = &ic->ic_if;
+ struct if_ieee80211_data ifie;
+ int s = splnet();
+
+ if (LINK_STATE_IS_UP(ifp->if_link_state)) {
+ memset(&ifie, 0, sizeof(ifie));
+ ifie.ifie_nwid_len = ic->ic_bss->ni_esslen;
+ memcpy(ifie.ifie_nwid, ic->ic_bss->ni_essid,
+ sizeof(ifie.ifie_nwid));
+ memcpy(ifie.ifie_addr, ic->ic_bss->ni_bssid,
+ sizeof(ifie.ifie_addr));
+ ifie.ifie_channel = ieee80211_chan2ieee(ic,
+ ic->ic_bss->ni_chan);
+ ifie.ifie_flags = ic->ic_flags;
+ ifie.ifie_xflags = ic->ic_xflags;
+ rtm_80211info(&ic->ic_if, &ifie);
+ }
+
+ splx(s);
+}
+
+void
ieee80211_set_link_state(struct ieee80211com *ic, int nstate)
{
struct ifnet *ifp = &ic->ic_if;
@@ -1307,20 +1332,8 @@ ieee80211_set_link_state(struct ieee80211com *ic, int
}
if (nstate != ifp->if_link_state) {
ifp->if_link_state = nstate;
- if (LINK_STATE_IS_UP(nstate)) {
- struct if_ieee80211_data ifie;
- memset(&ifie, 0, sizeof(ifie));
- ifie.ifie_nwid_len = ic->ic_bss->ni_esslen;
- memcpy(ifie.ifie_nwid, ic->ic_bss->ni_essid,
- sizeof(ifie.ifie_nwid));
- memcpy(ifie.ifie_addr, ic->ic_bss->ni_bssid,
- sizeof(ifie.ifie_addr));
- ifie.ifie_channel = ieee80211_chan2ieee(ic,
- ic->ic_bss->ni_chan);
- ifie.ifie_flags = ic->ic_flags;
- ifie.ifie_xflags = ic->ic_xflags;
- rtm_80211info(&ic->ic_if, &ifie);
- }
+ if (LINK_STATE_IS_UP(nstate))
+ task_add(systq, &ic->ic_rtm_80211info_task);
if_link_state_change(ifp);
}
}
blob - 7208e5dc0be1983a31d7f74142e87581bea95d13
blob + ce6d1ad91f391cb16c7f0bbfa79210401d5dc7eb
--- sys/net80211/ieee80211_proto.h
+++ sys/net80211/ieee80211_proto.h
@@ -63,6 +63,7 @@ extern void ieee80211_proto_detach(struct ifnet *);
struct ieee80211_node;
struct ieee80211_rxinfo;
struct ieee80211_rsnparams;
+extern void ieee80211_rtm_80211info_task(void *);
extern void ieee80211_set_link_state(struct ieee80211com *, int);
extern u_int ieee80211_get_hdrlen(const struct ieee80211_frame *);
extern int ieee80211_classify(struct ieee80211com *, struct mbuf *);
blob - dd17ed76031db17bd86cd75a5c1eec659dbd3f30
blob + 641419331ed3f65fbc9272c055948438b28f1025
--- sys/net80211/ieee80211_var.h
+++ sys/net80211/ieee80211_var.h
@@ -306,6 +306,7 @@ struct ieee80211com {
struct timeout ic_inact_timeout; /* node inactivity timeout */
struct timeout ic_node_cache_timeout;
#endif
+ struct task ic_rtm_80211info_task;
int ic_des_esslen;
u_int8_t ic_des_essid[IEEE80211_NWID_LEN];
struct ieee80211_channel *ic_des_chan; /* desired channel */