ieee80211_local *local
用途:
- contains information about the real hardware, and is created when the interface is first added. (Daniel Caps Mur, Linux Wi-Fi open source drivers-mac80211,ath9k/ath5k-, pp.1)
- each instance of these (hw is embedded into local) represents a wireless driver, ieee80211_hw is the part of the ieee80211_local that is visible to drivers, contains all operating information about a wireless device. (Johannes Berg, mac80211 overview)
- It only used inside the mac80211 layer: https://elixir.bootlin.com/linux/v4.19-rc2/ident/ieee80211_local
- ref: https://stackoverflow.com/questions/21544411/explanation-of-struct-ieee80211-local-in-linux-kernel
第一次出現在:
ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
調用 ieee80211_alloc_hw_nm()
出現。
allocaed 在:
在 allocate wiphy 時分配出來,可以從以下的圖解中看出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* Ensure 32-byte alignment of our private data and hw private data. * We use the wiphy priv data for both our ieee80211_local and for * the driver’s private data * * In memory it’ll be like this: * * +————————-+ * | struct wiphy | * +————————-+ * | struct ieee80211_local | * +————————-+ * | driver’s private data | * +————————-+ * */ priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; wiphy = wiphy_new_nm(&mac80211_config_ops, priv_size, requested_name); local = wiphy_priv(wiphy) // &wiphy->priv |
嵌套了:
1 2 3 4 |
// struct ieee80211_hw hw; local->hw.wiphy = wiphy; local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); // 這是 ath_softc local->ops = ops; |
struct ath_softc
用途:driver 中封裝與 mac80211 層溝通的結構,用途廣泛。
allocated 在:drivers/net/wireless/ath/ath9k/pci.c#L950, hw = ieee80211_alloc_hw(sizeof(sturct ath_softc)
, &ath9k_ops);
嵌套於:struct ieee80211_hw
-> void *priv
struct ath_node
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
struct ath_node { struct ath_softc *sc; struct ieee80211_sta *sta; /* station struct we’re part of */ struct ieee80211_vif *vif; /* interface with which we’re associated */ u16 maxampdu; u8 mpdudensity; s8 ps_key; bool sleeping; bool no_ps_filter; s64 airtime_deficit[IEEE80211_NUM_ACS]; u32 airtime_rx_start; #ifdef CONFIG_ATH9K_STATION_STATISTICS struct ath_rx_rate_stats rx_rate_stats; struct ath_airtime_stats airtime_stats; #endif u8 key_idx[4]; u32 ackto; struct list_head list; }; |
用途:每個 station 在 ath9k 中會以 struct ath_node
表示。
allocate 在:net/mac80211/sta_info.c#L312, sta = kzalloc(sizeof(*sta) + hw->sta_data_size
, gfp);
第一出現在 driver 中:ath9k/main.c#L1512, struct ath_node *an = (struct ath_node *) sta->drv_priv;
嵌套於:struct sta_info
->struct ieee80211_sta sta
->u8 drv_priv[0] __aligned(sizeof(void *))
code 追蹤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
// net/mac80211/sta_info.c struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, const u8 *addr, gfp_t gfp) { struct ieee80211_local *local = sdata->local; struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; int i; sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp); if (!sta) return NULL; ... // net/mac80211/driver-ops.c __must_check int drv_sta_state(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, struct sta_info *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { ... if (local->ops->sta_state) { ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, old_state, new_state); ... // drivers/net/wireless/ath/ath9k/main.c static int ath9k_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); int ret = 0; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { ret = ath9k_sta_add(hw, vif, sta); ath_dbg(common, CONFIG, “Add station: %pM\n”, sta->addr); ... // drivers/net/wireless/ath/ath9k/main.c static int ath9k_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_node *an = (struct ath_node *) sta->drv_priv; struct ieee80211_key_conf ps_key = { }; int key; ath_node_attach(sc, sta, vif); ... |
struct ath_atx_tid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
struct ath_atx_tid { struct list_head list; struct sk_buff_head retry_q; struct ath_node *an; struct ath_txq *txq; unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; u16 seq_start; u16 seq_next; u16 baw_size; u8 tidno; int baw_head; /* first un-acked tx buffer */ int baw_tail; /* next unused tx buffer slot */ s8 bar_index; bool active; bool clear_ps_filter; bool has_queued; }; |
用途:於 driver 中描述 per station per tid tx queue 的結構。
allocated 在:net/mac80211/sta_info.c#L367:sta_info_alloc,
1 2 |
int size = sizeof(struct txq_info) + ALIGN(hw->txq_data_size, sizeof(void *)); txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); |
初始化在:drivers/net/wireless/ath/ath9k/xmit.c#L2884,將 ath_node 中所有的 tx queue 的 tid 都初始化一遍:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) { struct ath_atx_tid *tid; int tidno, acno; for (acno = 0; acno < IEEE80211_NUM_ACS; acno++) an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM; for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { tid = ath_node_to_tid(an, tidno); tid->an = an; tid->tidno = tidno; tid->seq_start = tid->seq_next = 0; tid->baw_size = WME_MAX_BA; tid->baw_head = tid->baw_tail = 0; tid->active = false; tid->clear_ps_filter = true; tid->has_queued = false; __skb_queue_head_init(&tid->retry_q); INIT_LIST_HEAD(&tid->list); acno = TID_TO_WME_AC(tidno); tid->txq = sc->tx.txq_map[acno]; if (!an->sta) break; /* just one multicast ath_atx_tid */ } } |
嵌套於:struct txq_info
-> struct ieee80211_txq txq
-> u8 drv_priv[0] __aligned(sizeof(void *));
struct ath_txq
用途:用來描述 ath driver 內 txq 的結構,與 ath_atx_tid 的差別是,這邊是封包存放的地方。
allocated 在:drivers/net/wireless/ath/ath9k/pci.c#L950, hw = ieee80211_alloc_hw(sizeof(sturct ath_softc)
, &ath9k_ops);
初始化在:
- ath9k_init_queues, drivers/net/wireless/ath/ath9k/init.c#L417, sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
- drivers/net/wireless/ath/ath9k/xmit.c#L1809
- drivers/net/wireless/ath/ath9k/xmit.c#L2905, tid->txq = sc->tx.txq_map[acno];
嵌套在:
struct ath_softc
->struct ath_tx tx
->struct ath_txq *txq_map[IEEE80211_NUM_ACSS]
(4 queues for difference ACs data, mapping to txq[ATH9K_NUM_TX_QUEUES])struct ath_softc
->struct ath_tx tx
->struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
(10 hw queues, including ATH9K_TX_QUEUE_CAB/UAPSD/DATA…etc)struct txq_info
->struct ieee80211_txq txq
->u8 drv_priv[0] (ath_atx_tid)
->struct ath_txq txq
struct ath_chanctx
用途:用於處理 channel context 的結構,用來支援 wireless multi-channel operation,預設沒有啟用該功能
allocated 在:drivers/net/wireless/ath/ath9k/pci.c#L950, hw = ieee80211_alloc_hw(sizeof(sturct ath_softc)
, &ath9k_ops);
初始化在:
- drivers/net/wireless/ath/ath9k/init.c#686, sc->cur_chan = &sc->chanctx[0];
- drivers/net/wireless/ath/ath9k/init.c#775, ath_chanctx_init(sc);
嵌套於:struct ath_softc
-> struct ath_chanctx chatctx[ATH9K_NUM_CHANCTX]
struct ath_hw
用途:於 driver 中封裝 ieee80211_hw 的結構,同時 common 也封裝在其中
allocated 在:drivers/net/wireless/ath/ath9k/init.c#L660, ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL);
初始化在:drivers/net/wireless/ath/ath9k/init.c#L660
嵌套於:struct ath_softc
-> struct ath_hw *sc_ah
struct ath_common
用途:多用於 debug message 使用,偶爾會使用其中的一些參數。ath 系列共用結構。
allocated 在:drivers/net/wireless/ath/ath9k/init.c#L660, ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL);
初始化在:drivers/net/wireless/ath/ath9k/init.c#L675
嵌套於:struct ath_softc
-> struct ath_hw *sc_ah
-> struct ath_common common
Leave a Reply