root/drivers/net/wireless/ralink/rt2x00/rt2x00config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rt2x00lib_config_intf
  2. rt2x00lib_config_erp
  3. rt2x00lib_config_antenna
  4. rt2x00ht_center_channel
  5. rt2x00lib_config

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3         Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
   4         <http://rt2x00.serialmonkey.com>
   5 
   6  */
   7 
   8 /*
   9         Module: rt2x00lib
  10         Abstract: rt2x00 generic configuration routines.
  11  */
  12 
  13 #include <linux/kernel.h>
  14 #include <linux/module.h>
  15 
  16 #include "rt2x00.h"
  17 #include "rt2x00lib.h"
  18 
  19 void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
  20                            struct rt2x00_intf *intf,
  21                            enum nl80211_iftype type,
  22                            const u8 *mac, const u8 *bssid)
  23 {
  24         struct rt2x00intf_conf conf;
  25         unsigned int flags = 0;
  26 
  27         conf.type = type;
  28 
  29         switch (type) {
  30         case NL80211_IFTYPE_ADHOC:
  31                 conf.sync = TSF_SYNC_ADHOC;
  32                 break;
  33         case NL80211_IFTYPE_AP:
  34         case NL80211_IFTYPE_MESH_POINT:
  35         case NL80211_IFTYPE_WDS:
  36                 conf.sync = TSF_SYNC_AP_NONE;
  37                 break;
  38         case NL80211_IFTYPE_STATION:
  39                 conf.sync = TSF_SYNC_INFRA;
  40                 break;
  41         default:
  42                 conf.sync = TSF_SYNC_NONE;
  43                 break;
  44         }
  45 
  46         /*
  47          * Note that when NULL is passed as address we will send
  48          * 00:00:00:00:00 to the device to clear the address.
  49          * This will prevent the device being confused when it wants
  50          * to ACK frames or considers itself associated.
  51          */
  52         memset(conf.mac, 0, sizeof(conf.mac));
  53         if (mac)
  54                 memcpy(conf.mac, mac, ETH_ALEN);
  55 
  56         memset(conf.bssid, 0, sizeof(conf.bssid));
  57         if (bssid)
  58                 memcpy(conf.bssid, bssid, ETH_ALEN);
  59 
  60         flags |= CONFIG_UPDATE_TYPE;
  61         if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
  62                 flags |= CONFIG_UPDATE_MAC;
  63         if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
  64                 flags |= CONFIG_UPDATE_BSSID;
  65 
  66         rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
  67 }
  68 
  69 void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
  70                           struct rt2x00_intf *intf,
  71                           struct ieee80211_bss_conf *bss_conf,
  72                           u32 changed)
  73 {
  74         struct rt2x00lib_erp erp;
  75 
  76         memset(&erp, 0, sizeof(erp));
  77 
  78         erp.short_preamble = bss_conf->use_short_preamble;
  79         erp.cts_protection = bss_conf->use_cts_prot;
  80 
  81         erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME;
  82         erp.sifs = SIFS;
  83         erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS;
  84         erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
  85         erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
  86 
  87         erp.basic_rates = bss_conf->basic_rates;
  88         erp.beacon_int = bss_conf->beacon_int;
  89 
  90         /* Update the AID, this is needed for dynamic PS support */
  91         rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
  92         rt2x00dev->last_beacon = bss_conf->sync_tsf;
  93 
  94         /* Update global beacon interval time, this is needed for PS support */
  95         rt2x00dev->beacon_int = bss_conf->beacon_int;
  96 
  97         if (changed & BSS_CHANGED_HT)
  98                 erp.ht_opmode = bss_conf->ht_operation_mode;
  99 
 100         rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
 101 }
 102 
 103 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 104                               struct antenna_setup config)
 105 {
 106         struct link_ant *ant = &rt2x00dev->link.ant;
 107         struct antenna_setup *def = &rt2x00dev->default_ant;
 108         struct antenna_setup *active = &rt2x00dev->link.ant.active;
 109 
 110         /*
 111          * When the caller tries to send the SW diversity,
 112          * we must update the ANTENNA_RX_DIVERSITY flag to
 113          * enable the antenna diversity in the link tuner.
 114          *
 115          * Secondly, we must guarentee we never send the
 116          * software antenna diversity command to the driver.
 117          */
 118         if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
 119                 if (config.rx == ANTENNA_SW_DIVERSITY) {
 120                         ant->flags |= ANTENNA_RX_DIVERSITY;
 121 
 122                         if (def->rx == ANTENNA_SW_DIVERSITY)
 123                                 config.rx = ANTENNA_B;
 124                         else
 125                                 config.rx = def->rx;
 126                 }
 127         } else if (config.rx == ANTENNA_SW_DIVERSITY)
 128                 config.rx = active->rx;
 129 
 130         if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
 131                 if (config.tx == ANTENNA_SW_DIVERSITY) {
 132                         ant->flags |= ANTENNA_TX_DIVERSITY;
 133 
 134                         if (def->tx == ANTENNA_SW_DIVERSITY)
 135                                 config.tx = ANTENNA_B;
 136                         else
 137                                 config.tx = def->tx;
 138                 }
 139         } else if (config.tx == ANTENNA_SW_DIVERSITY)
 140                 config.tx = active->tx;
 141 
 142         /*
 143          * Antenna setup changes require the RX to be disabled,
 144          * else the changes will be ignored by the device.
 145          */
 146         if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 147                 rt2x00queue_stop_queue(rt2x00dev->rx);
 148 
 149         /*
 150          * Write new antenna setup to device and reset the link tuner.
 151          * The latter is required since we need to recalibrate the
 152          * noise-sensitivity ratio for the new setup.
 153          */
 154         rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);
 155 
 156         rt2x00link_reset_tuner(rt2x00dev, true);
 157 
 158         memcpy(active, &config, sizeof(config));
 159 
 160         if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 161                 rt2x00queue_start_queue(rt2x00dev->rx);
 162 }
 163 
 164 static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
 165                                    struct ieee80211_conf *conf)
 166 {
 167         struct hw_mode_spec *spec = &rt2x00dev->spec;
 168         int center_channel;
 169         u16 i;
 170 
 171         /*
 172          * Initialize center channel to current channel.
 173          */
 174         center_channel = spec->channels[conf->chandef.chan->hw_value].channel;
 175 
 176         /*
 177          * Adjust center channel to HT40+ and HT40- operation.
 178          */
 179         if (conf_is_ht40_plus(conf))
 180                 center_channel += 2;
 181         else if (conf_is_ht40_minus(conf))
 182                 center_channel -= (center_channel == 14) ? 1 : 2;
 183 
 184         for (i = 0; i < spec->num_channels; i++)
 185                 if (spec->channels[i].channel == center_channel)
 186                         return i;
 187 
 188         WARN_ON(1);
 189         return conf->chandef.chan->hw_value;
 190 }
 191 
 192 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 193                       struct ieee80211_conf *conf,
 194                       unsigned int ieee80211_flags)
 195 {
 196         struct rt2x00lib_conf libconf;
 197         u16 hw_value;
 198         u16 autowake_timeout;
 199         u16 beacon_int;
 200         u16 beacon_diff;
 201 
 202         memset(&libconf, 0, sizeof(libconf));
 203 
 204         libconf.conf = conf;
 205 
 206         if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 207                 if (!conf_is_ht(conf))
 208                         set_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags);
 209                 else
 210                         clear_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags);
 211 
 212                 if (conf_is_ht40(conf)) {
 213                         set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 214                         hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
 215                 } else {
 216                         clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 217                         hw_value = conf->chandef.chan->hw_value;
 218                 }
 219 
 220                 memcpy(&libconf.rf,
 221                        &rt2x00dev->spec.channels[hw_value],
 222                        sizeof(libconf.rf));
 223 
 224                 memcpy(&libconf.channel,
 225                        &rt2x00dev->spec.channels_info[hw_value],
 226                        sizeof(libconf.channel));
 227 
 228                 /* Used for VCO periodic calibration */
 229                 rt2x00dev->rf_channel = libconf.rf.channel;
 230         }
 231 
 232         if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) &&
 233             (ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
 234                 cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
 235 
 236         /*
 237          * Start configuration.
 238          */
 239         rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
 240 
 241         if (conf->flags & IEEE80211_CONF_PS)
 242                 set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
 243         else
 244                 clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
 245 
 246         if (conf->flags & IEEE80211_CONF_MONITOR)
 247                 set_bit(CONFIG_MONITORING, &rt2x00dev->flags);
 248         else
 249                 clear_bit(CONFIG_MONITORING, &rt2x00dev->flags);
 250 
 251         rt2x00dev->curr_band = conf->chandef.chan->band;
 252         rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
 253         rt2x00dev->tx_power = conf->power_level;
 254         rt2x00dev->short_retry = conf->short_frame_max_tx_count;
 255         rt2x00dev->long_retry = conf->long_frame_max_tx_count;
 256 
 257         /*
 258          * Some configuration changes affect the link quality
 259          * which means we need to reset the link tuner.
 260          */
 261         if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
 262                 rt2x00link_reset_tuner(rt2x00dev, false);
 263 
 264         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
 265             rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) &&
 266             (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
 267             (conf->flags & IEEE80211_CONF_PS)) {
 268                 beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
 269                 beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int);
 270 
 271                 if (beacon_diff > beacon_int)
 272                         beacon_diff = 0;
 273 
 274                 autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff;
 275                 queue_delayed_work(rt2x00dev->workqueue,
 276                                    &rt2x00dev->autowakeup_work,
 277                                    autowake_timeout - 15);
 278         }
 279 }

/* [<][>][^][v][top][bottom][index][help] */