Skip to content

Commit

Permalink
mac80211: share STA information with driver
Browse files Browse the repository at this point in the history
This patch changes mac80211 to share some more data about
stations with drivers. Should help iwlwifi and ath9k when
 they get around to updating, and might also help with
implementing rate control algorithms without internals.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Sep 15, 2008
1 parent 8aa21e6 commit 17741cd
Show file tree
Hide file tree
Showing 23 changed files with 189 additions and 127 deletions.
30 changes: 14 additions & 16 deletions drivers/net/wireless/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1405,27 +1405,26 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
const u8 *addr)
struct ieee80211_sta *sta)
{
struct ath_softc *sc = hw->priv;
struct ath_node *an;
unsigned long flags;
DECLARE_MAC_BUF(mac);

spin_lock_irqsave(&sc->node_lock, flags);
an = ath_node_find(sc, (u8 *) addr);
an = ath_node_find(sc, sta->addr);
spin_unlock_irqrestore(&sc->node_lock, flags);

switch (cmd) {
case STA_NOTIFY_ADD:
spin_lock_irqsave(&sc->node_lock, flags);
if (!an) {
ath_node_attach(sc, (u8 *)addr, 0);
ath_node_attach(sc, sta->addr, 0);
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
__func__,
print_mac(mac, addr));
__func__, print_mac(mac, sta->addr));
} else {
ath_node_get(sc, (u8 *)addr);
ath_node_get(sc, sta->addr);
}
spin_unlock_irqrestore(&sc->node_lock, flags);
break;
Expand All @@ -1438,7 +1437,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
__func__,
print_mac(mac, addr));
print_mac(mac, sta->addr));
}
break;
default:
Expand Down Expand Up @@ -1581,45 +1580,44 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw)

static int ath9k_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr,
u16 tid,
u16 *ssn)
struct ieee80211_sta *sta,
u16 tid, u16 *ssn)
{
struct ath_softc *sc = hw->priv;
int ret = 0;

switch (action) {
case IEEE80211_AMPDU_RX_START:
ret = ath_rx_aggr_start(sc, addr, tid, ssn);
ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to start RX aggregation\n",
__func__);
break;
case IEEE80211_AMPDU_RX_STOP:
ret = ath_rx_aggr_stop(sc, addr, tid);
ret = ath_rx_aggr_stop(sc, sta->addr, tid);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to stop RX aggregation\n",
__func__);
break;
case IEEE80211_AMPDU_TX_START:
ret = ath_tx_aggr_start(sc, addr, tid, ssn);
ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to start TX aggregation\n",
__func__);
else
ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
ret = ath_tx_aggr_stop(sc, addr, tid);
ret = ath_tx_aggr_stop(sc, sta->addr, tid);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to stop TX aggregation\n",
__func__);

ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
default:
DPRINTF(sc, ATH_DBG_FATAL,
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4234,7 +4234,8 @@ static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
return err;
}

static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, bool set)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;
Expand All @@ -4249,7 +4250,7 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
static void b43_op_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
const u8 *addr)
struct ieee80211_sta *sta)
{
struct b43_wl *wl = hw_to_b43_wl(hw);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/b43legacy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3403,7 +3403,7 @@ static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
}

static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
int aid, int set)
struct ieee80211_sta *sta, bool set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
Expand Down
12 changes: 6 additions & 6 deletions drivers/net/wireless/iwlwifi/iwl-agn-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
if (state == HT_AGG_STATE_IDLE &&
rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
print_mac(mac, sta->addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
print_mac(mac, sta->sta.addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid);
}
}

Expand Down Expand Up @@ -2244,17 +2244,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,

lq_sta->ibss_sta_added = 0;
if (priv->iw_mode == NL80211_IFTYPE_AP) {
u8 sta_id = iwl_find_station(priv, sta->addr);
u8 sta_id = iwl_find_station(priv, sta->sta.addr);
DECLARE_MAC_BUF(mac);

/* for IBSS the call are from tasklet */
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->addr));
print_mac(mac, sta->sta.addr));

if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->addr));
sta_id = iwl_add_station_flags(priv, sta->addr,
print_mac(mac, sta->sta.addr));
sta_id = iwl_add_station_flags(priv, sta->sta.addr,
0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
Expand Down
12 changes: 6 additions & 6 deletions drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3413,30 +3413,30 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,

static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn)
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
struct iwl_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);

IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
print_mac(mac, addr), tid);
print_mac(mac, sta->addr), tid);

if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;

switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
return iwl_rx_agg_start(priv, addr, tid, *ssn);
return iwl_rx_agg_start(priv, sta->addr, tid, *ssn);
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT("stop Rx\n");
return iwl_rx_agg_stop(priv, addr, tid);
return iwl_rx_agg_stop(priv, sta->addr, tid);
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT("start Tx\n");
return iwl_tx_agg_start(priv, addr, tid, ssn);
return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT("stop Tx\n");
return iwl_tx_agg_stop(priv, addr, tid);
return iwl_tx_agg_stop(priv, sta->addr, tid);
default:
IWL_DEBUG_HT("unknown\n");
return -EINVAL;
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/mac80211_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,

static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd, const u8 *addr)
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
hwsim_check_magic(vif);
}
Expand Down
53 changes: 48 additions & 5 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ enum mac80211_tx_control_flags {
* (2) driver internal use (if applicable)
* (3) TX status information - driver tells mac80211 what happened
*
* The TX control's sta pointer is only valid during the ->tx call,
* it may be NULL.
*
* @flags: transmit info flags, defined above
* @band: TBD
* @tx_rate_idx: TBD
Expand Down Expand Up @@ -329,8 +332,8 @@ struct ieee80211_tx_info {
struct {
struct ieee80211_vif *vif;
struct ieee80211_key_conf *hw_key;
struct ieee80211_sta *sta;
unsigned long jiffies;
u16 aid;
s8 rts_cts_rate_idx, alt_retry_rate_idx;
u8 retry_limit;
u8 icv_len;
Expand Down Expand Up @@ -651,6 +654,29 @@ enum set_key_cmd {
SET_KEY, DISABLE_KEY,
};

/**
* struct ieee80211_sta - station table entry
*
* A station table entry represents a station we are possibly
* communicating with. Since stations are RCU-managed in
* mac80211, any ieee80211_sta pointer you get access to must
* either be protected by rcu_read_lock() explicitly or implicitly,
* or you must take good care to not use such a pointer after a
* call to your sta_notify callback that removed it.
*
* @addr: MAC address
* @aid: AID we assigned to the station if we're an AP
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
*/
struct ieee80211_sta {
u8 addr[ETH_ALEN];
u16 aid;

/* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
};

/**
* enum sta_notify_cmd - sta notify command
*
Expand Down Expand Up @@ -795,6 +821,8 @@ enum ieee80211_hw_flags {
*
* @vif_data_size: size (in bytes) of the drv_priv data area
* within &struct ieee80211_vif.
* @sta_data_size: size (in bytes) of the drv_priv data area
* within &struct ieee80211_sta.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
Expand All @@ -806,6 +834,7 @@ struct ieee80211_hw {
unsigned int extra_tx_headroom;
int channel_change_time;
int vif_data_size;
int sta_data_size;
u16 queues;
u16 ampdu_queues;
u16 max_listen_interval;
Expand Down Expand Up @@ -1089,7 +1118,7 @@ enum ieee80211_ampdu_mlme_action {
* This callback must be implemented and atomic.
*
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
* must be set or cleared for a given AID. Must be atomic.
* must be set or cleared for a given STA. Must be atomic.
*
* @set_key: See the section "Hardware crypto acceleration"
* This callback can sleep, and is only called between add_interface
Expand Down Expand Up @@ -1175,7 +1204,8 @@ struct ieee80211_ops {
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list);
int (*set_tim)(struct ieee80211_hw *hw, int aid, int set);
int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
bool set);
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_address, const u8 *address,
struct ieee80211_key_conf *key);
Expand All @@ -1192,7 +1222,7 @@ struct ieee80211_ops {
int (*set_retry_limit)(struct ieee80211_hw *hw,
u32 short_retry, u32 long_retr);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, const u8 *addr);
enum sta_notify_cmd, struct ieee80211_sta *sta);
int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
int (*get_tx_stats)(struct ieee80211_hw *hw,
Expand All @@ -1202,7 +1232,7 @@ struct ieee80211_ops {
int (*tx_last_beacon)(struct ieee80211_hw *hw);
int (*ampdu_action)(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn);
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
};

/**
Expand Down Expand Up @@ -1752,4 +1782,17 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
*/
void ieee80211_notify_mac(struct ieee80211_hw *hw,
enum ieee80211_notification_types notif_type);

/**
* ieee80211_find_sta - find a station
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @addr: station's address
*
* This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well.
*/
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
const u8 *addr);

#endif /* MAC80211_H */
12 changes: 6 additions & 6 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
sta = sta_info_get_by_idx(local, idx, dev);
if (sta) {
ret = 0;
memcpy(mac, sta->addr, ETH_ALEN);
memcpy(mac, sta->sta.addr, ETH_ALEN);
sta_set_sinfo(sta, sinfo);
}

Expand Down Expand Up @@ -593,7 +593,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
* Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */

memset(msg->da, 0xff, ETH_ALEN);
memcpy(msg->sa, sta->addr, ETH_ALEN);
memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
msg->len = htons(6);
msg->dsap = 0;
msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
Expand Down Expand Up @@ -648,9 +648,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,
*/

if (params->aid) {
sta->aid = params->aid;
if (sta->aid > IEEE80211_MAX_AID)
sta->aid = 0; /* XXX: should this be an error? */
sta->sta.aid = params->aid;
if (sta->sta.aid > IEEE80211_MAX_AID)
sta->sta.aid = 0; /* XXX: should this be an error? */
}

if (params->listen_interval >= 0)
Expand Down Expand Up @@ -919,7 +919,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
struct mpath_info *pinfo)
{
if (mpath->next_hop)
memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
else
memset(next_hop, 0, ETH_ALEN);

Expand Down
3 changes: 2 additions & 1 deletion net/mac80211/debugfs_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
rcu_read_lock();
sta = rcu_dereference(key->sta);
if (sta)
sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
sprintf(buf, "../../stations/%s",
print_mac(mac, sta->sta.addr));
rcu_read_unlock();

/* using sta as a boolean is fine outside RCU lock */
Expand Down
Loading

0 comments on commit 17741cd

Please sign in to comment.