qual->false_cca = bbp;
}
-static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, u8 vgc_level)
{
rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
- rt2x00dev->link.vgc_level = vgc_level;
- rt2x00dev->link.vgc_level_reg = vgc_level;
+ qual->vgc_level = vgc_level;
+ qual->vgc_level_reg = vgc_level;
}
-static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
- rt2400pci_set_vgc(rt2x00dev, 0x08);
+ rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
}
-static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, const u32 count)
{
- struct link *link = &rt2x00dev->link;
-
/*
* The link tuner should not run longer then 60 seconds,
* and should run once every 2 seconds.
*/
- if (link->count > 60 || !(link->count & 1))
+ if (count > 60 || !(count & 1))
return;
/*
* Base r13 link tuning on the false cca count.
*/
- if ((link->qual.false_cca > 512) && (link->vgc_level < 0x20))
- rt2400pci_set_vgc(rt2x00dev, ++link->vgc_level);
- else if ((link->qual.false_cca < 100) && (link->vgc_level > 0x08))
- rt2400pci_set_vgc(rt2x00dev, --link->vgc_level);
+ if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
+ rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+ else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
+ rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
}
/*
qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
}
-static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, u8 vgc_level)
{
- if (rt2x00dev->link.vgc_level_reg != vgc_level) {
+ if (qual->vgc_level_reg != vgc_level) {
rt2500pci_bbp_write(rt2x00dev, 17, vgc_level);
- rt2x00dev->link.vgc_level_reg = vgc_level;
+ qual->vgc_level_reg = vgc_level;
}
}
-static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
- rt2500pci_set_vgc(rt2x00dev, 0x48);
+ rt2500pci_set_vgc(rt2x00dev, qual, 0x48);
}
-static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, const u32 count)
{
- struct link *link = &rt2x00dev->link;
- int rssi = rt2x00_get_link_rssi(link);
-
/*
* To prevent collisions with MAC ASIC on chipsets
* up to version C the link tuning should halt after 20
* seconds while being associated.
*/
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
- rt2x00dev->intf_associated && link->count > 20)
+ rt2x00dev->intf_associated && count > 20)
return;
/*
* then corrupt the R17 tuning. To remidy this the tuning should
* be stopped (While making sure the R17 value will not exceed limits)
*/
- if (rssi < -80 && link->count > 20) {
- if (link->vgc_level_reg >= 0x41)
- rt2500pci_set_vgc(rt2x00dev, link->vgc_level);
+ if (qual->rssi < -80 && count > 20) {
+ if (qual->vgc_level_reg >= 0x41)
+ rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
return;
}
/*
* Special big-R17 for short distance
*/
- if (rssi >= -58) {
- rt2500pci_set_vgc(rt2x00dev, 0x50);
+ if (qual->rssi >= -58) {
+ rt2500pci_set_vgc(rt2x00dev, qual, 0x50);
return;
}
/*
* Special mid-R17 for middle distance
*/
- if (rssi >= -74) {
- rt2500pci_set_vgc(rt2x00dev, 0x41);
+ if (qual->rssi >= -74) {
+ rt2500pci_set_vgc(rt2x00dev, qual, 0x41);
return;
}
* Leave short or middle distance condition, restore r17
* to the dynamic tuning range.
*/
- if (link->vgc_level_reg >= 0x41) {
- rt2500pci_set_vgc(rt2x00dev, link->vgc_level);
+ if (qual->vgc_level_reg >= 0x41) {
+ rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
return;
}
* R17 is inside the dynamic tuning range,
* start tuning the link based on the false cca counter.
*/
- if (link->qual.false_cca > 512 && link->vgc_level_reg < 0x40) {
- rt2500pci_set_vgc(rt2x00dev, ++link->vgc_level_reg);
- link->vgc_level = link->vgc_level_reg;
- } else if (link->qual.false_cca < 100 && link->vgc_level_reg > 0x32) {
- rt2500pci_set_vgc(rt2x00dev, --link->vgc_level_reg);
- link->vgc_level = link->vgc_level_reg;
+ if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) {
+ rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg);
+ qual->vgc_level = qual->vgc_level_reg;
+ } else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) {
+ rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg);
+ qual->vgc_level = qual->vgc_level_reg;
}
}
qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
}
-static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u16 eeprom;
u16 value;
value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
rt2500usb_bbp_write(rt2x00dev, 17, value);
- rt2x00dev->link.vgc_level = value;
+ qual->vgc_level = value;
}
/*
*/
struct link_qual {
/*
- * Statistics required for Link tuning.
- * For the average RSSI value we use the "Walking average" approach.
- * When adding RSSI to the average value the following calculation
- * is needed:
- *
- * avg_rssi = ((avg_rssi * 7) + rssi) / 8;
+ * Statistics required for Link tuning by driver
+ * The rssi value is provided by rt2x00lib during the
+ * link_tuner() callback function.
+ * The false_cca field is filled during the link_stats()
+ * callback function and could be used during the
+ * link_tuner() callback function.
+ */
+ int rssi;
+ int false_cca;
+
+ /*
+ * VGC levels
+ * Hardware driver will tune the VGC level during each call
+ * to the link_tuner() callback function. This vgc_level is
+ * is determined based on the link quality statistics like
+ * average RSSI and the false CCA count.
*
- * The advantage of this approach is that we only need 1 variable
- * to store the average in (No need for a count and a total).
- * But more importantly, normal average values will over time
- * move less and less towards newly added values this results
- * that with link tuning, the device can have a very good RSSI
- * for a few minutes but when the device is moved away from the AP
- * the average will not decrease fast enough to compensate.
- * The walking average compensates this and will move towards
- * the new values correctly allowing a effective link tuning.
+ * In some cases the drivers need to differentiate between
+ * the currently "desired" VGC level and the level configured
+ * in the hardware. The latter is important to reduce the
+ * number of BBP register reads to reduce register access
+ * overhead. For this reason we store both values here.
*/
- int avg_rssi;
- int false_cca;
+ u8 vgc_level;
+ u8 vgc_level_reg;
/*
* Statistics required for Signal quality calculation.
- * For calculating the Signal quality we have to determine
- * the total number of success and failed RX and TX frames.
- * After that we also use the average RSSI value to help
- * determining the signal quality.
- * For the calculation we will use the following algorithm:
- *
- * rssi_percentage = (avg_rssi * 100) / rssi_offset
- * rx_percentage = (rx_success * 100) / rx_total
- * tx_percentage = (tx_success * 100) / tx_total
- * avg_signal = ((WEIGHT_RSSI * avg_rssi) +
- * (WEIGHT_TX * tx_percentage) +
- * (WEIGHT_RX * rx_percentage)) / 100
- *
- * This value should then be checked to not be greater then 100.
+ * These fields might be changed during the link_stats()
+ * callback function.
*/
- int rx_percentage;
int rx_success;
int rx_failed;
- int tx_percentage;
int tx_success;
int tx_failed;
-#define WEIGHT_RSSI 20
-#define WEIGHT_RX 40
-#define WEIGHT_TX 40
};
/*
struct link_ant ant;
/*
- * Active VGC level (for false cca tuning)
+ * Currently active average RSSI value
*/
- u8 vgc_level;
+ int avg_rssi;
/*
- * VGC level as configured in register
+ * Currently precalculated percentages of successful
+ * TX and RX frames.
*/
- u8 vgc_level_reg;
+ int rx_percentage;
+ int tx_percentage;
/*
* Work structure for scheduling periodic link tuning.
struct delayed_work work;
};
-/*
- * Small helper macro to work with moving/walking averages.
- */
-#define MOVING_AVERAGE(__avg, __val, __samples) \
- ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
-
-/*
- * When we lack RSSI information return something less then -80 to
- * tell the driver to tune the device to maximum sensitivity.
- */
-#define DEFAULT_RSSI ( -128 )
-
-/*
- * Link quality access functions.
- */
-static inline int rt2x00_get_link_rssi(struct link *link)
-{
- if (link->qual.avg_rssi && link->qual.rx_success)
- return link->qual.avg_rssi;
- return DEFAULT_RSSI;
-}
-
/*
* Interface structure
* Per interface configuration details, this structure
int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev);
void (*link_stats) (struct rt2x00_dev *rt2x00dev,
struct link_qual *qual);
- void (*reset_tuner) (struct rt2x00_dev *rt2x00dev);
- void (*link_tuner) (struct rt2x00_dev *rt2x00dev);
+ void (*reset_tuner) (struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual);
+ void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, const u32 count);
/*
* TX control handlers
#include "rt2x00.h"
#include "rt2x00lib.h"
+/*
+ * When we lack RSSI information return something less then -80 to
+ * tell the driver to tune the device to maximum sensitivity.
+ */
+#define DEFAULT_RSSI -128
+
+/*
+ * When no TX/RX percentage could be calculated due to lack of
+ * frames on the air, we fallback to a percentage of 50%.
+ * This will assure we will get at least get some decent value
+ * when the link tuner starts.
+ * The value will be dropped and overwritten with the correct (measured)
+ * value anyway during the first run of the link tuner.
+ */
+#define DEFAULT_PERCENTAGE 50
+
+/*
+ * Small helper macro to work with moving/walking averages.
+ * When adding a value to the average value the following calculation
+ * is needed:
+ *
+ * avg_rssi = ((avg_rssi * 7) + rssi) / 8;
+ *
+ * The advantage of this approach is that we only need 1 variable
+ * to store the average in (No need for a count and a total).
+ * But more importantly, normal average values will over time
+ * move less and less towards newly added values this results
+ * that with link tuning, the device can have a very good RSSI
+ * for a few minutes but when the device is moved away from the AP
+ * the average will not decrease fast enough to compensate.
+ * The walking average compensates this and will move towards
+ * the new values correctly allowing a effective link tuning.
+ */
+#define MOVING_AVERAGE(__avg, __val, __samples) \
+ ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
+
+/*
+ * Small helper macro for percentage calculation
+ * This is a very simple macro with the only catch that it will
+ * produce a default value in case no total value was provided.
+ */
+#define PERCENTAGE(__value, __total) \
+ ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
+
+/*
+ * For calculating the Signal quality we have determined
+ * the total number of success and failed RX and TX frames.
+ * With the addition of the average RSSI value we can determine
+ * the link quality using the following algorithm:
+ *
+ * rssi_percentage = (avg_rssi * 100) / rssi_offset
+ * rx_percentage = (rx_success * 100) / rx_total
+ * tx_percentage = (tx_success * 100) / tx_total
+ * avg_signal = ((WEIGHT_RSSI * avg_rssi) +
+ * (WEIGHT_TX * tx_percentage) +
+ * (WEIGHT_RX * rx_percentage)) / 100
+ *
+ * This value should then be checked to not be greater then 100.
+ * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must
+ * sum up to 100 as well.
+ */
+#define WEIGHT_RSSI 20
+#define WEIGHT_RX 40
+#define WEIGHT_TX 40
+
static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
{
struct link_ant *ant = &rt2x00dev->link.ant;
struct sk_buff *skb,
struct rxdone_entry_desc *rxdesc)
{
+ struct link *link = &rt2x00dev->link;
struct link_qual *qual = &rt2x00dev->link.qual;
struct link_ant *ant = &rt2x00dev->link.ant;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
/*
* Update global RSSI
*/
- if (qual->avg_rssi)
- avg_rssi = MOVING_AVERAGE(qual->avg_rssi, rxdesc->rssi, 8);
- qual->avg_rssi = avg_rssi;
+ if (link->avg_rssi)
+ avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8);
+ link->avg_rssi = avg_rssi;
/*
* Update antenna RSSI
static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
{
+ struct link *link = &rt2x00dev->link;
struct link_qual *qual = &rt2x00dev->link.qual;
- if (qual->rx_failed || qual->rx_success)
- qual->rx_percentage =
- (qual->rx_success * 100) /
- (qual->rx_failed + qual->rx_success);
- else
- qual->rx_percentage = 50;
-
- if (qual->tx_failed || qual->tx_success)
- qual->tx_percentage =
- (qual->tx_success * 100) /
- (qual->tx_failed + qual->tx_success);
- else
- qual->tx_percentage = 50;
+ link->rx_percentage =
+ PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success);
+ link->tx_percentage =
+ PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success);
qual->rx_success = 0;
qual->rx_failed = 0;
int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi)
{
- struct link_qual *qual = &rt2x00dev->link.qual;
+ struct link *link = &rt2x00dev->link;
int rssi_percentage = 0;
int signal;
* Calculate the different percentages,
* which will be used for the signal.
*/
- rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset;
+ rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset);
/*
* Add the individual percentages and use the WEIGHT
* defines to calculate the current link signal.
*/
signal = ((WEIGHT_RSSI * rssi_percentage) +
- (WEIGHT_TX * qual->tx_percentage) +
- (WEIGHT_RX * qual->rx_percentage)) / 100;
+ (WEIGHT_TX * link->tx_percentage) +
+ (WEIGHT_RX * link->rx_percentage)) / 100;
return max_t(int, signal, 100);
}
void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
{
- struct link_qual *qual = &rt2x00dev->link.qual;
+ struct link *link = &rt2x00dev->link;
/*
* Link tuning should only be performed when
if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
return;
- /*
- * Clear all (possibly) pre-existing quality statistics.
- */
- memset(qual, 0, sizeof(*qual));
-
- /*
- * The RX and TX percentage should start at 50%
- * this will assure we will get at least get some
- * decent value when the link tuner starts.
- * The value will be dropped and overwritten with
- * the correct (measured) value anyway during the
- * first run of the link tuner.
- */
- qual->rx_percentage = 50;
- qual->tx_percentage = 50;
+ link->rx_percentage = DEFAULT_PERCENTAGE;
+ link->tx_percentage = DEFAULT_PERCENTAGE;
rt2x00link_reset_tuner(rt2x00dev, false);
queue_delayed_work(rt2x00dev->hw->workqueue,
- &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
+ &link->work, LINK_TUNE_INTERVAL);
}
void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
{
+ struct link_qual *qual = &rt2x00dev->link.qual;
+
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
* first minute after being enabled.
*/
rt2x00dev->link.count = 0;
- rt2x00dev->link.vgc_level = 0;
+ memset(qual, 0, sizeof(*qual));
/*
* Reset the link tuner.
*/
- rt2x00dev->ops->lib->reset_tuner(rt2x00dev);
+ rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
if (antenna)
rt2x00link_antenna_reset(rt2x00dev);
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, link.work.work);
+ struct link *link = &rt2x00dev->link;
struct link_qual *qual = &rt2x00dev->link.qual;
/*
rt2x00dev->ops->lib->link_stats(rt2x00dev, qual);
rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
+ /*
+ * Update quality RSSI for link tuning,
+ * when we have received some frames and we managed to
+ * collect the RSSI data we could use this. Otherwise we
+ * must fallback to the default RSSI value.
+ */
+ if (!link->avg_rssi || !qual->rx_success)
+ qual->rssi = DEFAULT_RSSI;
+ else
+ qual->rssi = link->avg_rssi;
+
/*
* Only perform the link tuning when Link tuning
* has been enabled (This could have been disabled from the EEPROM).
*/
if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
- rt2x00dev->ops->lib->link_tuner(rt2x00dev);
+ rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
/*
* Precalculate a portion of the link signal which is
/*
* Send a signal to the led to update the led signal strength.
*/
- rt2x00leds_led_quality(rt2x00dev, qual->avg_rssi);
+ rt2x00leds_led_quality(rt2x00dev, link->avg_rssi);
/*
* Evaluate antenna setup, make this the last step since this could
/*
* Increase tuner counter, and reschedule the next link tuner run.
*/
- rt2x00dev->link.count++;
+ link->count++;
queue_delayed_work(rt2x00dev->hw->workqueue,
- &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
+ &link->work, LINK_TUNE_INTERVAL);
}
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
-static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, u8 vgc_level)
{
- if (rt2x00dev->link.vgc_level != vgc_level) {
+ if (qual->vgc_level != vgc_level) {
rt61pci_bbp_write(rt2x00dev, 17, vgc_level);
- rt2x00dev->link.vgc_level = vgc_level;
- rt2x00dev->link.vgc_level_reg = vgc_level;
+ qual->vgc_level = vgc_level;
+ qual->vgc_level_reg = vgc_level;
}
}
-static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
- rt61pci_set_vgc(rt2x00dev, 0x20);
+ rt61pci_set_vgc(rt2x00dev, qual, 0x20);
}
-static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, const u32 count)
{
- struct link *link = &rt2x00dev->link;
- int rssi = rt2x00_get_link_rssi(link);
u8 up_bound;
u8 low_bound;
/*
* Special big-R17 for very short distance
*/
- if (rssi >= -35) {
- rt61pci_set_vgc(rt2x00dev, 0x60);
+ if (qual->rssi >= -35) {
+ rt61pci_set_vgc(rt2x00dev, qual, 0x60);
return;
}
/*
* Special big-R17 for short distance
*/
- if (rssi >= -58) {
- rt61pci_set_vgc(rt2x00dev, up_bound);
+ if (qual->rssi >= -58) {
+ rt61pci_set_vgc(rt2x00dev, qual, up_bound);
return;
}
/*
* Special big-R17 for middle-short distance
*/
- if (rssi >= -66) {
- rt61pci_set_vgc(rt2x00dev, low_bound + 0x10);
+ if (qual->rssi >= -66) {
+ rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10);
return;
}
/*
* Special mid-R17 for middle distance
*/
- if (rssi >= -74) {
- rt61pci_set_vgc(rt2x00dev, low_bound + 0x08);
+ if (qual->rssi >= -74) {
+ rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08);
return;
}
* Special case: Change up_bound based on the rssi.
* Lower up_bound when rssi is weaker then -74 dBm.
*/
- up_bound -= 2 * (-74 - rssi);
+ up_bound -= 2 * (-74 - qual->rssi);
if (low_bound > up_bound)
up_bound = low_bound;
- if (link->vgc_level > up_bound) {
- rt61pci_set_vgc(rt2x00dev, up_bound);
+ if (qual->vgc_level > up_bound) {
+ rt61pci_set_vgc(rt2x00dev, qual, up_bound);
return;
}
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
*/
- if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound))
- rt61pci_set_vgc(rt2x00dev, ++link->vgc_level);
- else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound))
- rt61pci_set_vgc(rt2x00dev, --link->vgc_level);
+ if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
+ rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+ else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
+ rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
}
/*
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
-static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, u8 vgc_level)
{
- if (rt2x00dev->link.vgc_level != vgc_level) {
+ if (qual->vgc_level != vgc_level) {
rt73usb_bbp_write(rt2x00dev, 17, vgc_level);
- rt2x00dev->link.vgc_level = vgc_level;
- rt2x00dev->link.vgc_level_reg = vgc_level;
+ qual->vgc_level = vgc_level;
+ qual->vgc_level_reg = vgc_level;
}
}
-static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
- rt73usb_set_vgc(rt2x00dev, 0x20);
+ rt73usb_set_vgc(rt2x00dev, qual, 0x20);
}
-static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, const u32 count)
{
- struct link *link = &rt2x00dev->link;
- int rssi = rt2x00_get_link_rssi(link);
u8 up_bound;
u8 low_bound;
up_bound += 0x10;
}
} else {
- if (rssi > -82) {
+ if (qual->rssi > -82) {
low_bound = 0x1c;
up_bound = 0x40;
- } else if (rssi > -84) {
+ } else if (qual->rssi > -84) {
low_bound = 0x1c;
up_bound = 0x20;
} else {
/*
* Special big-R17 for very short distance
*/
- if (rssi > -35) {
- rt73usb_set_vgc(rt2x00dev, 0x60);
+ if (qual->rssi > -35) {
+ rt73usb_set_vgc(rt2x00dev, qual, 0x60);
return;
}
/*
* Special big-R17 for short distance
*/
- if (rssi >= -58) {
- rt73usb_set_vgc(rt2x00dev, up_bound);
+ if (qual->rssi >= -58) {
+ rt73usb_set_vgc(rt2x00dev, qual, up_bound);
return;
}
/*
* Special big-R17 for middle-short distance
*/
- if (rssi >= -66) {
- rt73usb_set_vgc(rt2x00dev, low_bound + 0x10);
+ if (qual->rssi >= -66) {
+ rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10);
return;
}
/*
* Special mid-R17 for middle distance
*/
- if (rssi >= -74) {
- rt73usb_set_vgc(rt2x00dev, low_bound + 0x08);
+ if (qual->rssi >= -74) {
+ rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08);
return;
}
* Special case: Change up_bound based on the rssi.
* Lower up_bound when rssi is weaker then -74 dBm.
*/
- up_bound -= 2 * (-74 - rssi);
+ up_bound -= 2 * (-74 - qual->rssi);
if (low_bound > up_bound)
up_bound = low_bound;
- if (link->vgc_level > up_bound) {
- rt73usb_set_vgc(rt2x00dev, up_bound);
+ if (qual->vgc_level > up_bound) {
+ rt73usb_set_vgc(rt2x00dev, qual, up_bound);
return;
}
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
*/
- if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound))
- rt73usb_set_vgc(rt2x00dev,
- min_t(u8, link->vgc_level + 4, up_bound));
- else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound))
- rt73usb_set_vgc(rt2x00dev,
- max_t(u8, link->vgc_level - 4, low_bound));
+ if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
+ rt73usb_set_vgc(rt2x00dev, qual,
+ min_t(u8, qual->vgc_level + 4, up_bound));
+ else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
+ rt73usb_set_vgc(rt2x00dev, qual,
+ max_t(u8, qual->vgc_level - 4, low_bound));
}
/*