implement support for wprobe in madwifi
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@15051 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
fc05d24bf7
commit
bf2f58a6ec
|
@ -39,6 +39,8 @@ else
|
||||||
PATCH_DIR=./patches
|
PATCH_DIR=./patches
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
PKG_BUILD_DEPENDS:=wprobe
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
ifneq ($(CONFIG_TARGET_atheros),)
|
ifneq ($(CONFIG_TARGET_atheros),)
|
||||||
|
@ -168,6 +170,16 @@ define KernelPackage/madwifi/config
|
||||||
source "$(SOURCE)/Config.in"
|
source "$(SOURCE)/Config.in"
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
MADWIFI_INC = \
|
||||||
|
-I$(PKG_BUILD_DIR) \
|
||||||
|
-I$(PKG_BUILD_DIR)/include \
|
||||||
|
-I$(PKG_BUILD_DIR)/hal \
|
||||||
|
-I$(PKG_BUILD_DIR)/ath \
|
||||||
|
-I$(PKG_BUILD_DIR)/ath_hal \
|
||||||
|
-I$(PKG_BUILD_DIR)/net80211 \
|
||||||
|
-I$(STAGING_DIR)/usr/include \
|
||||||
|
-include $(PKG_BUILD_DIR)/include/compat.h
|
||||||
|
|
||||||
MAKE_ARGS:= \
|
MAKE_ARGS:= \
|
||||||
PATH="$(TARGET_PATH)" \
|
PATH="$(TARGET_PATH)" \
|
||||||
ARCH="$(LINUX_KARCH)" \
|
ARCH="$(LINUX_KARCH)" \
|
||||||
|
@ -179,6 +191,7 @@ MAKE_ARGS:= \
|
||||||
LDOPTS="--no-warn-mismatch " \
|
LDOPTS="--no-warn-mismatch " \
|
||||||
ATH_RATE="ath_rate/$(RATE_CONTROL)" \
|
ATH_RATE="ath_rate/$(RATE_CONTROL)" \
|
||||||
DO_MULTI=1 \
|
DO_MULTI=1 \
|
||||||
|
INCS="$(MADWIFI_INC)" \
|
||||||
$(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
|
$(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
|
||||||
|
|
||||||
MAKE_VARS:= \
|
MAKE_VARS:= \
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
@@
|
||||||
|
@@
|
||||||
|
#include "if_athioctl.h"
|
||||||
|
+#include "wprobe.h"
|
||||||
|
|
||||||
|
@@
|
||||||
|
@@
|
||||||
|
struct ath_vap {
|
||||||
|
...
|
||||||
|
+ struct wprobe_iface av_wpif;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@
|
||||||
|
@@
|
||||||
|
struct ath_node {
|
||||||
|
...
|
||||||
|
+ struct wprobe_link an_wplink;
|
||||||
|
+ uint8_t an_wplink_active;
|
||||||
|
+ struct work_struct an_destroy;
|
||||||
|
u_int16_t an_decomp_index;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
@@
|
||||||
|
@@
|
||||||
|
ath_vap_create(...) {
|
||||||
|
<...
|
||||||
|
+ ath_init_wprobe_dev(avp);
|
||||||
|
return vap;
|
||||||
|
...>
|
||||||
|
}
|
||||||
|
|
||||||
|
@ rule5 @
|
||||||
|
expression vap;
|
||||||
|
@@
|
||||||
|
ath_vap_delete(...) {
|
||||||
|
<...
|
||||||
|
ieee80211_vap_detach(vap);
|
||||||
|
+ ath_remove_wprobe_dev(ATH_VAP(vap));
|
||||||
|
...>
|
||||||
|
}
|
||||||
|
|
||||||
|
@ rule6 @
|
||||||
|
@@
|
||||||
|
static int xchanmode = -1;
|
||||||
|
+
|
||||||
|
+#include "ath_wprobe.c"
|
||||||
|
|
||||||
|
|
||||||
|
@ rule7 @
|
||||||
|
expression sc, ni;
|
||||||
|
@@
|
||||||
|
<...
|
||||||
|
sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);
|
||||||
|
+ ath_wprobe_node_join(ni->ni_vap, ni);
|
||||||
|
...>
|
||||||
|
|
||||||
|
@ rule8 @
|
||||||
|
expression ni;
|
||||||
|
expression sc;
|
||||||
|
@@
|
||||||
|
<...
|
||||||
|
sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni));
|
||||||
|
+ ath_wprobe_node_leave(ni->ni_vap, ni);
|
||||||
|
...>
|
||||||
|
|
||||||
|
@ rule9 @
|
||||||
|
expression ni;
|
||||||
|
expression rs;
|
||||||
|
@@
|
||||||
|
<...
|
||||||
|
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
|
||||||
|
+ ath_node_sample_rx(ni, rs);
|
||||||
|
...>
|
||||||
|
|
||||||
|
@ rule10 @
|
||||||
|
expression an;
|
||||||
|
expression ts;
|
||||||
|
@@
|
||||||
|
<...
|
||||||
|
ATH_RSSI_LPF(an->an_halstats.ns_avgtxrssi, ts->ts_rssi);
|
||||||
|
+ ath_node_sample_tx(&an->an_node, ts, bf->bf_skb->len);
|
||||||
|
...>
|
||||||
|
|
|
@ -0,0 +1,461 @@
|
||||||
|
--- /dev/null 2009-03-26 21:01:06.000000000 +0100
|
||||||
|
+++ ./ath/ath_wprobe.c 2009-03-26 20:58:07.000000000 +0100
|
||||||
|
@@ -0,0 +1,364 @@
|
||||||
|
+#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,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+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
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+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);
|
||||||
|
+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 / 10;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+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_node_sample_tx(struct ieee80211_node *ni, struct ath_tx_status *ts, int len)
|
||||||
|
+{
|
||||||
|
+ 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;
|
||||||
|
+
|
||||||
|
+ if (wprobe_disabled() || !an->an_wplink_active || !l->val)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ 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 2009-03-26 19:54:36.000000000 +0100
|
||||||
|
+++ /var/folders/DB/DBZUyxsHGRKP0B3nCU1mmU+++TI/-Tmp-/cocci-output-73937-18abc0-if_ath.c 2009-03-26 21:08:34.000000000 +0100
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1605,6 +1607,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--;
|
||||||
|
@@ -5931,6 +5934,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
|
||||||
|
@@ -7001,6 +7005,7 @@ drop_micfail:
|
||||||
|
goto lookup_slowpath;
|
||||||
|
}
|
||||||
|
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
|
||||||
|
+ ath_node_sample_rx(ni, rs);
|
||||||
|
type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
|
||||||
|
ieee80211_unref_node(&ni);
|
||||||
|
} else {
|
||||||
|
@@ -7020,6 +7025,7 @@ lookup_slowpath:
|
||||||
|
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
|
||||||
|
@@ -8599,6 +8605,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->len);
|
||||||
|
if (bf->bf_skb->priority == WME_AC_VO ||
|
||||||
|
bf->bf_skb->priority == WME_AC_VI)
|
||||||
|
ni->ni_ic->ic_wme.wme_hipri_traffic++;
|
||||||
|
@@ -10090,6 +10097,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 2009-03-26 19:54:35.000000000 +0100
|
||||||
|
+++ /var/folders/DB/DBZUyxsHGRKP0B3nCU1mmU+++TI/-Tmp-/cocci-output-73937-80429d-if_athvar.h 2009-03-26 21:08:42.000000000 +0100
|
||||||
|
@@ -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,7 @@ struct ath_vap {
|
||||||
|
#else
|
||||||
|
unsigned int av_beacon_alloc;
|
||||||
|
#endif
|
||||||
|
+ struct wprobe_iface av_wpif;
|
||||||
|
};
|
||||||
|
#define ATH_VAP(_v) ((struct ath_vap *)(_v))
|
||||||
|
|
Loading…
Reference in New Issue