diff options
Diffstat (limited to 'package/madwifi/patches/416-wprobe.patch')
-rw-r--r-- | package/madwifi/patches/416-wprobe.patch | 549 |
1 files changed, 0 insertions, 549 deletions
diff --git a/package/madwifi/patches/416-wprobe.patch b/package/madwifi/patches/416-wprobe.patch deleted file mode 100644 index 0b378d7e26..0000000000 --- a/package/madwifi/patches/416-wprobe.patch +++ /dev/null @@ -1,549 +0,0 @@ ---- /dev/null -+++ b/ath/ath_wprobe.c -@@ -0,0 +1,433 @@ -+#include <net80211/ieee80211_node.h> -+#include <linux/wprobe.h> -+ -+atomic_t cleanup_tasks = ATOMIC_INIT(0); -+ -+enum wp_node_val { -+ WP_NODE_RSSI, -+ WP_NODE_SIGNAL, -+ WP_NODE_RX_RATE, -+ WP_NODE_TX_RATE, -+ WP_NODE_RETRANSMIT_200, -+ WP_NODE_RETRANSMIT_400, -+ WP_NODE_RETRANSMIT_800, -+ WP_NODE_RETRANSMIT_1600, -+}; -+ -+enum wp_global_val { -+ WP_GLOBAL_NOISE, -+ WP_GLOBAL_PHY_BUSY, -+ WP_GLOBAL_PHY_RX, -+ WP_GLOBAL_PHY_TX, -+ WP_GLOBAL_FRAMES, -+ WP_GLOBAL_PROBEREQ, -+}; -+ -+static struct wprobe_item ath_wprobe_globals[] = { -+ [WP_GLOBAL_NOISE] = { -+ .name = "noise", -+ .type = WPROBE_VAL_S16, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_GLOBAL_PHY_BUSY] = { -+ .name = "phy_busy", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_GLOBAL_PHY_RX] = { -+ .name = "phy_rx", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_GLOBAL_PHY_TX] = { -+ .name = "phy_tx", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_GLOBAL_FRAMES] = { -+ .name = "frames", -+ .type = WPROBE_VAL_U32, -+ }, -+ [WP_GLOBAL_PROBEREQ] = { -+ .name = "probereq", -+ .type = WPROBE_VAL_U32, -+ }, -+}; -+ -+static struct wprobe_item ath_wprobe_link[] = { -+ [WP_NODE_RSSI] = { -+ .name = "rssi", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_SIGNAL] = { -+ .name = "signal", -+ .type = WPROBE_VAL_S16, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_RX_RATE] = { -+ .name = "rx_rate", -+ .type = WPROBE_VAL_U16, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_TX_RATE] = { -+ .name = "tx_rate", -+ .type = WPROBE_VAL_U16, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_RETRANSMIT_200] = { -+ .name = "retransmit_200", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_RETRANSMIT_400] = { -+ .name = "retransmit_400", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_RETRANSMIT_800] = { -+ .name = "retransmit_800", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+ [WP_NODE_RETRANSMIT_1600] = { -+ .name = "retransmit_1600", -+ .type = WPROBE_VAL_U8, -+ .flags = WPROBE_F_KEEPSTAT -+ }, -+}; -+ -+#define AR5K_MIBC 0x0040 -+#define AR5K_MIBC_FREEZE (1 << 1) -+#define AR5K_TXFC 0x80ec -+#define AR5K_RXFC 0x80f0 -+#define AR5K_RXCLEAR 0x80f4 -+#define AR5K_CYCLES 0x80f8 -+ -+#define READ_CLR(_ah, _reg) \ -+ ({ u32 __val = OS_REG_READ(_ah, _reg); OS_REG_WRITE(_ah, _reg, 0); __val; }) -+ -+static bool -+wprobe_disabled(void) -+{ -+ return (!wprobe_add_iface || IS_ERR(wprobe_add_iface)); -+} -+ -+static int -+ath_wprobe_sync(struct wprobe_iface *dev, struct wprobe_link *l, struct wprobe_value *val, bool measure) -+{ -+ struct ath_vap *avp = container_of(dev, struct ath_vap, av_wpif); -+ struct ieee80211vap *vap = &avp->av_vap; -+ struct ieee80211com *ic = vap->iv_ic; -+ struct ath_softc *sc = ic->ic_dev->priv; -+ struct ath_hal *ah = sc->sc_ah; -+ u32 cc, busy, rx, tx; -+ s16 noise; -+ -+ if (l) -+ goto out; -+ -+ OS_REG_WRITE(ah, AR5K_MIBC, AR5K_MIBC_FREEZE); -+ cc = READ_CLR(ah, AR5K_CYCLES); -+ busy = READ_CLR(ah, AR5K_RXCLEAR); -+ rx = READ_CLR(ah, AR5K_RXFC); -+ tx = READ_CLR(ah, AR5K_TXFC); -+ OS_REG_WRITE(ah, AR5K_MIBC, 0); -+ noise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan)); -+ ic->ic_channoise = noise; -+ -+ WPROBE_FILL_BEGIN(val, ath_wprobe_globals); -+ if (cc & 0xf0000000) { -+ /* scale down if the counters are near max */ -+ cc >>= 8; -+ busy >>= 8; -+ rx >>= 8; -+ tx >>= 8; -+ } -+ if (ah->ah_macType < 5212) -+ goto phy_skip; -+ if (!cc) -+ goto phy_skip; -+ if (busy > cc) -+ goto phy_skip; -+ if (rx > cc) -+ goto phy_skip; -+ if (tx > cc) -+ goto phy_skip; -+ busy = (busy * 100) / cc; -+ rx = (rx * 100) / cc; -+ tx = (tx * 100) / cc; -+ WPROBE_SET(WP_GLOBAL_PHY_BUSY, U8, busy); -+ WPROBE_SET(WP_GLOBAL_PHY_RX, U8, rx); -+ WPROBE_SET(WP_GLOBAL_PHY_TX, U8, tx); -+ WPROBE_SET(WP_GLOBAL_FRAMES, U32, avp->av_rxframes); -+ WPROBE_SET(WP_GLOBAL_PROBEREQ, U32, avp->av_rxprobereq); -+ -+phy_skip: -+ WPROBE_SET(WP_GLOBAL_NOISE, S16, noise); -+ WPROBE_FILL_END(); -+ -+out: -+ return 0; -+} -+ -+#undef AR5K_TXFC -+#undef AR5K_RXFC -+#undef AR5K_RXCLEAR -+#undef AR5K_CYCLES -+#undef AR5K_MIBC -+#undef AR5K_MIBC_FREEZE -+#undef READ_CLR -+ -+static const struct wprobe_iface ath_wprobe_dev = { -+ .link_items = ath_wprobe_link, -+ .n_link_items = ARRAY_SIZE(ath_wprobe_link), -+ .global_items = ath_wprobe_globals, -+ .n_global_items = ARRAY_SIZE(ath_wprobe_globals), -+ .sync_data = ath_wprobe_sync, -+}; -+ -+static int -+ath_lookup_rateval(struct ieee80211_node *ni, int rate) -+{ -+ struct ieee80211vap *vap = ni->ni_vap; -+ struct ieee80211com *ic = vap->iv_ic; -+ struct ath_softc *sc = ic->ic_dev->priv; -+ const HAL_RATE_TABLE *rt = sc->sc_currates; -+ -+ if ((!rt) || (rate < 0) || (rate >= ARRAY_SIZE(sc->sc_hwmap))) -+ return -1; -+ -+ rate = sc->sc_hwmap[rate].ieeerate; -+ rate = sc->sc_rixmap[rate & IEEE80211_RATE_VAL]; -+ if ((rate < 0) || (rate >= rt->rateCount)) -+ return -1; -+ -+ return rt->info[rate].rateKbps; -+} -+ -+static void -+ath_wprobe_report_rx(struct ieee80211vap *vap, struct ath_rx_status *rs, struct sk_buff *skb) -+{ -+ const struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; -+ struct wprobe_wlan_hdr hdr; -+ struct ath_vap *avp; -+ int hdrsize; -+ -+ if (wprobe_disabled()) -+ return; -+ -+ avp = ATH_VAP(vap); -+ avp->av_rxframes++; -+ if (wh->i_fc[0] == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ)) -+ avp->av_rxprobereq++; -+ -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.len = skb->len; -+ hdr.snr = rs->rs_rssi; -+ hdr.type = WPROBE_PKT_RX; -+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) -+ hdrsize = sizeof(struct ieee80211_ctlframe_addr2); -+ else -+ hdrsize = ieee80211_hdrsize(skb->data); -+ wprobe_add_frame(&avp->av_wpif, &hdr, skb->data, hdrsize + 0x42); -+} -+ -+ -+static void -+ath_node_sample_rx(struct ieee80211_node *ni, struct ath_rx_status *rs) -+{ -+ struct ath_node *an = ATH_NODE(ni); -+ struct ieee80211vap *vap = ni->ni_vap; -+ struct ieee80211com *ic = vap->iv_ic; -+ struct wprobe_link *l = &an->an_wplink; -+ struct wprobe_value *v = l->val; -+ unsigned long flags; -+ int rate; -+ -+ if (wprobe_disabled() || !an->an_wplink_active || !l->val) -+ return; -+ -+ rate = ath_lookup_rateval(ni, rs->rs_rate); -+ -+ spin_lock_irqsave(&l->iface->lock, flags); -+ WPROBE_FILL_BEGIN(v, ath_wprobe_link); -+ WPROBE_SET(WP_NODE_RSSI, U8, rs->rs_rssi); -+ WPROBE_SET(WP_NODE_SIGNAL, S16, ic->ic_channoise + rs->rs_rssi); -+ if ((rate > 0) && (rate <= 600000)) -+ WPROBE_SET(WP_NODE_RX_RATE, U16, rate); -+ WPROBE_FILL_END(); -+ wprobe_update_stats(l->iface, l); -+ spin_unlock_irqrestore(&l->iface->lock, flags); -+} -+ -+static void -+ath_wprobe_report_tx(struct ieee80211vap *vap, struct ath_tx_status *ts, struct sk_buff *skb) -+{ -+ const struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; -+ struct wprobe_wlan_hdr hdr; -+ struct ath_vap *avp; -+ int hdrsize; -+ -+ if (wprobe_disabled()) -+ return; -+ -+ avp = ATH_VAP(vap); -+ -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.len = skb->len; -+ hdr.snr = ts->ts_rssi; -+ hdr.type = WPROBE_PKT_TX; -+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) -+ hdrsize = sizeof(struct ieee80211_ctlframe_addr2); -+ else -+ hdrsize = ieee80211_hdrsize(skb->data); -+ wprobe_add_frame(&avp->av_wpif, &hdr, skb->data, hdrsize + 0x42); -+} -+ -+ -+ -+static void -+ath_node_sample_tx(struct ieee80211_node *ni, struct ath_tx_status *ts, struct sk_buff *skb) -+{ -+ struct ath_node *an = ATH_NODE(ni); -+ struct ieee80211vap *vap = ni->ni_vap; -+ struct ieee80211com *ic = vap->iv_ic; -+ struct wprobe_link *l = &an->an_wplink; -+ struct wprobe_value *v = l->val; -+ unsigned long flags; -+ int rate, rexmit_counter; -+ int len = skb->len; -+ -+ if (wprobe_disabled() || !an->an_wplink_active || !l->val) -+ return; -+ -+ ath_wprobe_report_tx(vap, ts, skb); -+ rate = ath_lookup_rateval(ni, ts->ts_rate); -+ -+ spin_lock_irqsave(&l->iface->lock, flags); -+ WPROBE_FILL_BEGIN(v, ath_wprobe_link); -+ WPROBE_SET(WP_NODE_RSSI, U8, ts->ts_rssi); -+ WPROBE_SET(WP_NODE_SIGNAL, S16, ic->ic_channoise + ts->ts_rssi); -+ -+ if (len <= 200) -+ rexmit_counter = WP_NODE_RETRANSMIT_200; -+ else if (len <= 400) -+ rexmit_counter = WP_NODE_RETRANSMIT_400; -+ else if (len <= 800) -+ rexmit_counter = WP_NODE_RETRANSMIT_800; -+ else -+ rexmit_counter = WP_NODE_RETRANSMIT_1600; -+ WPROBE_SET(rexmit_counter, U8, ts->ts_longretry); -+ -+ if ((rate > 0) && (rate <= 600000)) -+ WPROBE_SET(WP_NODE_TX_RATE, U16, rate); -+ WPROBE_FILL_END(); -+ wprobe_update_stats(l->iface, l); -+ spin_unlock_irqrestore(&l->iface->lock, flags); -+} -+ -+static void -+ath_wprobe_node_join(struct ieee80211vap *vap, struct ieee80211_node *ni) -+{ -+ struct wprobe_iface *dev; -+ struct wprobe_link *l; -+ struct ath_vap *avp; -+ struct ath_node *an = ATH_NODE(ni); -+ -+ if (wprobe_disabled() || an->an_wplink_active) -+ return; -+ -+ avp = ATH_VAP(vap); -+ dev = &avp->av_wpif; -+ l = &an->an_wplink; -+ -+ ieee80211_ref_node(ni); -+ wprobe_add_link(dev, l, ni->ni_macaddr); -+ an->an_wplink_active = 1; -+} -+ -+static void -+ath_wprobe_do_node_leave(struct work_struct *work) -+{ -+ struct ath_node *an = container_of(work, struct ath_node, an_destroy); -+ struct ieee80211_node *ni = &an->an_node; -+ struct ieee80211vap *vap = ni->ni_vap; -+ struct wprobe_iface *dev; -+ struct wprobe_link *l; -+ struct ath_vap *avp; -+ -+ avp = ATH_VAP(vap); -+ dev = &avp->av_wpif; -+ l = &an->an_wplink; -+ -+ wprobe_remove_link(dev, l); -+ ieee80211_unref_node(&ni); -+ atomic_dec(&cleanup_tasks); -+} -+ -+static void -+ath_wprobe_node_leave(struct ieee80211vap *vap, struct ieee80211_node *ni) -+{ -+ struct ath_node *an = ATH_NODE(ni); -+ -+ if (wprobe_disabled() || !an->an_wplink_active) -+ return; -+ -+ atomic_inc(&cleanup_tasks); -+ an->an_wplink_active = 0; -+ IEEE80211_INIT_WORK(&an->an_destroy, ath_wprobe_do_node_leave); -+ schedule_work(&an->an_destroy); -+} -+ -+static void -+ath_init_wprobe_dev(struct ath_vap *avp) -+{ -+ struct ieee80211vap *vap = &avp->av_vap; -+ struct wprobe_iface *dev = &avp->av_wpif; -+ -+ if (wprobe_disabled() || (vap->iv_opmode == IEEE80211_M_WDS)) -+ return; -+ -+ memcpy(dev, &ath_wprobe_dev, sizeof(struct wprobe_iface)); -+ dev->addr = vap->iv_myaddr; -+ dev->name = vap->iv_dev->name; -+ wprobe_add_iface(dev); -+} -+ -+static void -+ath_remove_wprobe_dev(struct ath_vap *avp) -+{ -+ struct ieee80211vap *vap = &avp->av_vap; -+ struct ieee80211com *ic = vap->iv_ic; -+ struct ieee80211_node *ni; -+ struct wprobe_iface *dev = &avp->av_wpif; -+ struct wprobe_link *l; -+ struct ath_node *an; -+ unsigned long flags; -+ -+ if (wprobe_disabled() || (vap->iv_opmode == IEEE80211_M_WDS)) -+ return; -+ -+restart: -+ rcu_read_lock(); -+ list_for_each_entry_rcu(l, &dev->links, list) { -+ an = container_of(l, struct ath_node, an_wplink); -+ -+ if (!an->an_wplink_active) -+ continue; -+ -+ ni = &an->an_node; -+ ath_wprobe_node_leave(vap, ni); -+ rcu_read_unlock(); -+ goto restart; -+ } -+ rcu_read_unlock(); -+ -+ /* wait for the cleanup tasks to finish */ -+ while (atomic_read(&cleanup_tasks) != 0) { -+ schedule(); -+ } -+ -+ wprobe_remove_iface(dev); -+} ---- a/ath/if_ath.c -+++ b/ath/if_ath.c -@@ -400,6 +400,7 @@ static int countrycode = -1; - static int maxvaps = -1; - static int outdoor = -1; - static int xchanmode = -1; -+#include "ath_wprobe.c" - static int beacon_cal = 1; - - static const struct ath_hw_detect generic_hw_info = { -@@ -1525,6 +1526,7 @@ ath_vap_create(struct ieee80211com *ic, - ath_hal_intrset(ah, sc->sc_imask); - } - -+ ath_init_wprobe_dev(avp); - return vap; - } - -@@ -1606,6 +1608,7 @@ ath_vap_delete(struct ieee80211vap *vap) - decrease = 0; - - ieee80211_vap_detach(vap); -+ ath_remove_wprobe_dev(ATH_VAP(vap)); - /* NB: memory is reclaimed through dev->destructor callback */ - if (decrease) - sc->sc_nvaps--; -@@ -5940,6 +5943,7 @@ ath_node_cleanup(struct ieee80211_node * - /* Clean up node-specific rate things - this currently appears to - * always be a no-op */ - sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni)); -+ ath_wprobe_node_leave(ni->ni_vap, ni); - - ATH_NODE_UAPSD_LOCK_IRQ(an); - #ifdef IEEE80211_DEBUG_REFCNT -@@ -7010,6 +7014,8 @@ drop_micfail: - goto lookup_slowpath; - } - ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi); -+ ath_node_sample_rx(ni, rs); -+ ath_wprobe_report_rx(ni->ni_vap, rs, skb); - type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf); - ieee80211_unref_node(&ni); - } else { -@@ -7024,15 +7030,21 @@ lookup_slowpath: - else - vap = ieee80211_find_rxvap(ic, wh->i_addr1); - -- if (vap) -+ if (vap) { -+ ath_wprobe_report_rx(vap, rs, skb); - ni = ieee80211_find_rxnode(ic, vap, wh); -- else -+ } else { -+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { -+ ath_wprobe_report_rx(vap, rs, skb); -+ } - ni = NULL; -+ } - - if (ni != NULL) { - ieee80211_keyix_t keyix; - - ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi); -+ ath_node_sample_rx(ni, rs); - type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf); - /* - * If the station has a key cache slot assigned -@@ -8612,6 +8624,7 @@ ath_tx_processq(struct ath_softc *sc, st - sc->sc_stats.ast_tx_rssi = ts->ts_rssi; - ATH_RSSI_LPF(an->an_halstats.ns_avgtxrssi, - ts->ts_rssi); -+ ath_node_sample_tx(&an->an_node, ts, bf->bf_skb); - if (bf->bf_skb->priority == WME_AC_VO || - bf->bf_skb->priority == WME_AC_VI) - ni->ni_ic->ic_wme.wme_hipri_traffic++; -@@ -10111,6 +10124,7 @@ ath_newassoc(struct ieee80211_node *ni, - struct ath_softc *sc = ic->ic_dev->priv; - - sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew); -+ ath_wprobe_node_join(ni->ni_vap, ni); - - /* are we supporting compression? */ - if (!(vap->iv_ath_cap & ni->ni_ath_flags & IEEE80211_NODE_COMP)) ---- a/ath/if_athvar.h -+++ b/ath/if_athvar.h -@@ -46,6 +46,7 @@ - #include "ah_desc.h" - #include "ah_os.h" - #include "if_athioctl.h" -+#include <linux/wprobe.h> - #include "net80211/ieee80211.h" /* XXX for WME_NUM_AC */ - #include <asm/io.h> - #include <linux/list.h> -@@ -352,6 +353,9 @@ typedef STAILQ_HEAD(, ath_buf) ath_bufhe - /* driver-specific node state */ - struct ath_node { - struct ieee80211_node an_node; /* base class */ -+ struct wprobe_link an_wplink; -+ uint8_t an_wplink_active; -+ struct work_struct an_destroy; - u_int16_t an_decomp_index; /* decompression mask index */ - u_int32_t an_avgrssi; /* average rssi over all rx frames */ - u_int8_t an_prevdatarix; /* rate ix of last data frame */ -@@ -521,6 +525,9 @@ struct ath_vap { - #else - unsigned int av_beacon_alloc; - #endif -+ struct wprobe_iface av_wpif; -+ u32 av_rxframes; -+ u32 av_rxprobereq; - }; - #define ATH_VAP(_v) ((struct ath_vap *)(_v)) - |