static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) { enum antenna rx = rt2x00dev->link.ant.active.rx; enum antenna tx = rt2x00dev->link.ant.active.tx; int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link); int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr); /* * Legacy driver indicates that we should swap antenna's * when the difference in RSSI is greater that 5. This * also should be done when the RSSI was actually better * then the previous sample. * When the difference exceeds the threshold we should * sample the rssi from the other antenna to make a valid * comparison between the 2 antennas. */ if (abs(rssi_curr - rssi_old) < 5) return; rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) rx = (rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) tx = (tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; rt2x00lib_config_antenna(rt2x00dev, rx, tx); }
static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) { enum antenna rx = rt2x00dev->link.ant.active.rx; enum antenna tx = rt2x00dev->link.ant.active.tx; int sample_a = rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A); int sample_b = rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B); /* * We are done sampling. Now we should evaluate the results. */ rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE; /* * During the last period we have sampled the RSSI * from both antenna's. It now is time to determine * which antenna demonstrated the best performance. * When we are already on the antenna with the best * performance, then there really is nothing for us * left to do. */ if (sample_a == sample_b) return; if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; rt2x00lib_config_antenna(rt2x00dev, rx, tx); }
int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { struct rt2x00_dev *rt2x00dev = hw->priv; struct link_ant *ant = &rt2x00dev->link.ant; struct antenna_setup *def = &rt2x00dev->default_ant; struct antenna_setup setup; // The antenna value is not supposed to be 0, // or exceed the maximum number of antenna's. if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3)) return -EINVAL; // When the client tried to configure the antenna to or from // diversity mode, we must reset the default antenna as well // as that controls the diversity switch. if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3) ant->flags &= ~ANTENNA_TX_DIVERSITY; if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3) ant->flags &= ~ANTENNA_RX_DIVERSITY; // If diversity is being enabled, check if we need hardware // or software diversity. In the latter case, reset the value, // and make sure we update the antenna flags to have the // link tuner pick up the diversity tuning. if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) { tx_ant = ANTENNA_SW_DIVERSITY; ant->flags |= ANTENNA_TX_DIVERSITY; } if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) { rx_ant = ANTENNA_SW_DIVERSITY; ant->flags |= ANTENNA_RX_DIVERSITY; } setup.tx = tx_ant; setup.rx = rx_ant; setup.rx_chain_num = 0; setup.tx_chain_num = 0; rt2x00lib_config_antenna(rt2x00dev, setup); return 0; }
int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) { struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_conf *conf = &hw->conf; /* * mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; /* * Some configuration parameters (e.g. channel and antenna values) can * only be set when the radio is enabled, but do require the RX to * be off. During this period we should keep link tuning enabled, * if for any reason the link tuner must be reset, this will be * handled by rt2x00lib_config(). */ rt2x00queue_stop_queue(rt2x00dev->rx); /* * When we've just turned on the radio, we want to reprogram * everything to ensure a consistent state */ rt2x00lib_config(rt2x00dev, conf, changed); /* * After the radio has been enabled we need to configure * the antenna to the default settings. rt2x00lib_config_antenna() * should determine if any action should be taken based on * checking if diversity has been enabled or no antenna changes * have been made since the last configuration change. */ rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); /* Turn RX back on */ rt2x00queue_start_queue(rt2x00dev->rx); return 0; }
static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) { struct link_ant *ant = &rt2x00dev->link.ant; struct antenna_setup new_ant; int other_antenna; int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev); int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev); memcpy(&new_ant, &ant->active, sizeof(new_ant)); /* * We are done sampling. Now we should evaluate the results. */ ant->flags &= ~ANTENNA_MODE_SAMPLE; /* * During the last period we have sampled the RSSI * from both antennas. It now is time to determine * which antenna demonstrated the best performance. * When we are already on the antenna with the best * performance, just create a good starting point * for the history and we are done. */ if (sample_current >= sample_other) { rt2x00link_antenna_update_rssi_history(rt2x00dev, sample_current); return; } other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; if (ant->flags & ANTENNA_RX_DIVERSITY) new_ant.rx = other_antenna; if (ant->flags & ANTENNA_TX_DIVERSITY) new_ant.tx = other_antenna; rt2x00lib_config_antenna(rt2x00dev, new_ant); }
static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev) { struct link_ant *ant = &rt2x00dev->link.ant; struct antenna_setup new_ant; int rssi_curr; int rssi_old; memcpy(&new_ant, &ant->active, sizeof(new_ant)); /* * Get current RSSI value along with the historical value, * after that update the history with the current value. */ rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev); rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev); rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr); /* * Legacy driver indicates that we should swap antenna's * when the difference in RSSI is greater that 5. This * also should be done when the RSSI was actually better * then the previous sample. * When the difference exceeds the threshold we should * sample the rssi from the other antenna to make a valid * comparison between the 2 antennas. */ if (abs(rssi_curr - rssi_old) < 5) return; ant->flags |= ANTENNA_MODE_SAMPLE; if (ant->flags & ANTENNA_RX_DIVERSITY) new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; if (ant->flags & ANTENNA_TX_DIVERSITY) new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; rt2x00lib_config_antenna(rt2x00dev, new_ant); }