static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params) { struct qtnf_wmac *mac = wiphy_priv(wiphy); struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); int ret; pr_debug("%s: chan(%u) count(%u) radar(%u) block_tx(%u)\n", dev->name, params->chandef.chan->hw_value, params->count, params->radar_required, params->block_tx); switch (vif->wdev.iftype) { case NL80211_IFTYPE_AP: if (!(vif->bss_status & QTNF_STATE_AP_START)) { pr_warn("AP not started on %s\n", dev->name); return -ENOTCONN; } break; default: pr_err("unsupported vif type (%d) on %s\n", vif->wdev.iftype, dev->name); return -EOPNOTSUPP; } if (vif->vifid != 0) { if (!(mac->status & QTNF_MAC_CSA_ACTIVE)) return -EOPNOTSUPP; if (!cfg80211_chandef_identical(¶ms->chandef, &mac->csa_chandef)) return -EINVAL; return 0; } if (!cfg80211_chandef_valid(¶ms->chandef)) { pr_err("%s: invalid channel\n", dev->name); return -EINVAL; } if (cfg80211_chandef_identical(¶ms->chandef, &mac->chandef)) { pr_err("%s: switch request to the same channel\n", dev->name); return -EALREADY; } ret = qtnf_cmd_send_chan_switch(mac, params); if (ret) pr_warn("%s: failed to switch to channel (%u)\n", dev->name, params->chandef.chan->hw_value); return ret; }
const struct cfg80211_chan_def * cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, const struct cfg80211_chan_def *c2) { u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; /* If they are identical, return */ if (cfg80211_chandef_identical(c1, c2)) return c1; /* otherwise, must have same control channel */ if (c1->chan != c2->chan) return NULL; /* * If they have the same width, but aren't identical, * then they can't be compatible. */ if (c1->width == c2->width) return NULL; /* * can't be compatible if one of them is 5 or 10 MHz, * but they don't have the same width. */ if (c1->width == NL80211_CHAN_WIDTH_5 || c1->width == NL80211_CHAN_WIDTH_10 || c2->width == NL80211_CHAN_WIDTH_5 || c2->width == NL80211_CHAN_WIDTH_10) return NULL; if (c1->width == NL80211_CHAN_WIDTH_20_NOHT || c1->width == NL80211_CHAN_WIDTH_20) return c2; if (c2->width == NL80211_CHAN_WIDTH_20_NOHT || c2->width == NL80211_CHAN_WIDTH_20) return c1; chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); if (c1_pri40 != c2_pri40) return NULL; WARN_ON(!c1_pri80 && !c2_pri80); if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) return NULL; if (c1->width > c2->width) return c1; return c2; }
static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings) { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); struct qtnf_wmac *mac = wiphy_priv(wiphy); struct qtnf_bss_config *bss_cfg; int ret; if (!cfg80211_chandef_identical(&mac->chandef, &settings->chandef)) { memcpy(&mac->chandef, &settings->chandef, sizeof(mac->chandef)); if (vif->vifid != 0) pr_warn("%s: unexpected chan %u (%u MHz)\n", dev->name, settings->chandef.chan->hw_value, settings->chandef.chan->center_freq); } bss_cfg = &vif->bss_cfg; memset(bss_cfg, 0, sizeof(*bss_cfg)); bss_cfg->bcn_period = settings->beacon_interval; bss_cfg->dtim = settings->dtim_period; bss_cfg->auth_type = settings->auth_type; bss_cfg->privacy = settings->privacy; bss_cfg->ssid_len = settings->ssid_len; memcpy(&bss_cfg->ssid, settings->ssid, bss_cfg->ssid_len); memcpy(&bss_cfg->crypto, &settings->crypto, sizeof(struct cfg80211_crypto_settings)); ret = qtnf_cmd_send_config_ap(vif); if (ret) { pr_err("VIF%u.%u: failed to push config to FW\n", vif->mac->macid, vif->vifid); goto out; } if (!(vif->bss_status & QTNF_STATE_AP_CONFIG)) { pr_err("VIF%u.%u: AP config failed in FW\n", vif->mac->macid, vif->vifid); ret = -EFAULT; goto out; } ret = qtnf_mgmt_set_appie(vif, &settings->beacon); if (ret) { pr_err("VIF%u.%u: failed to add IEs to beacon\n", vif->mac->macid, vif->vifid); goto out; } ret = qtnf_cmd_send_start_ap(vif); if (ret) { pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid, vif->vifid); goto out; } if (!(vif->bss_status & QTNF_STATE_AP_START)) { pr_err("VIF%u.%u: FW failed to start AP operation\n", vif->mac->macid, vif->vifid); ret = -EFAULT; } out: return ret; }