linux/drivers/net/wireless/rt2x00/rt2x00config.c
<<
>>
Prefs
   1/*
   2        Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
   3        <http://rt2x00.serialmonkey.com>
   4
   5        This program is free software; you can redistribute it and/or modify
   6        it under the terms of the GNU General Public License as published by
   7        the Free Software Foundation; either version 2 of the License, or
   8        (at your option) any later version.
   9
  10        This program is distributed in the hope that it will be useful,
  11        but WITHOUT ANY WARRANTY; without even the implied warranty of
  12        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13        GNU General Public License for more details.
  14
  15        You should have received a copy of the GNU General Public License
  16        along with this program; if not, write to the
  17        Free Software Foundation, Inc.,
  18        59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19 */
  20
  21/*
  22        Module: rt2x00lib
  23        Abstract: rt2x00 generic configuration routines.
  24 */
  25
  26#include <linux/kernel.h>
  27#include <linux/module.h>
  28
  29#include "rt2x00.h"
  30#include "rt2x00lib.h"
  31
  32void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
  33                           struct rt2x00_intf *intf,
  34                           enum nl80211_iftype type,
  35                           const u8 *mac, const u8 *bssid)
  36{
  37        struct rt2x00intf_conf conf;
  38        unsigned int flags = 0;
  39
  40        conf.type = type;
  41
  42        switch (type) {
  43        case NL80211_IFTYPE_ADHOC:
  44        case NL80211_IFTYPE_AP:
  45        case NL80211_IFTYPE_MESH_POINT:
  46        case NL80211_IFTYPE_WDS:
  47                conf.sync = TSF_SYNC_BEACON;
  48                break;
  49        case NL80211_IFTYPE_STATION:
  50                conf.sync = TSF_SYNC_INFRA;
  51                break;
  52        default:
  53                conf.sync = TSF_SYNC_NONE;
  54                break;
  55        }
  56
  57        /*
  58         * Note that when NULL is passed as address we will send
  59         * 00:00:00:00:00 to the device to clear the address.
  60         * This will prevent the device being confused when it wants
  61         * to ACK frames or consideres itself associated.
  62         */
  63        memset(&conf.mac, 0, sizeof(conf.mac));
  64        if (mac)
  65                memcpy(&conf.mac, mac, ETH_ALEN);
  66
  67        memset(&conf.bssid, 0, sizeof(conf.bssid));
  68        if (bssid)
  69                memcpy(&conf.bssid, bssid, ETH_ALEN);
  70
  71        flags |= CONFIG_UPDATE_TYPE;
  72        if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
  73                flags |= CONFIG_UPDATE_MAC;
  74        if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
  75                flags |= CONFIG_UPDATE_BSSID;
  76
  77        rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
  78}
  79
  80void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
  81                          struct rt2x00_intf *intf,
  82                          struct ieee80211_bss_conf *bss_conf)
  83{
  84        struct rt2x00lib_erp erp;
  85
  86        memset(&erp, 0, sizeof(erp));
  87
  88        erp.short_preamble = bss_conf->use_short_preamble;
  89        erp.cts_protection = bss_conf->use_cts_prot;
  90
  91        erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME;
  92        erp.sifs = SIFS;
  93        erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS;
  94        erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
  95        erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
  96
  97        erp.basic_rates = bss_conf->basic_rates;
  98        erp.beacon_int = bss_conf->beacon_int;
  99
 100        /* Update global beacon interval time, this is needed for PS support */
 101        rt2x00dev->beacon_int = bss_conf->beacon_int;
 102
 103        rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
 104}
 105
 106static inline
 107enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
 108                                            enum antenna default_ant)
 109{
 110        if (current_ant != ANTENNA_SW_DIVERSITY)
 111                return current_ant;
 112        return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
 113}
 114
 115void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 116                              struct antenna_setup config)
 117{
 118        struct link_ant *ant = &rt2x00dev->link.ant;
 119        struct antenna_setup *def = &rt2x00dev->default_ant;
 120        struct antenna_setup *active = &rt2x00dev->link.ant.active;
 121
 122        /*
 123         * Failsafe: Make sure we are not sending the
 124         * ANTENNA_SW_DIVERSITY state to the driver.
 125         * If that happens, fallback to hardware defaults,
 126         * or our own default.
 127         * If diversity handling is active for a particular antenna,
 128         * we shouldn't overwrite that antenna.
 129         * The calls to rt2x00lib_config_antenna_check()
 130         * might have caused that we restore back to the already
 131         * active setting. If that has happened we can quit.
 132         */
 133        if (!(ant->flags & ANTENNA_RX_DIVERSITY))
 134                config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
 135        else
 136                config.rx = active->rx;
 137
 138        if (!(ant->flags & ANTENNA_TX_DIVERSITY))
 139                config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
 140        else
 141                config.tx = active->tx;
 142
 143        if (config.rx == active->rx && config.tx == active->tx)
 144                return;
 145
 146        /*
 147         * Antenna setup changes require the RX to be disabled,
 148         * else the changes will be ignored by the device.
 149         */
 150        if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 151                rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);
 152
 153        /*
 154         * Write new antenna setup to device and reset the link tuner.
 155         * The latter is required since we need to recalibrate the
 156         * noise-sensitivity ratio for the new setup.
 157         */
 158        rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);
 159
 160        rt2x00link_reset_tuner(rt2x00dev, true);
 161
 162        memcpy(active, &config, sizeof(config));
 163
 164        if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 165                rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
 166}
 167
 168void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 169                      struct ieee80211_conf *conf,
 170                      unsigned int ieee80211_flags)
 171{
 172        struct rt2x00lib_conf libconf;
 173
 174        memset(&libconf, 0, sizeof(libconf));
 175
 176        libconf.conf = conf;
 177
 178        if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 179                if (conf_is_ht40(conf))
 180                        __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 181                else
 182                        __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 183
 184                memcpy(&libconf.rf,
 185                       &rt2x00dev->spec.channels[conf->channel->hw_value],
 186                       sizeof(libconf.rf));
 187
 188                memcpy(&libconf.channel,
 189                       &rt2x00dev->spec.channels_info[conf->channel->hw_value],
 190                       sizeof(libconf.channel));
 191        }
 192
 193        /*
 194         * Start configuration.
 195         */
 196        rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
 197
 198        /*
 199         * Some configuration changes affect the link quality
 200         * which means we need to reset the link tuner.
 201         */
 202        if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
 203                rt2x00link_reset_tuner(rt2x00dev, false);
 204
 205        rt2x00dev->curr_band = conf->channel->band;
 206        rt2x00dev->tx_power = conf->power_level;
 207        rt2x00dev->short_retry = conf->short_frame_max_tx_count;
 208        rt2x00dev->long_retry = conf->long_frame_max_tx_count;
 209
 210        rt2x00dev->rx_status.band = conf->channel->band;
 211        rt2x00dev->rx_status.freq = conf->channel->center_freq;
 212}
 213