2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-26 22:24:09 +08:00

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:
Sujith 2008-10-29 10:16:06 +05:30 committed by John W. Linville
parent a37c2c7940
commit 5640b08ef7
5 changed files with 67 additions and 193 deletions

View File

@ -152,12 +152,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
struct ath_vap *avp; struct ath_vap *avp;
struct sk_buff *skb; struct sk_buff *skb;
struct ath_txq *cabq; struct ath_txq *cabq;
struct ieee80211_vif *vif;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
int cabq_depth; int cabq_depth;
avp = sc->sc_vaps[if_id]; vif = sc->sc_vaps[if_id];
ASSERT(avp); ASSERT(vif);
avp = (void *)vif->drv_priv;
cabq = sc->sc_cabq; cabq = sc->sc_cabq;
if (avp->av_bcbuf == NULL) { 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); PCI_DMA_TODEVICE);
} }
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); skb = ieee80211_beacon_get(sc->hw, vif);
bf->bf_mpdu = skb; bf->bf_mpdu = skb;
if (skb == NULL) if (skb == NULL)
return 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, skb_end_pointer(skb) - skb->head,
PCI_DMA_TODEVICE); 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 * 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) { while (skb) {
ath_tx_cabq(sc, 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; 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) 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_hal *ah = sc->sc_ah;
struct ath_buf *bf; struct ath_buf *bf;
struct ath_vap *avp; struct ath_vap *avp;
struct sk_buff *skb; struct sk_buff *skb;
avp = sc->sc_vaps[if_id]; vif = sc->sc_vaps[if_id];
ASSERT(avp); ASSERT(vif);
avp = (void *)vif->drv_priv;
if (avp->av_bcbuf == NULL) { if (avp->av_bcbuf == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", 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) int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{ {
struct ieee80211_vif *vif;
struct ath_vap *avp; struct ath_vap *avp;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ath_buf *bf; struct ath_buf *bf;
struct sk_buff *skb; struct sk_buff *skb;
__le64 tstamp; __le64 tstamp;
avp = sc->sc_vaps[if_id]; vif = sc->sc_vaps[if_id];
ASSERT(avp); ASSERT(vif);
avp = (void *)vif->drv_priv;
/* Allocate a beacon descriptor if we haven't done so. */ /* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) { 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 * FIXME: Fill avp->av_btxctl.txpower and
* avp->av_btxctl.shortPreamble * avp->av_btxctl.shortPreamble
*/ */
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); skb = ieee80211_beacon_get(sc->hw, vif);
if (skb == NULL) { if (skb == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n", DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n",
__func__); __func__);
@ -652,15 +660,21 @@ void ath_bstuck_process(struct ath_softc *sc)
*/ */
void ath_beacon_config(struct ath_softc *sc, int if_id) void ath_beacon_config(struct ath_softc *sc, int if_id)
{ {
struct ieee80211_vif *vif;
struct ath_hal *ah = sc->sc_ah; struct ath_hal *ah = sc->sc_ah;
struct ath_beacon_config conf; struct ath_beacon_config conf;
struct ath_vap *avp;
enum ath9k_opmode av_opmode; enum ath9k_opmode av_opmode;
u32 nexttbtt, intval; u32 nexttbtt, intval;
if (if_id != ATH_IF_ID_ANY) if (if_id != ATH_IF_ID_ANY) {
av_opmode = sc->sc_vaps[if_id]->av_opmode; vif = sc->sc_vaps[if_id];
else ASSERT(vif);
avp = (void *)vif->drv_priv;
av_opmode = avp->av_opmode;
} else {
av_opmode = sc->sc_ah->ah_opmode; av_opmode = sc->sc_ah->ah_opmode;
}
memset(&conf, 0, sizeof(struct ath_beacon_config)); memset(&conf, 0, sizeof(struct ath_beacon_config));

View File

@ -14,8 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* Implementation of the main "ATH" layer. */
#include "core.h" #include "core.h"
#include "regd.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)); 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 */ /* Core */
/********/ /********/
@ -1356,14 +1246,10 @@ void ath_deinit(struct ath_softc *sc)
/* Node Management */ /* 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; struct ath_node *an;
avp = sc->sc_vaps[if_id];
ASSERT(avp != NULL);
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
if (sc->sc_flags & SC_OP_TXAGGR) if (sc->sc_flags & SC_OP_TXAGGR)

View File

@ -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); int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_newassoc(struct ath_softc *sc, void ath_newassoc(struct ath_softc *sc,
struct ath_node *node, int isnew, int isuapsd); struct ath_node *node, int isnew, int isuapsd);
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
int if_id);
void ath_node_detach(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 */ /* driver-specific vap state */
struct ath_vap { struct ath_vap {
struct ieee80211_vif *av_if_data; int av_bslot; /* beacon slot index */
enum ath9k_opmode av_opmode; /* VAP operational mode */ enum ath9k_opmode av_opmode; /* VAP operational mode */
struct ath_buf *av_bcbuf; /* beacon buffer */ struct ath_buf *av_bcbuf; /* beacon buffer */
struct ath_tx_control av_btxctl; /* txctl information for beacon */ 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_vap_config av_config;/* vap configuration parameters*/
struct ath_rate_node *rc_node; 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 */ /* Antenna diversity */
/*********************/ /*********************/
@ -925,7 +915,7 @@ struct ath_softc {
u8 sc_nbcnvaps; /* # of vaps sending beacons */ u8 sc_nbcnvaps; /* # of vaps sending beacons */
u16 sc_nvaps; /* # of active virtual ap's */ 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_mcastantenna;
u8 sc_defant; /* current default antenna */ u8 sc_defant; /* current default antenna */

View File

@ -162,7 +162,7 @@ static int ath_key_config(struct ath_softc *sc,
if (!sc->sc_vaps[0]) if (!sc->sc_vaps[0])
return -EIO; return -EIO;
vif = sc->sc_vaps[0]->av_if_data; vif = sc->sc_vaps[0];
opmode = vif->type; 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, static void ath9k_bss_assoc_info(struct ath_softc *sc,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf) struct ieee80211_bss_conf *bss_conf)
{ {
struct ieee80211_hw *hw = sc->hw; struct ieee80211_hw *hw = sc->hw;
struct ieee80211_channel *curchan = hw->conf.channel; struct ieee80211_channel *curchan = hw->conf.channel;
struct ath_vap *avp; struct ath_vap *avp = (void *)vif->drv_priv;
int pos; int pos;
if (bss_conf->assoc) { if (bss_conf->assoc) {
@ -325,13 +326,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
__func__, __func__,
bss_conf->aid); 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 */ /* New association, store aid */
if (avp->av_opmode == ATH9K_M_STA) { if (avp->av_opmode == ATH9K_M_STA) {
sc->sc_curaid = bss_conf->aid; sc->sc_curaid = bss_conf->aid;
@ -906,6 +900,7 @@ static int ath_attach(u16 devid,
hw->queues = 4; hw->queues = 4;
hw->sta_data_size = sizeof(struct ath_node); hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vap);
/* Register rate control */ /* Register rate control */
hw->rate_control_algorithm = "ath9k_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 ieee80211_if_init_conf *conf)
{ {
struct ath_softc *sc = hw->priv; 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 */ /* Support only vap for now */
@ -1119,13 +1115,22 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
__func__, __func__,
ic_opmode); ic_opmode);
error = ath_vap_attach(sc, 0, conf->vif, ic_opmode); /* Set the VAP opmode */
if (error) { avp->av_opmode = ic_opmode;
DPRINTF(sc, ATH_DBG_FATAL, avp->av_bslot = -1;
"%s: Unable to attach vap, error: %d\n",
__func__, error); if (ic_opmode == ATH9K_M_HOSTAP)
return error; 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) { if (conf->type == NL80211_IFTYPE_AP) {
/* TODO: is this a suitable place to start ANI for AP mode? */ /* 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 ieee80211_if_init_conf *conf)
{ {
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_vap *avp; struct ath_vap *avp = (void *)conf->vif->drv_priv;
int error;
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__); 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 #ifdef CONFIG_SLOW_ANT_DIV
ath_slow_ant_div_stop(&sc->sc_antdiv); ath_slow_ant_div_stop(&sc->sc_antdiv);
#endif #endif
/* Stop ANI */ /* Stop ANI */
del_timer_sync(&sc->sc_ani.timer); del_timer_sync(&sc->sc_ani.timer);
/* Update ratectrl */
ath_rate_newstate(sc, avp);
/* Reclaim beacon resources */ /* Reclaim beacon resources */
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { 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); 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; sc->sc_flags &= ~SC_OP_BEACONS;
error = ath_vap_detach(sc, 0); sc->sc_vaps[0] = NULL;
if (error) sc->sc_nvaps--;
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to detach vap, error: %d\n",
__func__, error);
} }
static int ath9k_config(struct ieee80211_hw *hw, u32 changed) 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_softc *sc = hw->priv;
struct ath_hal *ah = sc->sc_ah; struct ath_hal *ah = sc->sc_ah;
struct ath_vap *avp; struct ath_vap *avp = (void *)vif->drv_priv;
u32 rfilt = 0; u32 rfilt = 0;
int error, i; 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 /* TODO: Need to decide which hw opmode to use for multi-interface
* cases */ * cases */
if (vif->type == NL80211_IFTYPE_AP && if (vif->type == NL80211_IFTYPE_AP &&
@ -1317,7 +1298,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
} }
/* Check for WLAN_CAPABILITY_PRIVACY ? */ /* 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++) for (i = 0; i < IEEE80211_WEP_NKID; i++)
if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
ath9k_hw_keysetmac(sc->sc_ah, ath9k_hw_keysetmac(sc->sc_ah,
@ -1366,9 +1347,6 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
__func__, sc->rx_filter); __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, static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
enum sta_notify_cmd cmd, enum sta_notify_cmd cmd,
@ -1378,7 +1356,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
switch (cmd) { switch (cmd) {
case STA_NOTIFY_ADD: case STA_NOTIFY_ADD:
ath_node_attach(sc, sta, 0); ath_node_attach(sc, sta);
break; break;
case STA_NOTIFY_REMOVE: case STA_NOTIFY_REMOVE:
ath_node_detach(sc, sta); 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", DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
__func__, __func__,
bss_conf->assoc); bss_conf->assoc);
ath9k_bss_assoc_info(sc, bss_conf); ath9k_bss_assoc_info(sc, vif, bss_conf);
} }
} }

View File

@ -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) 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_softc *sc = priv;
struct ath_vap *avp = sc->sc_vaps[0]; struct ath_vap *avp;
struct ath_rate_node *rate_priv; struct ath_rate_node *rate_priv;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); 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); rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
if (!rate_priv) { if (!rate_priv) {
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,