Jiri,
This patch, which is made against your tree today, implements wireless
statistics for bcm43xx-d80211 in the same manner as was previously
done for bcm43xx-softmac.
There are changes to two of the data structures:
1. In bcm43xx_stats, the completely bogus 'link_quality' is replaced
by 'link_noise', which is calculated in 'handle_irq_noise'.
2. In ieee80211_rx_status, values for 'maxssi', 'signal', and 'noise'
have been added. For the bcm43xx driver, these could be u8's, but they
may need to be int's for other hardware. For the bcm43xx, maxssi is
set to RX_MAX_SSI, which is defined in bcm43xx_xmit.c.
The rest of the patches are a straight-forward passing of the data
from the driver to the d80211 version of ieee80211.
Note: there are some line-wrap problems in the patch below. Once the
code is accepted, I will generate a proper patch.
Larry
==================================================================
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
b/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
index a0faeca..d805928 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
@@ -623,7 +623,7 @@ struct bcm43xx_noise_calculation {
};
struct bcm43xx_stats {
- u8 link_quality;
+ u8 link_noise;
/* Store the last TX/RX times here for updating the leds. */
unsigned long last_tx;
unsigned long last_rx;
diff --git a/include/net/d80211.h b/include/net/d80211.h
index ba5cb4c..8479b58 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -205,6 +205,9 @@ struct ieee80211_rx_status {
int channel;
int phymode;
int ssi;
+ int maxssi;
+ int signal;
+ int noise;
int antenna;
int rate;
int flag;
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index 59d137b..4c43ecb 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -1506,15 +1506,7 @@ static void handle_irq_noise(struct bcm4
else
average -= 48;
- if (average > -65)
- bcm->stats.link_quality = 0;
- else if (average > -75)
- bcm->stats.link_quality = 1;
- else if (average > -85)
- bcm->stats.link_quality = 2;
- else
- bcm->stats.link_quality = 3;
-// dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n",
bcm->stats.link_quality, average);
+ bcm->stats.link_noise = average;
drop_calculation:
bcm->noisecalc.calculation_running = 0;
return;
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
index 3f86079..7b684e4 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
@@ -29,6 +29,7 @@
#include "bcm43xx_xmit.h"
+#define RX_MAX_SSI 60
/* Extract the bitrate out of a CCK PLCP header. */
static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
@@ -475,7 +476,10 @@ void bcm43xx_rx(struct bcm43xx_private *
*/
memset(&status, 0, sizeof(status));
- status.ssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+ status.noise = bcm->stats.link_noise;
+ status.ssi = rxhdr->rssi;
+ status.maxssi = RX_MAX_SSI;
+ status.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
!!(rxflags1 &
BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
!!(rxflags3 &
BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
if (is_ofdm)
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 60eca90..034eee5 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3173,6 +3173,9 @@ ieee80211_rx_h_sta_process(struct ieee80
sta->rx_fragments++;
sta->rx_bytes += rx->skb->len;
sta->last_rssi = rx->u.rx.status->ssi;
+ sta->last_signal = rx->u.rx.status->signal;
+ sta->last_noise = rx->u.rx.status->noise;
+ sta->max_rssi = rx->u.rx.status->maxssi;
if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
/* Change STA power saving mode only in the end of a frame
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 7e021ec..dbbf29a 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -337,6 +337,9 @@ struct ieee80211_local {
struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
int open_count;
int monitors;
+ u8 link_quality;
+ u8 noise;
+ struct iw_statistics wstats;
struct ieee80211_conf conf;
int dev_index;
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index dd52555..c9aa2f5 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1525,6 +1525,16 @@ static int ieee80211_ioctl_giwrange(stru
range->min_frag = 256;
range->max_frag = 2346;
+ range->max_qual.qual = 100;
+ range->max_qual.level = 152; /* set floor at -104 dBm (152 - 256) */
+ range->max_qual.noise = 152;
+ range->max_qual.updated = IW_QUAL_ALL_UPDATED;
+
+ range->avg_qual.qual = 50;
+ range->avg_qual.level = 0;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
+
return 0;
}
@@ -2963,6 +2973,39 @@ static int ieee80211_ioctl_giwauth(struc
return ret;
}
+/* Get wireless statistics. Called by /proc/net/wireless and by
SIOCGIWSTATS */
+static struct iw_statistics *ieee80211_get_wireless_stats(struct
net_device *net_dev)
+{
+ struct ieee80211_local *local = net_dev->ieee80211_ptr;
+ struct iw_statistics * wstats = &local->wstats;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(net_dev);
+ struct sta_info *sta;
+ static int tmp_level = 0;
+ static int tmp_qual = 0;
+
+ sta = sta_info_get(local, sdata->u.sta.bssid);
+ if (!sta) {
+ wstats->discard.fragment = 0;
+ wstats->discard.misc = 0;
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated |= IW_QUAL_ALL_UPDATED;
+ } else {
+ if (!tmp_level) { /* get initial values */
+ tmp_level = sta->last_signal;
+ tmp_qual = sta->last_rssi;
+ } else { /* smooth results */
+ tmp_level = (15 * tmp_level + sta->last_signal)/16;
+ tmp_qual = (15 * tmp_qual + sta->last_rssi)/16;
+ }
+ wstats->qual.level = tmp_level;
+ wstats->qual.qual = 100*tmp_qual/sta->max_rssi;
+ wstats->qual.noise = sta->last_noise;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ }
+ return wstats;
+}
static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
struct iw_request_info *info,
@@ -3128,4 +3171,5 @@ const struct iw_handler_def ieee80211_iw
.standard = (iw_handler *) ieee80211_handler,
.private = (iw_handler *) ieee80211_private_handler,
.private_args = (struct iw_priv_args *) ieee80211_ioctl_priv,
+ .get_wireless_stats = ieee80211_get_wireless_stats,
};
diff --git a/net/d80211/sta_info.h b/net/d80211/sta_info.h
index 70334e5..4d4169e 100644
--- a/net/d80211/sta_info.h
+++ b/net/d80211/sta_info.h
@@ -82,6 +82,9 @@ struct sta_info {
unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
int last_rssi; /* RSSI of last received frame from this STA */
+ int last_signal; /* signal of last received frame from this STA */
+ int last_noise; /* noise of last received frame from this STA */
+ int max_rssi; /* maximum value of RSSI for this STA */
int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
unsigned long last_ack;
int channel_use;
_______________________________________________
Bcm43xx-dev mailing list
[email protected]
http://bat.berlios.de/mailman/listinfo/bcm43xx-dev