}
EXPORT_SYMBOL_GPL(rt2800_write_txwi);
-void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc)
+static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2)
{
- __le32 *rxwi = (__le32 *) skb->data;
+ int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
+ int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
+ int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
+ u16 eeprom;
+ u8 offset0;
+ u8 offset1;
+ u8 offset2;
+
+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
+ offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
+ offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+ offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
+ } else {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
+ offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
+ offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+ offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
+ }
+
+ /*
+ * Convert the value from the descriptor into the RSSI value
+ * If the value in the descriptor is 0, it is considered invalid
+ * and the default (extremely low) rssi value is assumed
+ */
+ rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
+ rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
+ rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
+
+ /*
+ * mac80211 only accepts a single RSSI value. Calculating the
+ * average doesn't deliver a fair answer either since -60:-60 would
+ * be considered equally good as -50:-70 while the second is the one
+ * which gives less energy...
+ */
+ rssi0 = max(rssi0, rssi1);
+ return max(rssi0, rssi2);
+}
+
+void rt2800_process_rxwi(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
+{
+ __le32 *rxwi = (__le32 *) entry->skb->data;
u32 word;
rt2x00_desc_read(rxwi, 0, &word);
rt2x00_desc_read(rxwi, 2, &word);
- rxdesc->rssi =
- (rt2x00_get_field32(word, RXWI_W2_RSSI0) +
- rt2x00_get_field32(word, RXWI_W2_RSSI1)) / 2;
+ /*
+ * Convert descriptor AGC value to RSSI value.
+ */
+ rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
/*
* Remove RXWI descriptor from start of buffer.
*/
- skb_pull(skb, RXWI_DESC_SIZE);
+ skb_pull(entry->skb, RXWI_DESC_SIZE);
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);