Example #1
0
int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;

	/*
	 * Mac80211 might be calling this function while we are trying
	 * to remove the device or perhaps suspending it.
	 */
	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
		return 0;

	/*
	 * Check if we need to disable the radio,
	 * if this is not the case, at least the RX must be disabled.
	 */
	if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
		if (!conf->radio_enabled)
			rt2x00lib_disable_radio(rt2x00dev);
		else
			rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
	}

	rt2x00lib_config(rt2x00dev, conf, 0);

	/*
	 * Reenable RX only if the radio should be on.
	 */
	if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
	else if (conf->radio_enabled)
		return rt2x00lib_enable_radio(rt2x00dev);

	return 0;
}
Example #2
0
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
                  enum antenna rx, enum antenna tx)
{
    struct rt2x00lib_conf libconf;

    libconf.ant.rx = rx;
    libconf.ant.tx = tx;

    if (rx == rt2x00dev->link.ant.active.rx &&
        tx == rt2x00dev->link.ant.active.tx)
        return;

    /*
     * Antenna setup changes require the RX to be disabled,
     * else the changes will be ignored by the device.
     */
    if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
        rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);

    /*
     * Write new antenna setup to device and reset the link tuner.
     * The latter is required since we need to recalibrate the
     * noise-sensitivity ratio for the new setup.
     */
    rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
    rt2x00lib_reset_link_tuner(rt2x00dev);
    rt2x00_reset_link_ant_rssi(&rt2x00dev->link);

    rt2x00dev->link.ant.active.rx = libconf.ant.rx;
    rt2x00dev->link.ant.active.tx = libconf.ant.tx;

    if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
        rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
}
Example #3
0
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
			      struct antenna_setup config)
{
	struct link_ant *ant = &rt2x00dev->link.ant;
	struct antenna_setup *def = &rt2x00dev->default_ant;
	struct antenna_setup *active = &rt2x00dev->link.ant.active;

	/*
	 * Failsafe: Make sure we are not sending the
	 * ANTENNA_SW_DIVERSITY state to the driver.
	 * If that happens, fallback to hardware defaults,
	 * or our own default.
	 * If diversity handling is active for a particular antenna,
	 * we shouldn't overwrite that antenna.
	 * The calls to rt2x00lib_config_antenna_check()
	 * might have caused that we restore back to the already
	 * active setting. If that has happened we can quit.
	 */
	if (!(ant->flags & ANTENNA_RX_DIVERSITY))
		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
	else
		config.rx = active->rx;

	if (!(ant->flags & ANTENNA_TX_DIVERSITY))
		config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
	else
		config.tx = active->tx;

	if (config.rx == active->rx && config.tx == active->tx)
		return;

	/*
	 * Antenna setup changes require the RX to be disabled,
	 * else the changes will be ignored by the device.
	 */
	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);

	/*
	 * Write new antenna setup to device and reset the link tuner.
	 * The latter is required since we need to recalibrate the
	 * noise-sensitivity ratio for the new setup.
	 */
	rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);

	rt2x00link_reset_tuner(rt2x00dev, true);

	memcpy(active, &config, sizeof(config));

	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
}
Example #4
0
void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
{
	if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
		return;

	/*
	 * Stop the TX queues in mac80211.
	 */
	ieee80211_stop_queues(rt2x00dev->hw);
	rt2x00queue_stop_queues(rt2x00dev);

	/*
	 * Stop watchdog monitoring.
	 */
	rt2x00link_stop_watchdog(rt2x00dev);

	/*
	 * Disable RX.
	 */
	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);

	/*
	 * Disable radio.
	 */
	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF);
	rt2x00led_led_activity(rt2x00dev, false);
	rt2x00leds_led_radio(rt2x00dev, false);
}
int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	int force_reconfig;

	/*
	 * Mac80211 might be calling this function while we are trying
	 * to remove the device or perhaps suspending it.
	 */
	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
		return 0;

	/*
	 * Check if we need to disable the radio,
	 * if this is not the case, at least the RX must be disabled.
	 */
	if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
		if (!conf->radio_enabled)
			rt2x00lib_disable_radio(rt2x00dev);
		else
			rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
	}

	/*
	 * When the DEVICE_DIRTY_CONFIG flag is set, the device has recently
	 * been started and the configuration must be forced upon the hardware.
	 * Otherwise registers will not be intialized correctly and could
	 * result in non-working hardware because essential registers aren't
	 * initialized.
	 */
	force_reconfig =
	    __test_and_clear_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags);

	rt2x00lib_config(rt2x00dev, conf, force_reconfig);

	/*
	 * Reenable RX only if the radio should be on.
	 */
	if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
	else if (conf->radio_enabled)
		return rt2x00lib_enable_radio(rt2x00dev);

	return 0;
}
Example #6
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().
	 */
	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);

	/*
	 * 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 */
	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);

	return 0;
}
Example #7
0
/*
 * Radio control handlers.
 */
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
{
	int status;

	/*
	 * Don't enable the radio twice.
	 * And check if the hardware button has been disabled.
	 */
	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
		return 0;

	/*
	 * Initialize all data queues.
	 */
	rt2x00queue_init_queues(rt2x00dev);

	/*
	 * Enable radio.
	 */
	status =
	    rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON);
	if (status)
		return status;

	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON);

	rt2x00leds_led_radio(rt2x00dev, true);
	rt2x00led_led_activity(rt2x00dev, true);

	set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);

	/*
	 * Enable RX.
	 */
	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);

	/*
	 * Start watchdog monitoring.
	 */
	rt2x00link_start_watchdog(rt2x00dev);

	/*
	 * Start the TX queues.
	 */
	ieee80211_wake_queues(rt2x00dev->hw);

	return 0;
}