[net80211] separate out node allocation and node initialisation.

This is a new, optional (for now!) method that drivers can use to separate
node allocation and node initialisation.  Right now they're the same, and
drivers that need to do node allocation via firmware commands need to sleep
and thus they need to defer node allocation into an internal taskqueue.

Right now they're just separate but not deferred.  Later on if I get the time
we'll start deferring the node and key related operations but that requires
making a bunch of other stuff (notably things that generate frames!) also
async/deferred.

Tested:

* RT3593, STA/DWDS mode
* AR9380, STA/AP modes
* QCA9880 (athp) - STA/AP modes
This commit is contained in:
Adrian Chadd 2020-06-13 22:20:02 +00:00
parent d60bdf8569
commit ea3d5fd9df
2 changed files with 39 additions and 1 deletions

View File

@ -80,6 +80,7 @@ static int ieee80211_sta_join1(struct ieee80211_node *);
static struct ieee80211_node *node_alloc(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN]);
static int node_init(struct ieee80211_node *);
static void node_cleanup(struct ieee80211_node *);
static void node_free(struct ieee80211_node *);
static void node_age(struct ieee80211_node *);
@ -116,6 +117,7 @@ ieee80211_node_attach(struct ieee80211com *ic)
ieee80211_node_timeout, ic);
ic->ic_node_alloc = node_alloc;
ic->ic_node_init = node_init;
ic->ic_node_free = node_free;
ic->ic_node_cleanup = node_cleanup;
ic->ic_node_age = node_age;
@ -1074,6 +1076,12 @@ node_alloc(struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN])
return ni;
}
static int
node_init(struct ieee80211_node *ni)
{
return 0;
}
/*
* Initialize an ie blob with the specified data. If previous
* data exists re-use the data block. As a side effect we clear
@ -1414,6 +1422,15 @@ ieee80211_alloc_node(struct ieee80211_node_table *nt,
ni->ni_ic = ic;
IEEE80211_NODE_UNLOCK(nt);
/* handle failure; free node state */
if (ic->ic_node_init(ni) != 0) {
vap->iv_stats.is_rx_nodealloc++;
ieee80211_psq_cleanup(&ni->ni_psq);
ieee80211_ratectl_node_deinit(ni);
_ieee80211_free_node(ni);
return NULL;
}
IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni,
"%s: inact_reload %u", __func__, ni->ni_inact_reload);
@ -1456,6 +1473,16 @@ ieee80211_tmp_node(struct ieee80211vap *vap,
ieee80211_psq_init(&ni->ni_psq, "unknown");
ieee80211_ratectl_node_init(ni);
/* handle failure; free node state */
if (ic->ic_node_init(ni) != 0) {
vap->iv_stats.is_rx_nodealloc++;
ieee80211_psq_cleanup(&ni->ni_psq);
ieee80211_ratectl_node_deinit(ni);
_ieee80211_free_node(ni);
return NULL;
}
} else {
/* XXX msg */
vap->iv_stats.is_rx_nodealloc++;

View File

@ -310,11 +310,22 @@ struct ieee80211com {
/* TDMA update notification */
void (*ic_tdma_update)(struct ieee80211_node *,
const struct ieee80211_tdma_param *, int);
/* node state management */
/* Node state management */
/* Allocate a new node */
struct ieee80211_node* (*ic_node_alloc)(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN]);
/* Driver node initialisation after net80211 setup */
int (*ic_node_init)(struct ieee80211_node *);
/* Driver node deallocation */
void (*ic_node_free)(struct ieee80211_node *);
/* Driver node state cleanup before deallocation */
void (*ic_node_cleanup)(struct ieee80211_node *);
void (*ic_node_age)(struct ieee80211_node *);
void (*ic_node_drain)(struct ieee80211_node *);
int8_t (*ic_node_getrssi)(const struct ieee80211_node*);