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; }
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); }
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); }
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; }
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; }
/* * 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; }