aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2010-07-11 06:23:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-12 16:05:33 -0400
commit748619220651a33c260ed6c0a7648e69324edd74 (patch)
tree70aac3f3abd9ea5826f2217f708836dfe6434980 /drivers
parent5e846004914d2295e020edd48a828b653323f93e (diff)
rt2x00: Convert AGC value from descriptor to RSSI (dBm)
The RSSI values in the RXWI descriptor aren't true RSSI values. Instead they are more like the AGC values similar to rt61pci. And as such, it needs the same conversion before it can be passed to rt2x00lib/mac80211. This requires the struct queue_entry to be passed to rt2800_process_rxwi rather then the skb structure which is contained in the queue_entry. This is required to obtain the lna_gain information from the rt2x00_dev structure. This fixes connection problems when using wpa_supplicant which would try to connect to the worst AP's rather then the best ones. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c57
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c2
5 files changed, 55 insertions, 10 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 3cda22931876..edd3734b8b32 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -74,7 +74,7 @@
74 * Signal information. 74 * Signal information.
75 * Default offset is required for RSSI <-> dBm conversion. 75 * Default offset is required for RSSI <-> dBm conversion.
76 */ 76 */
77#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ 77#define DEFAULT_RSSI_OFFSET 120
78 78
79/* 79/*
80 * Register layout information. 80 * Register layout information.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 9030eef2403d..255d089e87ea 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -325,9 +325,53 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
325} 325}
326EXPORT_SYMBOL_GPL(rt2800_write_txwi); 326EXPORT_SYMBOL_GPL(rt2800_write_txwi);
327 327
328void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) 328static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2)
329{ 329{
330 __le32 *rxwi = (__le32 *) skb->data; 330 int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
331 int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
332 int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
333 u16 eeprom;
334 u8 offset0;
335 u8 offset1;
336 u8 offset2;
337
338 if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) {
339 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
340 offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
341 offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
342 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
343 offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
344 } else {
345 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
346 offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
347 offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
348 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
349 offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
350 }
351
352 /*
353 * Convert the value from the descriptor into the RSSI value
354 * If the value in the descriptor is 0, it is considered invalid
355 * and the default (extremely low) rssi value is assumed
356 */
357 rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
358 rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
359 rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
360
361 /*
362 * mac80211 only accepts a single RSSI value. Calculating the
363 * average doesn't deliver a fair answer either since -60:-60 would
364 * be considered equally good as -50:-70 while the second is the one
365 * which gives less energy...
366 */
367 rssi0 = max(rssi0, rssi1);
368 return max(rssi0, rssi2);
369}
370
371void rt2800_process_rxwi(struct queue_entry *entry,
372 struct rxdone_entry_desc *rxdesc)
373{
374 __le32 *rxwi = (__le32 *) entry->skb->data;
331 u32 word; 375 u32 word;
332 376
333 rt2x00_desc_read(rxwi, 0, &word); 377 rt2x00_desc_read(rxwi, 0, &word);
@@ -358,14 +402,15 @@ void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc)
358 402
359 rt2x00_desc_read(rxwi, 2, &word); 403 rt2x00_desc_read(rxwi, 2, &word);
360 404
361 rxdesc->rssi = 405 /*
362 (rt2x00_get_field32(word, RXWI_W2_RSSI0) + 406 * Convert descriptor AGC value to RSSI value.
363 rt2x00_get_field32(word, RXWI_W2_RSSI1)) / 2; 407 */
408 rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
364 409
365 /* 410 /*
366 * Remove RXWI descriptor from start of buffer. 411 * Remove RXWI descriptor from start of buffer.
367 */ 412 */
368 skb_pull(skb, RXWI_DESC_SIZE); 413 skb_pull(entry->skb, RXWI_DESC_SIZE);
369} 414}
370EXPORT_SYMBOL_GPL(rt2800_process_rxwi); 415EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
371 416
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 8313dbf441a5..eb3a4f50a363 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -121,7 +121,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
121 const u8 arg0, const u8 arg1); 121 const u8 arg0, const u8 arg1);
122 122
123void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); 123void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc);
124void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); 124void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
125 125
126void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); 126void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
127 127
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 6f11760117da..faf71e2aeb64 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -805,7 +805,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
805 /* 805 /*
806 * Process the RXWI structure that is at the start of the buffer. 806 * Process the RXWI structure that is at the start of the buffer.
807 */ 807 */
808 rt2800_process_rxwi(entry->skb, rxdesc); 808 rt2800_process_rxwi(entry, rxdesc);
809 809
810 /* 810 /*
811 * Set RX IDX in register to inform hardware that we have handled 811 * Set RX IDX in register to inform hardware that we have handled
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 4f85f7b42441..f2cd37e5aea8 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -563,7 +563,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
563 /* 563 /*
564 * Process the RXWI structure. 564 * Process the RXWI structure.
565 */ 565 */
566 rt2800_process_rxwi(entry->skb, rxdesc); 566 rt2800_process_rxwi(entry, rxdesc);
567} 567}
568 568
569/* 569/*