On Tue, Mar 24, 2026 at 06:52:14PM +0100, Kirill A. Korinsky wrote:
> Thanks for detailed explanation, and because I'm in context of iwx driver it
> ineed trivial implement. I haven't touched other dirvers, but iwx is tested
> and seems works.
> 
> Also, I've checked Linux and it treats both CSA and eCSA/XCSA, so I did the 
> same.
> 
> The diff:

Thanks, the diff makes sense, ok stsp@

Please also update IEEE80211_NODEREQ_ASSOCFAIL and the _BITS string
in ieee80211_ioctl.h for the new CSA failure case. Otherwise ifconfig
won't be able to display the failure.

I am wondering if we could use a smaller hammer than the init_task()
to handle the switch. Maybe direclty switching to SCAN state would work.
But that's a small detail. The init task will get the job done and
we could try to optimize this later.

> Index: sys/dev/pci/if_iwx.c
> ===================================================================
> RCS file: /home/cvs/src/sys/dev/pci/if_iwx.c,v
> diff -u -p -r1.223 if_iwx.c
> --- sys/dev/pci/if_iwx.c      14 Mar 2026 15:37:44 -0000      1.223
> +++ sys/dev/pci/if_iwx.c      24 Mar 2026 17:39:36 -0000
> @@ -10994,6 +10994,23 @@ iwx_rx_pkt(struct iwx_softc *sc, struct 
>                       break;
>               }
>  
> +             case IWX_WIDE_ID(IWX_MAC_CONF_GROUP,
> +                 IWX_CHANNEL_SWITCH_START_NOTIF): {
> +                     if (sc->sc_ic.ic_opmode != IEEE80211_M_STA ||
> +                         sc->sc_ic.ic_state != IEEE80211_S_RUN)
> +                             break;
> +
> +                     if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
> +                             printf("%s: firmware channel switch "
> +                                 "notification 0x%x\n",
> +                                 DEVNAME(sc), code);
> +
> +                     if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0 &&
> +                         !task_pending(&sc->init_task))
> +                             task_add(systq, &sc->init_task);
> +                     break;
> +             }
> +
>               case IWX_WIDE_ID(IWX_SYSTEM_GROUP,
>                   IWX_FSEQ_VER_MISMATCH_NOTIFICATION):
>                   break;
> Index: sys/dev/pci/if_iwxreg.h
> ===================================================================
> RCS file: /home/cvs/src/sys/dev/pci/if_iwxreg.h,v
> diff -u -p -r1.73 if_iwxreg.h
> --- sys/dev/pci/if_iwxreg.h   13 Mar 2026 11:11:02 -0000      1.73
> +++ sys/dev/pci/if_iwxreg.h   24 Mar 2026 17:37:13 -0000
> @@ -2079,6 +2079,7 @@ struct iwx_tx_queue_cfg_rsp {
>  #define IWX_STA_REMOVE_CMD           0x0c
>  #define IWX_SESSION_PROTECTION_NOTIF 0xfb
>  #define IWX_MISSED_BEACONS_NOTIF     0xf6
> +#define IWX_CHANNEL_SWITCH_START_NOTIF       0xff
>  
>  /* DATA_PATH group subcommand IDs */
>  #define IWX_DQA_ENABLE_CMD   0x00
> Index: sys/net80211/ieee80211_input.c
> ===================================================================
> RCS file: /home/cvs/src/sys/net80211/ieee80211_input.c,v
> diff -u -p -r1.260 ieee80211_input.c
> --- sys/net80211/ieee80211_input.c    19 Mar 2026 16:50:32 -0000      1.260
> +++ sys/net80211/ieee80211_input.c    24 Mar 2026 17:40:26 -0000
> @@ -1623,7 +1623,7 @@ ieee80211_recv_probe_resp(struct ieee802
>  {
>       struct ieee80211_node *ni;
>       const struct ieee80211_frame *wh;
> -     const u_int8_t *frm, *efrm;
> +     const u_int8_t *frm, *efrm, *csa, *xcsa;
>       const u_int8_t *tstamp, *ssid, *rates, *xrates, *edcaie, *wmmie, *tim;
>       const u_int8_t *rsnie, *wpaie, *htcaps, *htop, *vhtcaps, *vhtop, 
> *hecaps, *heop;
>       u_int16_t capinfo, bintval;
> @@ -1666,7 +1666,7 @@ ieee80211_recv_probe_resp(struct ieee802
>       capinfo = LE_READ_2(frm); frm += 2;
>  
>       ssid = rates = xrates = edcaie = wmmie = rsnie = wpaie = tim = NULL;
> -     htcaps = htop = vhtcaps = vhtop = hecaps = heop = NULL;
> +     htcaps = htop = vhtcaps = vhtop = hecaps = heop = csa = xcsa = NULL;
>       if (rxi->rxi_chan)
>               bchan = rxi->rxi_chan;
>       else
> @@ -1702,6 +1702,20 @@ ieee80211_recv_probe_resp(struct ieee802
>                       }
>                       erp = frm[2];
>                       break;
> +             case IEEE80211_ELEMID_CSA:
> +                     if (frm[1] < 3) {
> +                             ic->ic_stats.is_rx_elem_toosmall++;
> +                             break;
> +                     }
> +                     csa = frm;
> +                     break;
> +             case IEEE80211_ELEMID_XCSA:
> +                     if (frm[1] < 4) {
> +                             ic->ic_stats.is_rx_elem_toosmall++;
> +                             break;
> +                     }
> +                     xcsa = frm;
> +                     break;
>               case IEEE80211_ELEMID_RSN:
>                       rsnie = frm;
>                       break;
> @@ -1826,6 +1840,9 @@ ieee80211_recv_probe_resp(struct ieee802
>  #endif
>  
>       ni->ni_chan = &ic->ic_channels[chan];
> +     ni->ni_flags &= ~IEEE80211_NODE_CSA;
> +     if (csa != NULL || xcsa != NULL)
> +             ni->ni_flags |= IEEE80211_NODE_CSA;
>  
>       if (htcaps)
>               ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
> Index: sys/net80211/ieee80211_node.c
> ===================================================================
> RCS file: /home/cvs/src/sys/net80211/ieee80211_node.c,v
> diff -u -p -r1.211 ieee80211_node.c
> --- sys/net80211/ieee80211_node.c     19 Mar 2026 16:50:32 -0000      1.211
> +++ sys/net80211/ieee80211_node.c     24 Mar 2026 17:30:50 -0000
> @@ -1135,6 +1135,8 @@ ieee80211_match_bss(struct ieee80211com 
>       if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
>           !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
>               fail |= IEEE80211_NODE_ASSOCFAIL_BSSID;
> +     if (ni->ni_flags & IEEE80211_NODE_CSA)
> +             fail |= IEEE80211_NODE_ASSOCFAIL_CSA;
>  
>       if (ic->ic_flags & IEEE80211_F_RSNON) {
>               /*
> Index: sys/net80211/ieee80211_node.h
> ===================================================================
> RCS file: /home/cvs/src/sys/net80211/ieee80211_node.h,v
> diff -u -p -r1.99 ieee80211_node.h
> --- sys/net80211/ieee80211_node.h     19 Mar 2026 16:50:32 -0000      1.99
> +++ sys/net80211/ieee80211_node.h     24 Mar 2026 17:30:50 -0000
> @@ -413,6 +413,7 @@ struct ieee80211_node {
>  #define IEEE80211_NODE_ASSOCFAIL_BSSID               0x20
>  #define IEEE80211_NODE_ASSOCFAIL_WPA_PROTO   0x40
>  #define IEEE80211_NODE_ASSOCFAIL_WPA_KEY     0x80
> +#define IEEE80211_NODE_ASSOCFAIL_CSA         0x100
>  
>       int                     ni_inact;       /* inactivity mark count */
>       int                     ni_txrate;      /* index to ni_rates[] */
> @@ -444,6 +445,7 @@ struct ieee80211_node {
>  #define IEEE80211_NODE_VHT_SGI160    0x100000 /* SGI on 160 MHz negotiated 
> */ 
>  #define IEEE80211_NODE_HE            0x200000 /* HE negotiated */
>  #define IEEE80211_NODE_HECAP         0x400000 /* claims to support HE */
> +#define IEEE80211_NODE_CSA           0x800000 /* channel switch announced */
>  
>       /* If not NULL, this function gets called when ni_refcnt hits zero. */
>       void                    (*ni_unref_cb)(struct ieee80211com *,
> 
> 
> 
> -- 
> wbr, Kirill
> 

Reply via email to