[OLPC-devel] [PATCH] wireless/libertas: miscellaneous fixes
Dan Williams
dcbw at redhat.com
Fri Jun 23 23:58:26 EDT 2006
- Do SET_NETDEV_DEV so the device/driver links are created in sysfs for
the net class device, makes HAL and NetworkManager less angry
- Fix up the re-association code so it actually compiles
- Do wireless quality reporting ipw-style
- Hook up SIOCSIWENCODE so people can actually use encrypted APs
Signed-off-by: Dan Williams <dcbw at redhat.com>
(try #2, wrong list address on first mail, same patch in both)
--- a/drivers/net/wireless/libertas/if_usb.c 2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/if_usb.c 2006-06-23 23:00:54.000000000 -0400
@@ -888,6 +888,8 @@
return WLAN_STATUS_FAILURE;
}
+ SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
+
PRINTM(INFO, "udev pointer is at %p\n", cardp->udev);
LEAVE();
--- a/drivers/net/wireless/libertas/wlan_decl.h 2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/wlan_decl.h 2006-06-23 23:08:05.000000000 -0400
@@ -80,7 +80,7 @@
void command_timer_fn(unsigned long data);
#ifdef REASSOCIATION
-void reassoc_timer_fn(void data);
+void reassoc_timer_fn(unsigned long data);
#endif /* REASSOCIATION */
int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
--- a/drivers/net/wireless/libertas/wlan_dev.h 2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/wlan_dev.h 2006-06-23 23:04:56.000000000 -0400
@@ -248,7 +248,7 @@
#ifdef REASSOCIATION
/** Reassociation on and off */
u8 Reassoc_on;
- SEMAPHORE ReassocSem;
+ struct semaphore ReassocSem;
#endif /* REASSOCIATION */
u8 ATIMEnabled;
--- a/drivers/net/wireless/libertas/wlan_wext.c 2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/wlan_wext.c 2006-06-23 23:32:03.000000000 -0400
@@ -819,7 +819,7 @@
ENTER();
- del_timer(&Adapter->MrvDrvTimer);
+ del_timer(&Adapter->reassoc_timer);
Adapter->Reassoc_on = FALSE;
@@ -1792,12 +1792,17 @@
/*
* Set the qual, level and noise range values
*/
- /*
- * need to put the right values here
- */
- range->max_qual.qual = 10;
+ range->max_qual.qual = 100;
range->max_qual.level = 0;
range->max_qual.noise = 0;
+ range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+ range->avg_qual.qual = 70;
+ /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
+ range->avg_qual.level = 0;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
range->sensitivity = 0;
/*
@@ -2005,7 +2010,7 @@
(iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
(iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
(iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
- (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
(iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
(iw_handler) wlan_set_power, /* SIOCSIWPOWER */
(iw_handler) wlan_get_power, /* SIOCGIWPOWER */
@@ -4655,46 +4660,116 @@
*/
struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
{
+ enum {
+ POOR = 30,
+ FAIR = 60,
+ GOOD = 80,
+ VERY_GOOD = 90,
+ EXCELLENT = 95,
+ PERFECT = 100
+ };
wlan_private *priv = dev->priv;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
+ u32 rssi_qual;
+ u32 tx_qual;
+ u32 quality = 0;
+ int stats_valid = 0;
+ u8 rssi;
ENTER();
priv->wstats.status = Adapter->InfrastructureMode;
- priv->wstats.discard.retries = priv->stats.tx_errors;
+
+ /* If we're not associated, all quality values are meaningless */
+ if (Adapter->MediaConnectStatus != WlanMediaStateConnected)
+ goto out;
/* send RSSI command to get beacon RSSI/NF, valid only if associated */
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_RSSI,
0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+ if (ret)
+ goto out;
+ /* Quality by RSSI */
priv->wstats.qual.level =
CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
- Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
- priv->wstats.qual.noise = CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
- if (Adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0
- && Adapter->MediaConnectStatus == WlanMediaStateConnected)
+ Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+
+ if (Adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
- else
+ } else {
priv->wstats.qual.noise =
CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
- priv->wstats.qual.qual = 0;
+ }
PRINTM(INFO, "Signal Level = %#x\n", priv->wstats.qual.level);
PRINTM(INFO, "Noise = %#x\n", priv->wstats.qual.noise);
+ rssi = priv->wstats.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ if (rssi < 15)
+ rssi_qual = rssi * POOR / 10;
+ else if (rssi < 20)
+ rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
+ else if (rssi < 30)
+ rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
+ else if (rssi < 40)
+ rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
+ 10 + GOOD;
+ else
+ rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
+ 10 + VERY_GOOD;
+ quality = rssi_qual;
+
+ /* Quality by TX errors */
+ priv->wstats.discard.retries = priv->stats.tx_errors;
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_GET_LOG,
0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
-
if (!ret) {
+ u32 tx_retries = Adapter->LogMsg.retry;
+
+ if (tx_retries > 75)
+ tx_qual = (90 - tx_retries) * POOR / 15;
+ else if (tx_retries > 70)
+ tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
+ else if (tx_retries > 65)
+ tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
+ else if (tx_retries > 50)
+ tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
+ 15 + GOOD;
+ else
+ tx_qual = (50 - tx_retries) *
+ (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+ quality = min(quality, tx_qual);
+
priv->wstats.discard.code = Adapter->LogMsg.wepundecryptable;
priv->wstats.discard.fragment = Adapter->LogMsg.fcserror;
- priv->wstats.discard.retries = Adapter->LogMsg.retry;
+ priv->wstats.discard.retries = tx_retries;
priv->wstats.discard.misc = Adapter->LogMsg.ackfailure;
}
+ /* Calculate quality */
+ priv->wstats.qual.qual = max(quality, (u32)100);
+ priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+ stats_valid = 1;
+
+out:
+ if (!stats_valid) {
+ priv->wstats.miss.beacon = 0;
+ priv->wstats.discard.retries = 0;
+ priv->wstats.qual.qual = 0;
+ priv->wstats.qual.level = 0;
+ priv->wstats.qual.noise = 0;
+ priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+ priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
+ IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+ }
+
+ LEAVE ();
return &priv->wstats;
+
+
}
/**
More information about the Devel
mailing list