ath9k: Add change_interface callback
Add support to change interface type without bringing down the interface. Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a7ffac9591
commit
6b3b991dbd
@ -1428,13 +1428,78 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_reclaim_beacon(struct ath_softc *sc,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
|
||||
/* Disable SWBA interrupt */
|
||||
sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
|
||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
tasklet_kill(&sc->bcon_tasklet);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
ath_beacon_return(sc, avp);
|
||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||
|
||||
if (sc->nbcnvifs > 0) {
|
||||
/* Re-enable beaconing */
|
||||
sc->sc_ah->imask |= ATH9K_INT_SWBA;
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath9k_change_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype new_type,
|
||||
bool p2p)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
switch (new_type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (sc->nbcnvifs >= ATH_BCBUF) {
|
||||
ath_err(common, "No beacon slot available\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
/* Stop ANI */
|
||||
sc->sc_flags &= ~SC_OP_ANI_RUN;
|
||||
del_timer_sync(&common->ani.timer);
|
||||
if ((vif->type == NL80211_IFTYPE_AP) ||
|
||||
(vif->type == NL80211_IFTYPE_ADHOC))
|
||||
ath9k_reclaim_beacon(sc, vif);
|
||||
break;
|
||||
default:
|
||||
ath_err(common, "Interface type %d not yet supported\n",
|
||||
vif->type);
|
||||
mutex_unlock(&sc->mutex);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
vif->type = new_type;
|
||||
vif->p2p = p2p;
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
|
||||
ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
|
||||
|
||||
@ -1447,26 +1512,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
/* Reclaim beacon resources */
|
||||
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
|
||||
/* Disable SWBA interrupt */
|
||||
sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
|
||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
ath9k_ps_restore(sc);
|
||||
tasklet_kill(&sc->bcon_tasklet);
|
||||
}
|
||||
|
||||
ath_beacon_return(sc, avp);
|
||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||
|
||||
if (sc->nbcnvifs) {
|
||||
/* Re-enable SWBA interrupt */
|
||||
sc->sc_ah->imask |= ATH9K_INT_SWBA;
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
|
||||
ath9k_reclaim_beacon(sc, vif);
|
||||
|
||||
sc->nvifs--;
|
||||
|
||||
@ -2111,6 +2158,7 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.start = ath9k_start,
|
||||
.stop = ath9k_stop,
|
||||
.add_interface = ath9k_add_interface,
|
||||
.change_interface = ath9k_change_interface,
|
||||
.remove_interface = ath9k_remove_interface,
|
||||
.config = ath9k_config,
|
||||
.configure_filter = ath9k_configure_filter,
|
||||
|
Loading…
Reference in New Issue
Block a user