Commit 9cb5412b authored by Pat Erley's avatar Pat Erley Committed by John W. Linville

Add mesh point functionality to ath9k

This patch enables mesh point operation for ath9k.  Tested with b43,
ath9k, rt2500usb, and ath5k as peers.
Signed-off-by: default avatarPat Erley <pat-lkml@erley.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d8cd7eff
...@@ -70,7 +70,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, ...@@ -70,7 +70,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
ds = bf->bf_desc; ds = bf->bf_desc;
flags = ATH9K_TXDESC_NOACK; flags = ATH9K_TXDESC_NOACK;
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC && if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
ds->ds_link = bf->bf_daddr; /* self-linked */ ds->ds_link = bf->bf_daddr; /* self-linked */
flags |= ATH9K_TXDESC_VEOL; flags |= ATH9K_TXDESC_VEOL;
...@@ -728,6 +729,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) ...@@ -728,6 +729,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
ath_beacon_config_ap(sc, &conf, avp); ath_beacon_config_ap(sc, &conf, avp);
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
ath_beacon_config_adhoc(sc, &conf, avp, vif); ath_beacon_config_adhoc(sc, &conf, avp, vif);
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
......
...@@ -1448,6 +1448,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) ...@@ -1448,6 +1448,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
| AR_STA_ID1_KSRCH_MODE); | AR_STA_ID1_KSRCH_MODE);
REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
...@@ -3149,6 +3150,7 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) ...@@ -3149,6 +3150,7 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
flags |= AR_TBTT_TIMER_EN; flags |= AR_TBTT_TIMER_EN;
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
REG_SET_BIT(ah, AR_TXCFG, REG_SET_BIT(ah, AR_TXCFG,
AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
REG_WRITE(ah, AR_NEXT_NDP_TIMER, REG_WRITE(ah, AR_NEXT_NDP_TIMER,
......
...@@ -1599,7 +1599,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -1599,7 +1599,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->interface_modes = hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC); BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
hw->wiphy->reg_notifier = ath9k_reg_notifier; hw->wiphy->reg_notifier = ath9k_reg_notifier;
hw->wiphy->strict_regulatory = true; hw->wiphy->strict_regulatory = true;
...@@ -2207,18 +2208,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ...@@ -2207,18 +2208,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
ic_opmode = NL80211_IFTYPE_STATION; ic_opmode = NL80211_IFTYPE_STATION;
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
if (sc->nbcnvifs >= ATH_BCBUF) {
ret = -ENOBUFS;
goto out;
}
ic_opmode = NL80211_IFTYPE_ADHOC;
break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
if (sc->nbcnvifs >= ATH_BCBUF) { if (sc->nbcnvifs >= ATH_BCBUF) {
ret = -ENOBUFS; ret = -ENOBUFS;
goto out; goto out;
} }
ic_opmode = NL80211_IFTYPE_AP; ic_opmode = conf->type;
break; break;
default: default:
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,
...@@ -2254,7 +2250,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ...@@ -2254,7 +2250,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
* Note we only do this (at the moment) for station mode. * Note we only do this (at the moment) for station mode.
*/ */
if ((conf->type == NL80211_IFTYPE_STATION) || if ((conf->type == NL80211_IFTYPE_STATION) ||
(conf->type == NL80211_IFTYPE_ADHOC)) { (conf->type == NL80211_IFTYPE_ADHOC) ||
(conf->type == NL80211_IFTYPE_MESH_POINT)) {
if (ath9k_hw_phycounters(sc->sc_ah)) if (ath9k_hw_phycounters(sc->sc_ah))
sc->imask |= ATH9K_INT_MIB; sc->imask |= ATH9K_INT_MIB;
sc->imask |= ATH9K_INT_TSFOOR; sc->imask |= ATH9K_INT_TSFOOR;
...@@ -2301,8 +2298,9 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, ...@@ -2301,8 +2298,9 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
del_timer_sync(&sc->ani.timer); del_timer_sync(&sc->ani.timer);
/* Reclaim beacon resources */ /* Reclaim beacon resources */
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) { (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
ath_beacon_return(sc, avp); ath_beacon_return(sc, avp);
} }
...@@ -2435,6 +2433,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, ...@@ -2435,6 +2433,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
/* Set BSSID */ /* Set BSSID */
memcpy(sc->curbssid, conf->bssid, ETH_ALEN); memcpy(sc->curbssid, conf->bssid, ETH_ALEN);
memcpy(avp->bssid, conf->bssid, ETH_ALEN); memcpy(avp->bssid, conf->bssid, ETH_ALEN);
...@@ -2458,7 +2457,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, ...@@ -2458,7 +2457,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
} }
if ((vif->type == NL80211_IFTYPE_ADHOC) || if ((vif->type == NL80211_IFTYPE_ADHOC) ||
(vif->type == NL80211_IFTYPE_AP)) { (vif->type == NL80211_IFTYPE_AP) ||
(vif->type == NL80211_IFTYPE_MESH_POINT)) {
if ((conf->changed & IEEE80211_IFCC_BEACON) || if ((conf->changed & IEEE80211_IFCC_BEACON) ||
(conf->changed & IEEE80211_IFCC_BEACON_ENABLED && (conf->changed & IEEE80211_IFCC_BEACON_ENABLED &&
conf->enable_beacon)) { conf->enable_beacon)) {
......
...@@ -1619,6 +1619,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, ...@@ -1619,6 +1619,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
/* Choose rate table first */ /* Choose rate table first */
if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
rate_table = ath_choose_rate_table(sc, sband->band, rate_table = ath_choose_rate_table(sc, sband->band,
sta->ht_cap.ht_supported, sta->ht_cap.ht_supported,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment