LinuxKPI: 802.11: factor out getting and setting a chanctx
Further factor out acquiring the chanctx (either set or new), as well as populating a chanctx with information. This further simplifies lkpi_sta_scan_to_auth() and gives us more reusable function blocks. Sponsored by: The FreeBSD Foundation MFC after; 3 days
This commit is contained in:
@@ -2319,6 +2319,94 @@ lkpi_find_lchanctx_reserved(struct ieee80211_hw *hw, struct lkpi_vif *lvif)
|
|||||||
return (lchanctx);
|
return (lchanctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ieee80211_chanctx_conf *
|
||||||
|
lkpi_get_chanctx_conf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
|
||||||
|
chanctx_conf = rcu_dereference_protected(vif->bss_conf.chanctx_conf,
|
||||||
|
lockdep_is_held(&hw->wiphy->mtx));
|
||||||
|
if (chanctx_conf == NULL) {
|
||||||
|
struct lkpi_chanctx *lchanctx;
|
||||||
|
struct lkpi_vif *lvif;
|
||||||
|
|
||||||
|
lvif = VIF_TO_LVIF(vif);
|
||||||
|
lchanctx = lkpi_find_lchanctx_reserved(hw, lvif);
|
||||||
|
KASSERT(lchanctx != NULL, ("%s: hw %p, vif %p no lchanctx\n",
|
||||||
|
__func__, hw, vif));
|
||||||
|
list_del(&lchanctx->entry);
|
||||||
|
chanctx_conf = &lchanctx->chanctx_conf;
|
||||||
|
}
|
||||||
|
/* else { IMPROVE("diff changes for changed, working on live copy, rcu"); } */
|
||||||
|
|
||||||
|
return (chanctx_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lkpi_set_chanctx_conf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_chanctx_conf *chanctx_conf,
|
||||||
|
uint32_t changed, bool changed_set)
|
||||||
|
{
|
||||||
|
struct lkpi_hw *lhw;
|
||||||
|
struct lkpi_chanctx *lchanctx;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (vif->bss_conf.chanctx_conf == chanctx_conf) {
|
||||||
|
if (!changed_set) {
|
||||||
|
IMPROVE("OBSOLETE?");
|
||||||
|
changed = IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
|
||||||
|
changed |= IEEE80211_CHANCTX_CHANGE_RADAR;
|
||||||
|
changed |= IEEE80211_CHANCTX_CHANGE_RX_CHAINS;
|
||||||
|
changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
|
||||||
|
}
|
||||||
|
lkpi_80211_mo_change_chanctx(hw, chanctx_conf, changed);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lhw = HW_TO_LHW(hw);
|
||||||
|
|
||||||
|
/* The device is no longer idle. */
|
||||||
|
IMPROVE("Once we do multi-vif, only do for 1st chanctx");
|
||||||
|
lkpi_hw_conf_idle(hw, false);
|
||||||
|
|
||||||
|
error = lkpi_80211_mo_add_chanctx(hw, chanctx_conf);
|
||||||
|
if (error != 0 && error != EOPNOTSUPP) {
|
||||||
|
ic_printf(lhw->ic, "%s:%d: mo_add_chanctx "
|
||||||
|
"failed: %d\n", __func__, __LINE__, error);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
vif->bss_conf.chanreq.oper.chan = chanctx_conf->def.chan;
|
||||||
|
vif->bss_conf.chanreq.oper.width = chanctx_conf->def.width;
|
||||||
|
vif->bss_conf.chanreq.oper.center_freq1 =
|
||||||
|
chanctx_conf->def.center_freq1;
|
||||||
|
vif->bss_conf.chanreq.oper.center_freq2 =
|
||||||
|
chanctx_conf->def.center_freq2;
|
||||||
|
|
||||||
|
lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
|
||||||
|
list_add_rcu(&lchanctx->entry, &lhw->lchanctx_list);
|
||||||
|
rcu_assign_pointer(vif->bss_conf.chanctx_conf, chanctx_conf);
|
||||||
|
|
||||||
|
/* Assign vif chanctx. */
|
||||||
|
if (error == 0)
|
||||||
|
error = lkpi_80211_mo_assign_vif_chanctx(hw, vif,
|
||||||
|
&vif->bss_conf, chanctx_conf);
|
||||||
|
if (error == EOPNOTSUPP)
|
||||||
|
error = 0;
|
||||||
|
if (error != 0) {
|
||||||
|
ic_printf(lhw->ic, "%s:%d: mo_assign_vif_chanctx "
|
||||||
|
"failed: %d\n", __func__, __LINE__, error);
|
||||||
|
lkpi_80211_mo_remove_chanctx(hw, chanctx_conf);
|
||||||
|
rcu_assign_pointer(vif->bss_conf.chanctx_conf, NULL);
|
||||||
|
lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
|
||||||
|
list_del(&lchanctx->entry);
|
||||||
|
list_add_rcu(&lchanctx->entry, &lhw->lchanctx_list_reserved);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lkpi_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
lkpi_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
@@ -2419,7 +2507,6 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
|
|||||||
{
|
{
|
||||||
struct linuxkpi_ieee80211_channel *chan;
|
struct linuxkpi_ieee80211_channel *chan;
|
||||||
struct cfg80211_chan_def chandef;
|
struct cfg80211_chan_def chandef;
|
||||||
struct lkpi_chanctx *lchanctx;
|
|
||||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
struct lkpi_hw *lhw;
|
struct lkpi_hw *lhw;
|
||||||
struct ieee80211_hw *hw;
|
struct ieee80211_hw *hw;
|
||||||
@@ -2488,16 +2575,7 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
|
|||||||
wiphy_lock(hw->wiphy);
|
wiphy_lock(hw->wiphy);
|
||||||
|
|
||||||
/* Add chanctx (or if exists, change it). */
|
/* Add chanctx (or if exists, change it). */
|
||||||
chanctx_conf = rcu_dereference_protected(vif->bss_conf.chanctx_conf,
|
chanctx_conf = lkpi_get_chanctx_conf(hw, vif);
|
||||||
lockdep_is_held(&hw->wiphy->mtx));
|
|
||||||
if (chanctx_conf != NULL) {
|
|
||||||
lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
|
|
||||||
IMPROVE("diff changes for changed, working on live copy, rcu");
|
|
||||||
} else {
|
|
||||||
lchanctx = lkpi_find_lchanctx_reserved(hw, lvif);
|
|
||||||
list_del(&lchanctx->entry);
|
|
||||||
chanctx_conf = &lchanctx->chanctx_conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
KASSERT(ni->ni_chan != NULL && ni->ni_chan != IEEE80211_CHAN_ANYC,
|
KASSERT(ni->ni_chan != NULL && ni->ni_chan != IEEE80211_CHAN_ANYC,
|
||||||
("%s:%d: ni %p ni_chan %p\n", __func__, __LINE__, ni, ni->ni_chan));
|
("%s:%d: ni %p ni_chan %p\n", __func__, __LINE__, ni, ni->ni_chan));
|
||||||
@@ -2534,52 +2612,10 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
|
|||||||
|
|
||||||
bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
|
bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
|
||||||
|
|
||||||
error = 0;
|
error = lkpi_set_chanctx_conf(hw, vif, chanctx_conf, changed, true);
|
||||||
if (vif->bss_conf.chanctx_conf == chanctx_conf) {
|
if (error != 0)
|
||||||
changed = IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
|
|
||||||
changed |= IEEE80211_CHANCTX_CHANGE_RADAR;
|
|
||||||
changed |= IEEE80211_CHANCTX_CHANGE_RX_CHAINS;
|
|
||||||
changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
|
|
||||||
lkpi_80211_mo_change_chanctx(hw, chanctx_conf, changed);
|
|
||||||
} else {
|
|
||||||
/* The device is no longer idle. */
|
|
||||||
IMPROVE("Once we do multi-vif, only do for 1st chanctx");
|
|
||||||
lkpi_hw_conf_idle(hw, false);
|
|
||||||
|
|
||||||
error = lkpi_80211_mo_add_chanctx(hw, chanctx_conf);
|
|
||||||
if (error == 0 || error == EOPNOTSUPP) {
|
|
||||||
vif->bss_conf.chanreq.oper.chan = chanctx_conf->def.chan;
|
|
||||||
vif->bss_conf.chanreq.oper.width = chanctx_conf->def.width;
|
|
||||||
vif->bss_conf.chanreq.oper.center_freq1 =
|
|
||||||
chanctx_conf->def.center_freq1;
|
|
||||||
vif->bss_conf.chanreq.oper.center_freq2 =
|
|
||||||
chanctx_conf->def.center_freq2;
|
|
||||||
} else {
|
|
||||||
ic_printf(vap->iv_ic, "%s:%d: mo_add_chanctx "
|
|
||||||
"failed: %d\n", __func__, __LINE__, error);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
list_add_rcu(&lchanctx->entry, &lhw->lchanctx_list);
|
|
||||||
rcu_assign_pointer(vif->bss_conf.chanctx_conf, chanctx_conf);
|
|
||||||
|
|
||||||
/* Assign vif chanctx. */
|
|
||||||
if (error == 0)
|
|
||||||
error = lkpi_80211_mo_assign_vif_chanctx(hw, vif,
|
|
||||||
&vif->bss_conf, chanctx_conf);
|
|
||||||
if (error == EOPNOTSUPP)
|
|
||||||
error = 0;
|
|
||||||
if (error != 0) {
|
|
||||||
ic_printf(vap->iv_ic, "%s:%d: mo_assign_vif_chanctx "
|
|
||||||
"failed: %d\n", __func__, __LINE__, error);
|
|
||||||
lkpi_80211_mo_remove_chanctx(hw, chanctx_conf);
|
|
||||||
rcu_assign_pointer(vif->bss_conf.chanctx_conf, NULL);
|
|
||||||
lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
|
|
||||||
list_del(&lchanctx->entry);
|
|
||||||
list_add_rcu(&lchanctx->entry, &lhw->lchanctx_list_reserved);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IMPROVE("update radiotap chan fields too");
|
IMPROVE("update radiotap chan fields too");
|
||||||
|
|
||||||
/* RATES */
|
/* RATES */
|
||||||
|
|||||||
Reference in New Issue
Block a user