aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/airo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r--drivers/net/wireless/airo.c152
1 files changed, 105 insertions, 47 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 463c789cdc77..d72e0385e4f2 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -754,7 +754,7 @@ typedef struct {
754 u8 zero; 754 u8 zero;
755 u8 ssidLen; 755 u8 ssidLen;
756 u8 ssid[32]; 756 u8 ssid[32];
757 u16 rssi; 757 u16 dBm;
758#define CAP_ESS (1<<0) 758#define CAP_ESS (1<<0)
759#define CAP_IBSS (1<<1) 759#define CAP_IBSS (1<<1)
760#define CAP_PRIVACY (1<<4) 760#define CAP_PRIVACY (1<<4)
@@ -1125,6 +1125,9 @@ static int micsetup(struct airo_info *ai);
1125static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len); 1125static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
1126static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen); 1126static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
1127 1127
1128static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
1129static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
1130
1128#include <linux/crypto.h> 1131#include <linux/crypto.h>
1129#endif 1132#endif
1130 1133
@@ -1713,6 +1716,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
1713 list->fh.dwell = le16_to_cpu(list->fh.dwell); 1716 list->fh.dwell = le16_to_cpu(list->fh.dwell);
1714 list->dsChannel = le16_to_cpu(list->dsChannel); 1717 list->dsChannel = le16_to_cpu(list->dsChannel);
1715 list->atimWindow = le16_to_cpu(list->atimWindow); 1718 list->atimWindow = le16_to_cpu(list->atimWindow);
1719 list->dBm = le16_to_cpu(list->dBm);
1716 return rc; 1720 return rc;
1717} 1721}
1718 1722
@@ -2914,7 +2918,7 @@ static int airo_thread(void *data) {
2914 flush_signals(current); 2918 flush_signals(current);
2915 2919
2916 /* make swsusp happy with our thread */ 2920 /* make swsusp happy with our thread */
2917 try_to_freeze(PF_FREEZE); 2921 try_to_freeze();
2918 2922
2919 if (test_bit(JOB_DIE, &ai->flags)) 2923 if (test_bit(JOB_DIE, &ai->flags))
2920 break; 2924 break;
@@ -3245,7 +3249,10 @@ badrx:
3245 wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; 3249 wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
3246 else 3250 else
3247 wstats.level = (hdr.rssi[1] + 321) / 2; 3251 wstats.level = (hdr.rssi[1] + 321) / 2;
3248 wstats.updated = 3; 3252 wstats.noise = apriv->wstats.qual.noise;
3253 wstats.updated = IW_QUAL_LEVEL_UPDATED
3254 | IW_QUAL_QUAL_UPDATED
3255 | IW_QUAL_NOISE_UPDATED;
3249 /* Update spy records */ 3256 /* Update spy records */
3250 wireless_spy_update(dev, sa, &wstats); 3257 wireless_spy_update(dev, sa, &wstats);
3251 } 3258 }
@@ -3588,7 +3595,10 @@ void mpi_receive_802_11 (struct airo_info *ai)
3588 wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; 3595 wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
3589 else 3596 else
3590 wstats.level = (hdr.rssi[1] + 321) / 2; 3597 wstats.level = (hdr.rssi[1] + 321) / 2;
3591 wstats.updated = 3; 3598 wstats.noise = ai->wstats.qual.noise;
3599 wstats.updated = IW_QUAL_QUAL_UPDATED
3600 | IW_QUAL_LEVEL_UPDATED
3601 | IW_QUAL_NOISE_UPDATED;
3592 /* Update spy records */ 3602 /* Update spy records */
3593 wireless_spy_update(ai->dev, sa, &wstats); 3603 wireless_spy_update(ai->dev, sa, &wstats);
3594 } 3604 }
@@ -3679,7 +3689,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
3679 status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock); 3689 status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
3680 if ( status == SUCCESS ) { 3690 if ( status == SUCCESS ) {
3681 if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) 3691 if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
3682 memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); 3692 memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
3683 } 3693 }
3684 else { 3694 else {
3685 if (ai->rssi) { 3695 if (ai->rssi) {
@@ -5348,7 +5358,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
5348 (int)BSSList_rid.bssid[5], 5358 (int)BSSList_rid.bssid[5],
5349 (int)BSSList_rid.ssidLen, 5359 (int)BSSList_rid.ssidLen,
5350 BSSList_rid.ssid, 5360 BSSList_rid.ssid,
5351 (int)BSSList_rid.rssi); 5361 (int)BSSList_rid.dBm);
5352 ptr += sprintf(ptr, " channel = %d %s %s %s %s\n", 5362 ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
5353 (int)BSSList_rid.dsChannel, 5363 (int)BSSList_rid.dsChannel,
5354 BSSList_rid.cap & CAP_ESS ? "ESS" : "", 5364 BSSList_rid.cap & CAP_ESS ? "ESS" : "",
@@ -5593,6 +5603,29 @@ static void __exit airo_cleanup_module( void )
5593 * would not work at all... - Jean II 5603 * would not work at all... - Jean II
5594 */ 5604 */
5595 5605
5606static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi)
5607{
5608 if( !rssi_rid )
5609 return 0;
5610
5611 return (0x100 - rssi_rid[rssi].rssidBm);
5612}
5613
5614static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
5615{
5616 int i;
5617
5618 if( !rssi_rid )
5619 return 0;
5620
5621 for( i = 0; i < 256; i++ )
5622 if (rssi_rid[i].rssidBm == dbm)
5623 return rssi_rid[i].rssipct;
5624
5625 return 0;
5626}
5627
5628
5596static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) 5629static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
5597{ 5630{
5598 int quality = 0; 5631 int quality = 0;
@@ -6443,11 +6476,29 @@ static int airo_get_range(struct net_device *dev,
6443 } 6476 }
6444 range->num_frequency = k; 6477 range->num_frequency = k;
6445 6478
6479 range->sensitivity = 65535;
6480
6446 /* Hum... Should put the right values there */ 6481 /* Hum... Should put the right values there */
6447 range->max_qual.qual = airo_get_max_quality(&cap_rid); 6482 if (local->rssi)
6448 range->max_qual.level = 0x100 - 120; /* -120 dBm */ 6483 range->max_qual.qual = 100; /* % */
6484 else
6485 range->max_qual.qual = airo_get_max_quality(&cap_rid);
6486 range->max_qual.level = 0; /* 0 means we use dBm */
6449 range->max_qual.noise = 0; 6487 range->max_qual.noise = 0;
6450 range->sensitivity = 65535; 6488 range->max_qual.updated = 0;
6489
6490 /* Experimental measurements - boundary 11/5.5 Mb/s */
6491 /* Note : with or without the (local->rssi), results
6492 * are somewhat different. - Jean II */
6493 if (local->rssi) {
6494 range->avg_qual.qual = 50; /* % */
6495 range->avg_qual.level = 186; /* -70 dBm */
6496 } else {
6497 range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
6498 range->avg_qual.level = 176; /* -80 dBm */
6499 }
6500 range->avg_qual.noise = 0;
6501 range->avg_qual.updated = 0;
6451 6502
6452 for(i = 0 ; i < 8 ; i++) { 6503 for(i = 0 ; i < 8 ; i++) {
6453 range->bitrate[i] = cap_rid.supportedRates[i] * 500000; 6504 range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
@@ -6508,15 +6559,6 @@ static int airo_get_range(struct net_device *dev,
6508 range->max_retry = 65535; 6559 range->max_retry = 65535;
6509 range->min_r_time = 1024; 6560 range->min_r_time = 1024;
6510 range->max_r_time = 65535 * 1024; 6561 range->max_r_time = 65535 * 1024;
6511 /* Experimental measurements - boundary 11/5.5 Mb/s */
6512 /* Note : with or without the (local->rssi), results
6513 * are somewhat different. - Jean II */
6514 range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
6515 if (local->rssi)
6516 range->avg_qual.level = 186; /* -70 dBm */
6517 else
6518 range->avg_qual.level = 176; /* -80 dBm */
6519 range->avg_qual.noise = 0;
6520 6562
6521 /* Event capability (kernel + driver) */ 6563 /* Event capability (kernel + driver) */
6522 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | 6564 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
@@ -6676,12 +6718,18 @@ static int airo_get_aplist(struct net_device *dev,
6676 loseSync = 0; 6718 loseSync = 0;
6677 memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN); 6719 memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
6678 address[i].sa_family = ARPHRD_ETHER; 6720 address[i].sa_family = ARPHRD_ETHER;
6679 if (local->rssi) 6721 if (local->rssi) {
6680 qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm; 6722 qual[i].level = 0x100 - BSSList.dBm;
6681 else 6723 qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
6682 qual[i].level = (BSSList.rssi + 321) / 2; 6724 qual[i].updated = IW_QUAL_QUAL_UPDATED;
6683 qual[i].qual = qual[i].noise = 0; 6725 } else {
6684 qual[i].updated = 2; 6726 qual[i].level = (BSSList.dBm + 321) / 2;
6727 qual[i].qual = 0;
6728 qual[i].updated = IW_QUAL_QUAL_INVALID;
6729 }
6730 qual[i].noise = local->wstats.qual.noise;
6731 qual[i].updated = IW_QUAL_LEVEL_UPDATED
6732 | IW_QUAL_NOISE_UPDATED;
6685 if (BSSList.index == 0xffff) 6733 if (BSSList.index == 0xffff)
6686 break; 6734 break;
6687 } 6735 }
@@ -6760,7 +6808,7 @@ static int airo_set_scan(struct net_device *dev,
6760static inline char *airo_translate_scan(struct net_device *dev, 6808static inline char *airo_translate_scan(struct net_device *dev,
6761 char *current_ev, 6809 char *current_ev,
6762 char *end_buf, 6810 char *end_buf,
6763 BSSListRid *list) 6811 BSSListRid *bss)
6764{ 6812{
6765 struct airo_info *ai = dev->priv; 6813 struct airo_info *ai = dev->priv;
6766 struct iw_event iwe; /* Temporary buffer */ 6814 struct iw_event iwe; /* Temporary buffer */
@@ -6771,22 +6819,22 @@ static inline char *airo_translate_scan(struct net_device *dev,
6771 /* First entry *MUST* be the AP MAC address */ 6819 /* First entry *MUST* be the AP MAC address */
6772 iwe.cmd = SIOCGIWAP; 6820 iwe.cmd = SIOCGIWAP;
6773 iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 6821 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
6774 memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN); 6822 memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
6775 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); 6823 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
6776 6824
6777 /* Other entries will be displayed in the order we give them */ 6825 /* Other entries will be displayed in the order we give them */
6778 6826
6779 /* Add the ESSID */ 6827 /* Add the ESSID */
6780 iwe.u.data.length = list->ssidLen; 6828 iwe.u.data.length = bss->ssidLen;
6781 if(iwe.u.data.length > 32) 6829 if(iwe.u.data.length > 32)
6782 iwe.u.data.length = 32; 6830 iwe.u.data.length = 32;
6783 iwe.cmd = SIOCGIWESSID; 6831 iwe.cmd = SIOCGIWESSID;
6784 iwe.u.data.flags = 1; 6832 iwe.u.data.flags = 1;
6785 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); 6833 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
6786 6834
6787 /* Add mode */ 6835 /* Add mode */
6788 iwe.cmd = SIOCGIWMODE; 6836 iwe.cmd = SIOCGIWMODE;
6789 capabilities = le16_to_cpu(list->cap); 6837 capabilities = le16_to_cpu(bss->cap);
6790 if(capabilities & (CAP_ESS | CAP_IBSS)) { 6838 if(capabilities & (CAP_ESS | CAP_IBSS)) {
6791 if(capabilities & CAP_ESS) 6839 if(capabilities & CAP_ESS)
6792 iwe.u.mode = IW_MODE_MASTER; 6840 iwe.u.mode = IW_MODE_MASTER;
@@ -6797,19 +6845,25 @@ static inline char *airo_translate_scan(struct net_device *dev,
6797 6845
6798 /* Add frequency */ 6846 /* Add frequency */
6799 iwe.cmd = SIOCGIWFREQ; 6847 iwe.cmd = SIOCGIWFREQ;
6800 iwe.u.freq.m = le16_to_cpu(list->dsChannel); 6848 iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
6801 iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000; 6849 iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
6802 iwe.u.freq.e = 1; 6850 iwe.u.freq.e = 1;
6803 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); 6851 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
6804 6852
6805 /* Add quality statistics */ 6853 /* Add quality statistics */
6806 iwe.cmd = IWEVQUAL; 6854 iwe.cmd = IWEVQUAL;
6807 if (ai->rssi) 6855 if (ai->rssi) {
6808 iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm; 6856 iwe.u.qual.level = 0x100 - bss->dBm;
6809 else 6857 iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
6810 iwe.u.qual.level = (list->rssi + 321) / 2; 6858 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
6811 iwe.u.qual.noise = 0; 6859 } else {
6812 iwe.u.qual.qual = 0; 6860 iwe.u.qual.level = (bss->dBm + 321) / 2;
6861 iwe.u.qual.qual = 0;
6862 iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
6863 }
6864 iwe.u.qual.noise = ai->wstats.qual.noise;
6865 iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
6866 | IW_QUAL_NOISE_UPDATED;
6813 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); 6867 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
6814 6868
6815 /* Add encryption capability */ 6869 /* Add encryption capability */
@@ -6819,7 +6873,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
6819 else 6873 else
6820 iwe.u.data.flags = IW_ENCODE_DISABLED; 6874 iwe.u.data.flags = IW_ENCODE_DISABLED;
6821 iwe.u.data.length = 0; 6875 iwe.u.data.length = 0;
6822 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); 6876 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
6823 6877
6824 /* Rate : stuffing multiple values in a single event require a bit 6878 /* Rate : stuffing multiple values in a single event require a bit
6825 * more of magic - Jean II */ 6879 * more of magic - Jean II */
@@ -6831,10 +6885,10 @@ static inline char *airo_translate_scan(struct net_device *dev,
6831 /* Max 8 values */ 6885 /* Max 8 values */
6832 for(i = 0 ; i < 8 ; i++) { 6886 for(i = 0 ; i < 8 ; i++) {
6833 /* NULL terminated */ 6887 /* NULL terminated */
6834 if(list->rates[i] == 0) 6888 if(bss->rates[i] == 0)
6835 break; 6889 break;
6836 /* Bit rate given in 500 kb/s units (+ 0x80) */ 6890 /* Bit rate given in 500 kb/s units (+ 0x80) */
6837 iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000); 6891 iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
6838 /* Add new value to event */ 6892 /* Add new value to event */
6839 current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); 6893 current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
6840 } 6894 }
@@ -7153,18 +7207,22 @@ static void airo_read_wireless_stats(struct airo_info *local)
7153 /* The status */ 7207 /* The status */
7154 local->wstats.status = status_rid.mode; 7208 local->wstats.status = status_rid.mode;
7155 7209
7156 /* Signal quality and co. But where is the noise level ??? */ 7210 /* Signal quality and co */
7157 local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); 7211 if (local->rssi) {
7158 if (local->rssi) 7212 local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality );
7159 local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm; 7213 /* normalizedSignalStrength appears to be a percentage */
7160 else 7214 local->wstats.qual.qual = status_rid.normalizedSignalStrength;
7215 } else {
7161 local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; 7216 local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
7217 local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
7218 }
7219 local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
7162 if (status_rid.len >= 124) { 7220 if (status_rid.len >= 124) {
7163 local->wstats.qual.noise = 256 - status_rid.noisedBm; 7221 local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
7164 local->wstats.qual.updated = 7; 7222 local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
7165 } else { 7223 } else {
7166 local->wstats.qual.noise = 0; 7224 local->wstats.qual.noise = 0;
7167 local->wstats.qual.updated = 3; 7225 local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
7168 } 7226 }
7169 7227
7170 /* Packets discarded in the wireless adapter due to wireless 7228 /* Packets discarded in the wireless adapter due to wireless