* @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel,
  *     this is used only with channel switching with CSA
  * @IEEE80211_CHANCTX_CHANGE_MIN_WIDTH: The min required channel width changed
+ * @IEEE80211_CHANCTX_CHANGE_AP: The AP channel definition changed, so (wider
+ *     bandwidth) OFDMA settings need to be changed
  */
 enum ieee80211_chanctx_change {
        IEEE80211_CHANCTX_CHANGE_WIDTH          = BIT(0),
        IEEE80211_CHANCTX_CHANGE_RADAR          = BIT(2),
        IEEE80211_CHANCTX_CHANGE_CHANNEL        = BIT(3),
        IEEE80211_CHANCTX_CHANGE_MIN_WIDTH      = BIT(4),
+       IEEE80211_CHANCTX_CHANGE_AP             = BIT(5),
 };
 
 /**
  * struct ieee80211_chan_req - A channel "request"
  * @oper: channel definition to use for operation
+ * @ap: the channel definition of the AP, if any
+ *     (otherwise the chan member is %NULL)
  */
 struct ieee80211_chan_req {
        struct cfg80211_chan_def oper;
+       struct cfg80211_chan_def ap;
 };
 
 /**
  *
  * @def: the channel definition
  * @min_def: the minimum channel definition currently required.
+ * @ap: the channel definition the AP actually is operating as,
+ *     for use with (wider bandwidth) OFDMA
  * @rx_chains_static: The number of RX chains that must always be
  *     active on the channel to receive MIMO transmissions
  * @rx_chains_dynamic: The number of RX chains that must be enabled
 struct ieee80211_chanctx_conf {
        struct cfg80211_chan_def def;
        struct cfg80211_chan_def min_def;
+       struct cfg80211_chan_def ap;
 
        u8 rx_chains_static, rx_chains_dynamic;
 
  *     this is not pure P2P vif.
  * @IEEE80211_VIF_EML_ACTIVE: The driver indicates that EML operation is
  *      enabled for the interface.
+ * @IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW: Ignore wider bandwidth OFDMA
+ *     operation on this interface and request a channel context without
+ *     the AP definition. Use this e.g. because the device is able to
+ *     handle OFDMA (downlink and trigger for uplink) on a per-AP basis.
  */
 enum ieee80211_vif_flags {
        IEEE80211_VIF_BEACON_FILTER             = BIT(0),
        IEEE80211_VIF_SUPPORTS_UAPSD            = BIT(2),
        IEEE80211_VIF_GET_NOA_UPDATE            = BIT(3),
        IEEE80211_VIF_EML_ACTIVE                = BIT(4),
+       IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW     = BIT(5),
 };
 
 
 
        return container_of(conf, struct ieee80211_chanctx, conf);
 }
 
+bool ieee80211_chanreq_identical(const struct ieee80211_chan_req *a,
+                                const struct ieee80211_chan_req *b)
+{
+       if (!cfg80211_chandef_identical(&a->oper, &b->oper))
+               return false;
+       if (!a->ap.chan && !b->ap.chan)
+               return true;
+       return cfg80211_chandef_identical(&a->ap, &b->ap);
+}
+
 static const struct ieee80211_chan_req *
 ieee80211_chanreq_compatible(const struct ieee80211_chan_req *a,
-                            const struct ieee80211_chan_req *b)
+                            const struct ieee80211_chan_req *b,
+                            struct ieee80211_chan_req *tmp)
 {
        const struct cfg80211_chan_def *compat;
 
-       compat = cfg80211_chandef_compatible(&a->oper, &b->oper);
-
-       if (compat == &a->oper)
-               return a;
+       if (a->ap.chan && b->ap.chan &&
+           !cfg80211_chandef_identical(&a->ap, &b->ap))
+               return NULL;
 
-       if (compat == &b->oper)
-               return b;
+       compat = cfg80211_chandef_compatible(&a->oper, &b->oper);
+       if (!compat)
+               return NULL;
 
-       WARN_ON(compat);
-       return NULL;
+       /* Note: later code assumes this always fills & returns tmp if compat */
+       tmp->oper = *compat;
+       tmp->ap = a->ap.chan ? a->ap : b->ap;
+       return tmp;
 }
 
 static const struct ieee80211_chan_req *
                             const struct ieee80211_chan_req *req,
                             struct ieee80211_chan_req *tmp)
 {
+       const struct ieee80211_chan_req *ret;
+       struct ieee80211_chan_req tmp2;
+
        *tmp = (struct ieee80211_chan_req){
                .oper = ctx->conf.def,
+               .ap = ctx->conf.ap,
        };
 
-       return ieee80211_chanreq_compatible(tmp, req);
+       ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
+       if (!ret)
+               return NULL;
+       *tmp = *ret;
+       return tmp;
 }
 
 static const struct ieee80211_chan_req *
 ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *ctx,
-                                  const struct ieee80211_chan_req *req)
+                                  const struct ieee80211_chan_req *req,
+                                  struct ieee80211_chan_req *tmp)
 {
        struct ieee80211_link_data *link;
 
                return NULL;
 
        list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) {
-               req = ieee80211_chanreq_compatible(&link->reserved, req);
+               req = ieee80211_chanreq_compatible(&link->reserved, req, tmp);
                if (!req)
                        break;
        }
 static const struct ieee80211_chan_req *
 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
                                       struct ieee80211_chanctx *ctx,
-                                      const struct ieee80211_chan_req *compat)
+                                      const struct ieee80211_chan_req *compat,
+                                      struct ieee80211_chan_req *tmp)
 {
        struct ieee80211_link_data *link;
        const struct ieee80211_chan_req *comp_def = compat;
                        continue;
 
                comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq,
-                                                       comp_def);
+                                                       comp_def, tmp);
                if (!comp_def)
                        break;
        }
                              struct ieee80211_chanctx *ctx,
                              const struct ieee80211_chan_req *req)
 {
+       struct ieee80211_chan_req tmp;
+
        lockdep_assert_wiphy(local->hw.wiphy);
 
-       if (!ieee80211_chanctx_reserved_chanreq(local, ctx, req))
+       if (!ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
                return false;
 
-       if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req))
+       if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req, &tmp))
                return false;
 
        if (!list_empty(&ctx->reserved_links) &&
-           ieee80211_chanctx_reserved_chanreq(local, ctx, req))
+           ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
                return true;
 
        return false;
                                      struct ieee80211_link_data *rsvd_for)
 {
        const struct cfg80211_chan_def *chandef = &chanreq->oper;
-       u32 changed;
+       struct ieee80211_chan_req ctx_req = {
+               .oper = ctx->conf.def,
+               .ap = ctx->conf.ap,
+       };
+       u32 changed = 0;
 
        /* expected to handle only 20/40/80/160/320 channel widths */
        switch (chandef->width) {
         */
        ieee80211_chan_bw_change(local, old_ctx, true);
 
-       if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) {
+       if (ieee80211_chanreq_identical(&ctx_req, chanreq)) {
                ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
                return;
        }
 
-       WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
+       WARN_ON(ieee80211_chanctx_refcount(local, ctx) > 1 &&
+               !cfg80211_chandef_compatible(&ctx->conf.def, &chanreq->oper));
 
        ieee80211_remove_wbrf(local, &ctx->conf.def);
 
+       if (!cfg80211_chandef_identical(&ctx->conf.def, &chanreq->oper))
+               changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
+       if (!cfg80211_chandef_identical(&ctx->conf.ap, &chanreq->ap))
+               changed |= IEEE80211_CHANCTX_CHANGE_AP;
        ctx->conf.def = *chandef;
+       ctx->conf.ap = chanreq->ap;
 
        /* check if min chanctx also changed */
-       changed = IEEE80211_CHANCTX_CHANGE_WIDTH |
-                 _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
+       changed |= _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
 
        ieee80211_add_wbrf(local, &ctx->conf.def);
 
        drv_change_chanctx(local, ctx, changed);
 
-       /* check is BW wider */
+       /* check if BW is wider */
        ieee80211_chan_bw_change(local, old_ctx, false);
 }
 
                        continue;
 
                compat = ieee80211_chanctx_reserved_chanreq(local, ctx,
-                                                           compat);
+                                                           compat, &tmp);
                if (!compat)
                        continue;
 
        INIT_LIST_HEAD(&ctx->assigned_links);
        INIT_LIST_HEAD(&ctx->reserved_links);
        ctx->conf.def = chanreq->oper;
+       ctx->conf.ap = chanreq->ap;
        ctx->conf.rx_chains_static = 1;
        ctx->conf.rx_chains_dynamic = 1;
        ctx->mode = mode;
                                       struct ieee80211_chanctx *ctx)
 {
        struct ieee80211_chanctx_conf *conf = &ctx->conf;
-       const struct cfg80211_chan_def *compat = NULL;
+       const struct ieee80211_chan_req *compat = NULL;
        struct ieee80211_link_data *link;
-       struct ieee80211_chan_req chanreq = {};
+       struct ieee80211_chan_req tmp;
        struct sta_info *sta;
 
        lockdep_assert_wiphy(local->hw.wiphy);
                        continue;
 
                if (!compat)
-                       compat = &link_conf->chanreq.oper;
+                       compat = &link_conf->chanreq;
 
-               compat = cfg80211_chandef_compatible(&link_conf->chanreq.oper,
-                                                    compat);
+               compat = ieee80211_chanreq_compatible(&link_conf->chanreq,
+                                                     compat, &tmp);
                if (WARN_ON_ONCE(!compat))
                        return;
        }
 
        /* TDLS peers can sometimes affect the chandef width */
        list_for_each_entry(sta, &local->sta_list, list) {
+               struct ieee80211_chan_req tdls_chanreq = {};
                if (!sta->uploaded ||
                    !test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) ||
                    !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
                    !sta->tdls_chandef.chan)
                        continue;
 
-               compat = cfg80211_chandef_compatible(&sta->tdls_chandef,
-                                                    compat);
+               tdls_chanreq.oper = sta->tdls_chandef;
+
+               /* note this always fills and returns &tmp if compat */
+               compat = ieee80211_chanreq_compatible(&tdls_chanreq,
+                                                     compat, &tmp);
                if (WARN_ON_ONCE(!compat))
                        return;
        }
 
-       if (!compat)
-               return;
-
-       chanreq.oper = *compat;
-
-       ieee80211_change_chanctx(local, ctx, ctx, &chanreq);
+       ieee80211_change_chanctx(local, ctx, ctx, compat);
 }
 
 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
        struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
        struct ieee80211_chanctx *old_ctx, *new_ctx;
        const struct ieee80211_chan_req *chanreq;
+       struct ieee80211_chan_req tmp;
        u64 changed = 0;
        int err;
 
                return -EINVAL;
 
        chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
-                                                        &link->reserved);
+                                                        &link->reserved,
+                                                        &tmp);
        if (WARN_ON(!chanreq))
                return -EINVAL;
 
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_chanctx *old_ctx, *new_ctx;
        const struct ieee80211_chan_req *chanreq;
+       struct ieee80211_chan_req tmp;
        int err;
 
        old_ctx = ieee80211_link_get_chanctx(link);
                return -EINVAL;
 
        chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
-                                                        &link->reserved);
+                                                        &link->reserved,
+                                                        &tmp);
        if (WARN_ON(!chanreq))
                return -EINVAL;
 
        return 0;
 }
 
+/*
+ * This is similar to ieee80211_chanctx_compatible(), but rechecks
+ * against all the links actually using it (except the one that's
+ * passed, since that one is changing).
+ * This is done in order to allow changes to the AP's bandwidth for
+ * wider bandwidth OFDMA purposes, which wouldn't be treated as
+ * compatible by ieee80211_chanctx_recheck() but is OK if the link
+ * requesting the update is the only one using it.
+ */
+static const struct ieee80211_chan_req *
+ieee80211_chanctx_recheck(struct ieee80211_local *local,
+                         struct ieee80211_link_data *skip_link,
+                         struct ieee80211_chanctx *ctx,
+                         const struct ieee80211_chan_req *req,
+                         struct ieee80211_chan_req *tmp)
+{
+       const struct ieee80211_chan_req *ret = req;
+       struct ieee80211_link_data *link;
+
+       lockdep_assert_wiphy(local->hw.wiphy);
+
+       for_each_sdata_link(local, link) {
+               if (link == skip_link)
+                       continue;
+
+               if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
+                       ret = ieee80211_chanreq_compatible(ret,
+                                                          &link->conf->chanreq,
+                                                          tmp);
+                       if (!ret)
+                               return NULL;
+               }
+
+               if (link->reserved_chanctx == ctx) {
+                       ret = ieee80211_chanreq_compatible(ret,
+                                                          &link->reserved,
+                                                          tmp);
+                       if (!ret)
+                               return NULL;
+               }
+       }
+
+       *tmp = *ret;
+       return tmp;
+}
+
 int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
                                  const struct ieee80211_chan_req *chanreq,
                                  u64 *changed)
 
        ctx = container_of(conf, struct ieee80211_chanctx, conf);
 
-       compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp);
+       compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
        if (!compat)
                return -EINVAL;
 
        switch (ctx->replace_state) {
        case IEEE80211_CHANCTX_REPLACE_NONE:
-               if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat))
+               if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat,
+                                                       &tmp))
                        return -EBUSY;
                break;
        case IEEE80211_CHANCTX_WILL_BE_REPLACED:
 
                                struct cfg80211_chan_def *chandef);
 void ieee80211_chandef_downgrade(struct cfg80211_chan_def *chandef,
                                 struct ieee80211_conn_settings *conn);
+static inline void
+ieee80211_chanreq_downgrade(struct ieee80211_chan_req *chanreq,
+                           struct ieee80211_conn_settings *conn)
+{
+       ieee80211_chandef_downgrade(&chanreq->oper, conn);
+       if (WARN_ON(!conn))
+               return;
+       if (conn->mode < IEEE80211_CONN_MODE_EHT)
+               chanreq->ap.chan = NULL;
+}
+
+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,
 
 ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
                              struct ieee80211_conn_settings *conn,
                              struct cfg80211_bss *cbss, int link_id,
-                             struct cfg80211_chan_def *chandef)
+                             struct ieee80211_chan_req *chanreq)
 {
        struct ieee80211_local *local = sdata->local;
        const struct cfg80211_bss_ies *ies = rcu_dereference(cbss->ies);
        }
 
        conn->mode = ap_mode;
-       *chandef = ap_chandef;
+       chanreq->oper = ap_chandef;
 
-       while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
+       /* wider-bandwidth OFDMA is only done in EHT */
+       if (conn->mode >= IEEE80211_CONN_MODE_EHT &&
+           !(sdata->vif.driver_flags & IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW))
+               chanreq->ap = ap_chandef;
+       else
+               chanreq->ap.chan = NULL;
+
+       while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &chanreq->oper,
                                        IEEE80211_CHAN_DISABLED)) {
-               if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
+               if (WARN_ON(chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT)) {
                        ret = -EINVAL;
                        goto free;
                }
 
-               ieee80211_chandef_downgrade(chandef, conn);
+               ieee80211_chanreq_downgrade(chanreq, conn);
        }
 
        if (conn->mode >= IEEE80211_CONN_MODE_HE &&
-           !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef,
+           !cfg80211_chandef_usable(sdata->wdev.wiphy, &chanreq->oper,
                                     IEEE80211_CHAN_NO_HE)) {
                conn->mode = IEEE80211_CONN_MODE_VHT;
                conn->bw_limit = min_t(enum ieee80211_conn_bw_limit,
        }
 
        if (conn->mode >= IEEE80211_CONN_MODE_EHT &&
-           !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef,
+           !cfg80211_chandef_usable(sdata->wdev.wiphy, &chanreq->oper,
                                     IEEE80211_CHAN_NO_EHT)) {
                conn->mode = IEEE80211_CONN_MODE_HE;
                conn->bw_limit = min_t(enum ieee80211_conn_bw_limit,
                                       IEEE80211_CONN_BW_LIMIT_160);
        }
 
-       if (chandef->width != ap_chandef.width || ap_mode != conn->mode)
+       if (chanreq->oper.width != ap_chandef.width || ap_mode != conn->mode)
                sdata_info(sdata,
                           "regulatory prevented using AP config, downgraded\n");
 
                         ieee80211_conn_mode_str(conn->mode),
                         20 * (1 << conn->bw_limit));
 
-       if (WARN_ON_ONCE(!cfg80211_chandef_valid(chandef))) {
+       if (WARN_ON_ONCE(!cfg80211_chandef_valid(&chanreq->oper))) {
                ret = -EINVAL;
                goto free;
        }
        struct ieee80211_channel *channel = link->conf->chanreq.oper.chan;
        struct ieee80211_sub_if_data *sdata = link->sdata;
        struct ieee80211_chan_req chanreq = {};
-       struct cfg80211_chan_def ap_chandef;
        enum ieee80211_conn_mode ap_mode;
        u32 vht_cap_info = 0;
        u16 ht_opmode;
 
        ap_mode = ieee80211_determine_ap_chan(sdata, channel, vht_cap_info,
                                              elems, true, &link->u.mgd.conn,
-                                             &ap_chandef);
+                                             &chanreq.ap);
 
        if (ap_mode != link->u.mgd.conn.mode) {
                link_info(link,
                return -EINVAL;
        }
 
+       chanreq.oper = chanreq.ap;
+       if (link->u.mgd.conn.mode < IEEE80211_CONN_MODE_EHT ||
+           sdata->vif.driver_flags & IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW)
+               chanreq.ap.chan = NULL;
+
        /*
         * if HT operation mode changed store the new one -
         * this may be applicable even if channel is identical
         * won't do us any good -- we couldn't use it with the AP.
         */
        while (link->u.mgd.conn.bw_limit <
-                       ieee80211_min_bw_limit_from_chandef(&ap_chandef))
-               ieee80211_chandef_downgrade(&ap_chandef, NULL);
+                       ieee80211_min_bw_limit_from_chandef(&chanreq.oper))
+               ieee80211_chandef_downgrade(&chanreq.oper, NULL);
 
-       if (cfg80211_chandef_identical(&ap_chandef, &link->conf->chanreq.oper))
+       if (ieee80211_chanreq_identical(&chanreq, &link->conf->chanreq))
                return 0;
 
        link_info(link,
-                 "AP %pM changed bandwidth, new config is %d.%03d MHz, width %d (%d.%03d/%d MHz)\n",
-                 link->u.mgd.bssid, ap_chandef.chan->center_freq,
-                 ap_chandef.chan->freq_offset, ap_chandef.width,
-                 ap_chandef.center_freq1, ap_chandef.freq1_offset,
-                 ap_chandef.center_freq2);
+                 "AP %pM changed bandwidth, new used config is %d.%03d MHz, width %d (%d.%03d/%d MHz)\n",
+                 link->u.mgd.bssid, chanreq.oper.chan->center_freq,
+                 chanreq.oper.chan->freq_offset, chanreq.oper.width,
+                 chanreq.oper.center_freq1, chanreq.oper.freq1_offset,
+                 chanreq.oper.center_freq2);
 
-       if (!cfg80211_chandef_valid(&ap_chandef)) {
+       if (!cfg80211_chandef_valid(&chanreq.oper)) {
                sdata_info(sdata,
                           "AP %pM changed caps/bw in a way we can't support - disconnect\n",
                           link->u.mgd.bssid);
         * bandwidth changes where a this could happen, but those cases are
         * less common and wouldn't completely prevent using the AP.
         */
-       chanreq.oper = ap_chandef;
 
        ret = ieee80211_link_change_chanreq(link, &chanreq, changed);
        if (ret) {
                return;
        }
 
-       if (!cfg80211_chandef_identical(&link->conf->chanreq.oper,
-                                       &link->csa_chanreq.oper)) {
+       if (!ieee80211_chanreq_identical(&link->conf->chanreq,
+                                        &link->csa_chanreq)) {
                sdata_info(sdata,
                           "failed to finalize channel switch, disconnecting\n");
                wiphy_work_queue(sdata->local->hw.wiphy,
 
        rcu_read_lock();
        elems = ieee80211_determine_chan_mode(sdata, conn, cbss, link_id,
-                                             &chanreq.oper);
+                                             &chanreq);
 
        if (IS_ERR(elems)) {
                rcu_read_unlock();
                return ret;
 
        while (ret && chanreq.oper.width != NL80211_CHAN_WIDTH_20_NOHT) {
-               ieee80211_chandef_downgrade(&chanreq.oper, conn);
+               ieee80211_chanreq_downgrade(&chanreq, conn);
 
                ret = ieee80211_link_use_channel(link, &chanreq,
                                                 IEEE80211_CHANCTX_SHARED);
 
                        __entry->center_freq1 = (c) ? (c)->center_freq1 : 0;            \
                        __entry->freq1_offset = (c) ? (c)->freq1_offset : 0;            \
                        __entry->center_freq2 = (c) ? (c)->center_freq2 : 0;
-#define CHANDEF_PR_FMT " control:%d.%03d MHz width:%d center: %d.%03d/%d MHz"
+#define CHANDEF_PR_FMT " chandef(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz)"
 #define CHANDEF_PR_ARG __entry->control_freq, __entry->freq_offset, __entry->chan_width, \
                        __entry->center_freq1, __entry->freq1_offset, __entry->center_freq2
 
                        __entry->min_center_freq1 = (c)->center_freq1;                  \
                        __entry->min_freq1_offset = (c)->freq1_offset;                  \
                        __entry->min_center_freq2 = (c)->center_freq2;
-#define MIN_CHANDEF_PR_FMT     " min_control:%d.%03d MHz min_width:%d min_center: %d.%03d/%d MHz"
+#define MIN_CHANDEF_PR_FMT     " mindef(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz)"
 #define MIN_CHANDEF_PR_ARG     __entry->min_control_freq, __entry->min_freq_offset,    \
                        __entry->min_chan_width,                                        \
                        __entry->min_center_freq1, __entry->min_freq1_offset,           \
                        __entry->min_center_freq2
 
+#define AP_CHANDEF_ENTRY                                                               \
+                       __field(u32, ap_control_freq)                                   \
+                       __field(u32, ap_freq_offset)                                    \
+                       __field(u32, ap_chan_width)                                     \
+                       __field(u32, ap_center_freq1)                                   \
+                       __field(u32, ap_freq1_offset)                                   \
+                       __field(u32, ap_center_freq2)
+
+#define AP_CHANDEF_ASSIGN(c)                                                           \
+                       __entry->ap_control_freq = (c)->chan ? (c)->chan->center_freq : 0;\
+                       __entry->ap_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0;\
+                       __entry->ap_chan_width = (c)->chan ? (c)->width : 0;            \
+                       __entry->ap_center_freq1 = (c)->chan ? (c)->center_freq1 : 0;   \
+                       __entry->ap_freq1_offset = (c)->chan ? (c)->freq1_offset : 0;   \
+                       __entry->ap_center_freq2 = (c)->chan ? (c)->center_freq2 : 0;
+#define AP_CHANDEF_PR_FMT      " ap(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz)"
+#define AP_CHANDEF_PR_ARG      __entry->ap_control_freq, __entry->ap_freq_offset,      \
+                       __entry->ap_chan_width,                                         \
+                       __entry->ap_center_freq1, __entry->ap_freq1_offset,             \
+                       __entry->ap_center_freq2
+
 #define CHANCTX_ENTRY  CHANDEF_ENTRY                                                   \
                        MIN_CHANDEF_ENTRY                                               \
+                       AP_CHANDEF_ENTRY                                                \
                        __field(u8, rx_chains_static)                                   \
                        __field(u8, rx_chains_dynamic)
 #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def)                                  \
                        MIN_CHANDEF_ASSIGN(&ctx->conf.min_def)                          \
+                       AP_CHANDEF_ASSIGN(&ctx->conf.ap)                                \
                        __entry->rx_chains_static = ctx->conf.rx_chains_static;         \
                        __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
-#define CHANCTX_PR_FMT CHANDEF_PR_FMT MIN_CHANDEF_PR_FMT " chains:%d/%d"
-#define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG,                             \
+#define CHANCTX_PR_FMT CHANDEF_PR_FMT MIN_CHANDEF_PR_FMT AP_CHANDEF_PR_FMT " chains:%d/%d"
+#define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG, AP_CHANDEF_PR_ARG,          \
                        __entry->rx_chains_static, __entry->rx_chains_dynamic
 
 #define KEY_ENTRY      __field(u32, cipher)                                            \