forked from Minki/linux
ath9k: Revamp VAP management
Remove the internal VAP management routines and embed ath_vap in mac80211's driver private area provided in ieee80211_vif. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a37c2c7940
commit
5640b08ef7
@ -152,12 +152,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
struct ath_vap *avp;
|
||||
struct sk_buff *skb;
|
||||
struct ath_txq *cabq;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_tx_info *info;
|
||||
int cabq_depth;
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
ASSERT(avp);
|
||||
vif = sc->sc_vaps[if_id];
|
||||
ASSERT(vif);
|
||||
|
||||
avp = (void *)vif->drv_priv;
|
||||
cabq = sc->sc_cabq;
|
||||
|
||||
if (avp->av_bcbuf == NULL) {
|
||||
@ -174,7 +176,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
|
||||
skb = ieee80211_beacon_get(sc->hw, vif);
|
||||
bf->bf_mpdu = skb;
|
||||
if (skb == NULL)
|
||||
return NULL;
|
||||
@ -196,7 +198,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
|
||||
skb = ieee80211_get_buffered_bc(sc->hw, vif);
|
||||
|
||||
/*
|
||||
* if the CABQ traffic from previous DTIM is pending and the current
|
||||
@ -232,7 +234,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
*/
|
||||
while (skb) {
|
||||
ath_tx_cabq(sc, skb);
|
||||
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
|
||||
skb = ieee80211_get_buffered_bc(sc->hw, vif);
|
||||
}
|
||||
|
||||
return bf;
|
||||
@ -244,13 +246,16 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
*/
|
||||
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_buf *bf;
|
||||
struct ath_vap *avp;
|
||||
struct sk_buff *skb;
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
ASSERT(avp);
|
||||
vif = sc->sc_vaps[if_id];
|
||||
ASSERT(vif);
|
||||
|
||||
avp = (void *)vif->drv_priv;
|
||||
|
||||
if (avp->av_bcbuf == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
|
||||
@ -300,14 +305,17 @@ int ath_beaconq_setup(struct ath_hal *ah)
|
||||
*/
|
||||
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_vap *avp;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath_buf *bf;
|
||||
struct sk_buff *skb;
|
||||
__le64 tstamp;
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
ASSERT(avp);
|
||||
vif = sc->sc_vaps[if_id];
|
||||
ASSERT(vif);
|
||||
|
||||
avp = (void *)vif->drv_priv;
|
||||
|
||||
/* Allocate a beacon descriptor if we haven't done so. */
|
||||
if (!avp->av_bcbuf) {
|
||||
@ -363,7 +371,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
* FIXME: Fill avp->av_btxctl.txpower and
|
||||
* avp->av_btxctl.shortPreamble
|
||||
*/
|
||||
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
|
||||
skb = ieee80211_beacon_get(sc->hw, vif);
|
||||
if (skb == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n",
|
||||
__func__);
|
||||
@ -652,15 +660,21 @@ void ath_bstuck_process(struct ath_softc *sc)
|
||||
*/
|
||||
void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_beacon_config conf;
|
||||
struct ath_vap *avp;
|
||||
enum ath9k_opmode av_opmode;
|
||||
u32 nexttbtt, intval;
|
||||
|
||||
if (if_id != ATH_IF_ID_ANY)
|
||||
av_opmode = sc->sc_vaps[if_id]->av_opmode;
|
||||
else
|
||||
if (if_id != ATH_IF_ID_ANY) {
|
||||
vif = sc->sc_vaps[if_id];
|
||||
ASSERT(vif);
|
||||
avp = (void *)vif->drv_priv;
|
||||
av_opmode = avp->av_opmode;
|
||||
} else {
|
||||
av_opmode = sc->sc_ah->ah_opmode;
|
||||
}
|
||||
|
||||
memset(&conf, 0, sizeof(struct ath_beacon_config));
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Implementation of the main "ATH" layer. */
|
||||
|
||||
#include "core.h"
|
||||
#include "regd.h"
|
||||
|
||||
@ -641,114 +639,6 @@ static void ath_ani_calibrate(unsigned long data)
|
||||
mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* VAP management */
|
||||
/******************/
|
||||
|
||||
int ath_vap_attach(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ieee80211_vif *if_data,
|
||||
enum ath9k_opmode opmode)
|
||||
{
|
||||
struct ath_vap *avp;
|
||||
|
||||
if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: Invalid interface id = %u\n", __func__, if_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (opmode) {
|
||||
case ATH9K_M_STA:
|
||||
case ATH9K_M_IBSS:
|
||||
case ATH9K_M_MONITOR:
|
||||
break;
|
||||
case ATH9K_M_HOSTAP:
|
||||
/* XXX not right, beacon buffer is allocated on RUN trans */
|
||||
if (list_empty(&sc->sc_bbuf))
|
||||
return -ENOMEM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* create ath_vap */
|
||||
avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL);
|
||||
if (avp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(avp, 0, sizeof(struct ath_vap));
|
||||
avp->av_if_data = if_data;
|
||||
/* Set the VAP opmode */
|
||||
avp->av_opmode = opmode;
|
||||
avp->av_bslot = -1;
|
||||
|
||||
if (opmode == ATH9K_M_HOSTAP)
|
||||
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
|
||||
|
||||
sc->sc_vaps[if_id] = avp;
|
||||
sc->sc_nvaps++;
|
||||
/* Set the device opmode */
|
||||
sc->sc_ah->ah_opmode = opmode;
|
||||
|
||||
/* default VAP configuration */
|
||||
avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
|
||||
avp->av_config.av_fixed_retryset = 0x03030303;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath_vap_detach(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_vap *avp;
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
if (avp == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
|
||||
__func__, if_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quiesce the hardware while we remove the vap. In
|
||||
* particular we need to reclaim all references to the
|
||||
* vap state by any frames pending on the tx queues.
|
||||
*
|
||||
* XXX can we do this w/o affecting other vap's?
|
||||
*/
|
||||
ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
|
||||
ath_draintxq(sc, false); /* stop xmit side */
|
||||
ath_stoprecv(sc); /* stop recv side */
|
||||
ath_flushrecv(sc); /* flush recv queue */
|
||||
|
||||
kfree(avp);
|
||||
sc->sc_vaps[if_id] = NULL;
|
||||
sc->sc_nvaps--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath_vap_config(struct ath_softc *sc,
|
||||
int if_id, struct ath_vap_config *if_config)
|
||||
{
|
||||
struct ath_vap *avp;
|
||||
|
||||
if (if_id >= ATH_BCBUF) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: Invalid interface id = %u\n", __func__, if_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
ASSERT(avp != NULL);
|
||||
|
||||
if (avp)
|
||||
memcpy(&avp->av_config, if_config, sizeof(avp->av_config));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********/
|
||||
/* Core */
|
||||
/********/
|
||||
@ -1356,14 +1246,10 @@ void ath_deinit(struct ath_softc *sc)
|
||||
/* Node Management */
|
||||
/*******************/
|
||||
|
||||
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, int if_id)
|
||||
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath_vap *avp;
|
||||
struct ath_node *an;
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
ASSERT(avp != NULL);
|
||||
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
|
@ -635,8 +635,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
void ath_newassoc(struct ath_softc *sc,
|
||||
struct ath_node *node, int isnew, int isuapsd);
|
||||
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
int if_id);
|
||||
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
|
||||
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
|
||||
|
||||
/*******************/
|
||||
@ -701,23 +700,14 @@ struct ath_vap_config {
|
||||
|
||||
/* driver-specific vap state */
|
||||
struct ath_vap {
|
||||
struct ieee80211_vif *av_if_data;
|
||||
int av_bslot; /* beacon slot index */
|
||||
enum ath9k_opmode av_opmode; /* VAP operational mode */
|
||||
struct ath_buf *av_bcbuf; /* beacon buffer */
|
||||
struct ath_tx_control av_btxctl; /* txctl information for beacon */
|
||||
int av_bslot; /* beacon slot index */
|
||||
struct ath_vap_config av_config;/* vap configuration parameters*/
|
||||
struct ath_rate_node *rc_node;
|
||||
};
|
||||
|
||||
int ath_vap_attach(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ieee80211_vif *if_data,
|
||||
enum ath9k_opmode opmode);
|
||||
int ath_vap_detach(struct ath_softc *sc, int if_id);
|
||||
int ath_vap_config(struct ath_softc *sc,
|
||||
int if_id, struct ath_vap_config *if_config);
|
||||
|
||||
/*********************/
|
||||
/* Antenna diversity */
|
||||
/*********************/
|
||||
@ -925,7 +915,7 @@ struct ath_softc {
|
||||
|
||||
u8 sc_nbcnvaps; /* # of vaps sending beacons */
|
||||
u16 sc_nvaps; /* # of active virtual ap's */
|
||||
struct ath_vap *sc_vaps[ATH_BCBUF];
|
||||
struct ieee80211_vif *sc_vaps[ATH_BCBUF];
|
||||
|
||||
u8 sc_mcastantenna;
|
||||
u8 sc_defant; /* current default antenna */
|
||||
|
@ -162,7 +162,7 @@ static int ath_key_config(struct ath_softc *sc,
|
||||
if (!sc->sc_vaps[0])
|
||||
return -EIO;
|
||||
|
||||
vif = sc->sc_vaps[0]->av_if_data;
|
||||
vif = sc->sc_vaps[0];
|
||||
opmode = vif->type;
|
||||
|
||||
/*
|
||||
@ -313,11 +313,12 @@ static void ath9k_ht_conf(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
struct ath_vap *avp;
|
||||
struct ath_vap *avp = (void *)vif->drv_priv;
|
||||
int pos;
|
||||
|
||||
if (bss_conf->assoc) {
|
||||
@ -325,13 +326,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
__func__,
|
||||
bss_conf->aid);
|
||||
|
||||
avp = sc->sc_vaps[0];
|
||||
if (avp == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* New association, store aid */
|
||||
if (avp->av_opmode == ATH9K_M_STA) {
|
||||
sc->sc_curaid = bss_conf->aid;
|
||||
@ -906,6 +900,7 @@ static int ath_attach(u16 devid,
|
||||
|
||||
hw->queues = 4;
|
||||
hw->sta_data_size = sizeof(struct ath_node);
|
||||
hw->vif_data_size = sizeof(struct ath_vap);
|
||||
|
||||
/* Register rate control */
|
||||
hw->rate_control_algorithm = "ath9k_rate_control";
|
||||
@ -1091,7 +1086,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
int error, ic_opmode = 0;
|
||||
struct ath_vap *avp = (void *)conf->vif->drv_priv;
|
||||
int ic_opmode = 0;
|
||||
|
||||
/* Support only vap for now */
|
||||
|
||||
@ -1119,13 +1115,22 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
__func__,
|
||||
ic_opmode);
|
||||
|
||||
error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
|
||||
if (error) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: Unable to attach vap, error: %d\n",
|
||||
__func__, error);
|
||||
return error;
|
||||
}
|
||||
/* Set the VAP opmode */
|
||||
avp->av_opmode = ic_opmode;
|
||||
avp->av_bslot = -1;
|
||||
|
||||
if (ic_opmode == ATH9K_M_HOSTAP)
|
||||
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
|
||||
|
||||
sc->sc_vaps[0] = conf->vif;
|
||||
sc->sc_nvaps++;
|
||||
|
||||
/* Set the device opmode */
|
||||
sc->sc_ah->ah_opmode = ic_opmode;
|
||||
|
||||
/* default VAP configuration */
|
||||
avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
|
||||
avp->av_config.av_fixed_retryset = 0x03030303;
|
||||
|
||||
if (conf->type == NL80211_IFTYPE_AP) {
|
||||
/* TODO: is this a suitable place to start ANI for AP mode? */
|
||||
@ -1141,27 +1146,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_vap *avp;
|
||||
int error;
|
||||
struct ath_vap *avp = (void *)conf->vif->drv_priv;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);
|
||||
|
||||
avp = sc->sc_vaps[0];
|
||||
if (avp == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SLOW_ANT_DIV
|
||||
ath_slow_ant_div_stop(&sc->sc_antdiv);
|
||||
#endif
|
||||
/* Stop ANI */
|
||||
del_timer_sync(&sc->sc_ani.timer);
|
||||
|
||||
/* Update ratectrl */
|
||||
ath_rate_newstate(sc, avp);
|
||||
|
||||
/* Reclaim beacon resources */
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
|
||||
sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
|
||||
@ -1169,16 +1163,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
ath_beacon_return(sc, avp);
|
||||
}
|
||||
|
||||
/* Set interrupt mask */
|
||||
sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
|
||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||
|
||||
error = ath_vap_detach(sc, 0);
|
||||
if (error)
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: Unable to detach vap, error: %d\n",
|
||||
__func__, error);
|
||||
sc->sc_vaps[0] = NULL;
|
||||
sc->sc_nvaps--;
|
||||
}
|
||||
|
||||
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
@ -1226,17 +1214,10 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_vap *avp;
|
||||
struct ath_vap *avp = (void *)vif->drv_priv;
|
||||
u32 rfilt = 0;
|
||||
int error, i;
|
||||
|
||||
avp = sc->sc_vaps[0];
|
||||
if (avp == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: Need to decide which hw opmode to use for multi-interface
|
||||
* cases */
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
@ -1317,7 +1298,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
/* Check for WLAN_CAPABILITY_PRIVACY ? */
|
||||
if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
|
||||
if ((avp->av_opmode != ATH9K_M_STA)) {
|
||||
for (i = 0; i < IEEE80211_WEP_NKID; i++)
|
||||
if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
|
||||
ath9k_hw_keysetmac(sc->sc_ah,
|
||||
@ -1366,9 +1347,6 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
|
||||
__func__, sc->rx_filter);
|
||||
}
|
||||
|
||||
/* Only a single interface is currently supported,
|
||||
so pass 0 as the interface id to ath_node_attach */
|
||||
|
||||
static void ath9k_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
@ -1378,7 +1356,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
ath_node_attach(sc, sta, 0);
|
||||
ath_node_attach(sc, sta);
|
||||
break;
|
||||
case STA_NOTIFY_REMOVE:
|
||||
ath_node_detach(sc, sta);
|
||||
@ -1496,7 +1474,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
|
||||
__func__,
|
||||
bss_conf->assoc);
|
||||
ath9k_bss_assoc_info(sc, bss_conf);
|
||||
ath9k_bss_assoc_info(sc, vif, bss_conf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2042,12 +2042,18 @@ static void ath_rate_free(void *priv)
|
||||
|
||||
static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_softc *sc = priv;
|
||||
struct ath_vap *avp = sc->sc_vaps[0];
|
||||
struct ath_vap *avp;
|
||||
struct ath_rate_node *rate_priv;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
|
||||
|
||||
vif = sc->sc_vaps[0];
|
||||
ASSERT(vif);
|
||||
|
||||
avp = (void *)vif->drv_priv;
|
||||
|
||||
rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
|
||||
if (!rate_priv) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
|
Loading…
Reference in New Issue
Block a user