u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
 
        struct mac_address addresses[2];
+       struct ieee80211_chanctx_conf *chanctx;
        int channels, idx;
        bool use_chanctx;
        bool destroy_on_close;
 
 static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
                                       struct sk_buff *my_skb,
-                                      int dst_portid)
+                                      int dst_portid,
+                                      struct ieee80211_channel *channel)
 {
        struct sk_buff *skb;
        struct mac80211_hwsim_data *data = hw->priv;
        if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags))
                goto nla_put_failure;
 
-       if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq))
+       if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq))
                goto nla_put_failure;
 
        /* We get the tx control (rate and retries) info*/
        _portid = READ_ONCE(data->wmediumd);
 
        if (_portid || hwsim_virtio_enabled)
-               return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
+               return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel);
 
        /* NO wmediumd detected, perfect medium simulation */
        data->tx_pkts++;
        mac80211_hwsim_monitor_rx(hw, skb, chan);
 
        if (_pid || hwsim_virtio_enabled)
-               return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+               return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan);
 
        mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
        dev_kfree_skb(skb);
 static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
                                      struct ieee80211_chanctx_conf *ctx)
 {
+       struct mac80211_hwsim_data *hwsim = hw->priv;
+
+       mutex_lock(&hwsim->mutex);
+       hwsim->chanctx = ctx;
+       mutex_unlock(&hwsim->mutex);
        hwsim_set_chanctx_magic(ctx);
        wiphy_dbg(hw->wiphy,
                  "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
 static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
                                          struct ieee80211_chanctx_conf *ctx)
 {
+       struct mac80211_hwsim_data *hwsim = hw->priv;
+
+       mutex_lock(&hwsim->mutex);
+       hwsim->chanctx = NULL;
+       mutex_unlock(&hwsim->mutex);
        wiphy_dbg(hw->wiphy,
                  "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
                  ctx->def.chan->center_freq, ctx->def.width,
                                          struct ieee80211_chanctx_conf *ctx,
                                          u32 changed)
 {
+       struct mac80211_hwsim_data *hwsim = hw->priv;
+
+       mutex_lock(&hwsim->mutex);
+       hwsim->chanctx = ctx;
+       mutex_unlock(&hwsim->mutex);
        hwsim_check_chanctx_magic(ctx);
        wiphy_dbg(hw->wiphy,
                  "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
                hw->wiphy->max_remain_on_channel_duration = 1000;
                data->if_combination.radar_detect_widths = 0;
                data->if_combination.num_different_channels = data->channels;
+               data->chanctx = NULL;
        } else {
                data->if_combination.num_different_channels = 1;
                data->if_combination.radar_detect_widths =
        int frame_data_len;
        void *frame_data;
        struct sk_buff *skb = NULL;
+       struct ieee80211_channel *channel = NULL;
 
        if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
            !info->attrs[HWSIM_ATTR_FRAME] ||
        if (!data2)
                goto out;
 
+       if (data2->use_chanctx) {
+               if (data2->tmp_chan)
+                       channel = data2->tmp_chan;
+               else if (data2->chanctx)
+                       channel = data2->chanctx->def.chan;
+       } else {
+               channel = data2->channel;
+       }
+       if (!channel)
+               goto out;
+
        if (!hwsim_virtio_enabled) {
                if (hwsim_net_get_netgroup(genl_info_net(info)) !=
                    data2->netgroup)
 
        /* check if radio is configured properly */
 
-       if (data2->idle || !data2->started)
+       if ((data2->idle && !data2->tmp_chan) || !data2->started)
                goto out;
 
        /* A frame is received from user space */
                mutex_lock(&data2->mutex);
                rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]);
 
-               if (rx_status.freq != data2->channel->center_freq &&
-                   (!data2->tmp_chan ||
-                    rx_status.freq != data2->tmp_chan->center_freq)) {
+               if (rx_status.freq != channel->center_freq) {
                        mutex_unlock(&data2->mutex);
                        goto out;
                }
                mutex_unlock(&data2->mutex);
        } else {
-               rx_status.freq = data2->channel->center_freq;
+               rx_status.freq = channel->center_freq;
        }
 
-       rx_status.band = data2->channel->band;
+       rx_status.band = channel->band;
        rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
        rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);