/* This is work queue function for channel switch handling. * This function takes care of updating new channel definitin to * bss config structure, restart AP and indicate channel switch success * to cfg80211. */ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) { struct mwifiex_uap_bss_param *bss_cfg; struct delayed_work *delayed_work = to_delayed_work(work); struct mwifiex_private *priv = container_of(delayed_work, struct mwifiex_private, dfs_chan_sw_work); bss_cfg = &priv->bss_cfg; if (!bss_cfg->beacon_period) { mwifiex_dbg(priv->adapter, ERROR, "channel switch: AP already stopped\n"); return; } mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef); if (mwifiex_config_start_uap(priv, bss_cfg)) { mwifiex_dbg(priv->adapter, ERROR, "Failed to start AP after channel switch\n"); return; } mwifiex_dbg(priv->adapter, MSG, "indicating channel switch completion to kernel\n"); cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef); }
/* * This function sets the RF channel. * * This function creates multiple IOCTL requests, populates them accordingly * and issues them to set the band/channel and frequency. */ static int mwifiex_set_rf_channel(struct mwifiex_private *priv, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { struct mwifiex_chan_freq_power cfp; u32 config_bands = 0; struct wiphy *wiphy = priv->wdev->wiphy; struct mwifiex_adapter *adapter = priv->adapter; if (chan) { /* Set appropriate bands */ if (chan->band == IEEE80211_BAND_2GHZ) { if (channel_type == NL80211_CHAN_NO_HT) if (priv->adapter->config_bands == BAND_B || priv->adapter->config_bands == BAND_G) config_bands = priv->adapter->config_bands; else config_bands = BAND_B | BAND_G; else config_bands = BAND_B | BAND_G | BAND_GN; } else { if (channel_type == NL80211_CHAN_NO_HT) config_bands = BAND_A; else config_bands = BAND_AN | BAND_A; } if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) { adapter->config_bands = config_bands; if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { adapter->adhoc_start_band = config_bands; if ((config_bands & BAND_GN) || (config_bands & BAND_AN)) adapter->adhoc_11n_enabled = true; else adapter->adhoc_11n_enabled = false; } } adapter->sec_chan_offset = mwifiex_cfg80211_channel_type_to_sec_chan_offset (channel_type); adapter->channel_type = channel_type; mwifiex_send_domain_info_cmd_fw(wiphy); } wiphy_dbg(wiphy, "info: setting band %d, chan offset %d, mode %d\n", config_bands, adapter->sec_chan_offset, priv->bss_mode); if (!chan) return 0; memset(&cfp, 0, sizeof(cfp)); cfp.freq = chan->center_freq; cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); if (mwifiex_bss_set_channel(priv, &cfp)) return -EFAULT; if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); else return mwifiex_uap_set_channel(priv, cfp.channel); }