root/drivers/net/wireless/intersil/orinoco/cfg.c

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

DEFINITIONS

This source file includes following definitions.
  1. orinoco_wiphy_init
  2. orinoco_wiphy_register
  3. orinoco_change_vif
  4. orinoco_scan
  5. orinoco_set_monitor_channel
  6. orinoco_set_wiphy_params

   1 /* cfg80211 support
   2  *
   3  * See copyright notice in main.c
   4  */
   5 #include <linux/ieee80211.h>
   6 #include <net/cfg80211.h>
   7 #include "hw.h"
   8 #include "main.h"
   9 #include "orinoco.h"
  10 
  11 #include "cfg.h"
  12 
  13 /* Supported bitrates. Must agree with hw.c */
  14 static struct ieee80211_rate orinoco_rates[] = {
  15         { .bitrate = 10 },
  16         { .bitrate = 20 },
  17         { .bitrate = 55 },
  18         { .bitrate = 110 },
  19 };
  20 
  21 static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
  22 
  23 /* Called after orinoco_private is allocated. */
  24 void orinoco_wiphy_init(struct wiphy *wiphy)
  25 {
  26         struct orinoco_private *priv = wiphy_priv(wiphy);
  27 
  28         wiphy->privid = orinoco_wiphy_privid;
  29 
  30         set_wiphy_dev(wiphy, priv->dev);
  31 }
  32 
  33 /* Called after firmware is initialised */
  34 int orinoco_wiphy_register(struct wiphy *wiphy)
  35 {
  36         struct orinoco_private *priv = wiphy_priv(wiphy);
  37         int i, channels = 0;
  38 
  39         if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
  40                 wiphy->max_scan_ssids = 1;
  41         else
  42                 wiphy->max_scan_ssids = 0;
  43 
  44         wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
  45 
  46         /* TODO: should we set if we only have demo ad-hoc?
  47          *       (priv->has_port3)
  48          */
  49         if (priv->has_ibss)
  50                 wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
  51 
  52         if (!priv->broken_monitor || force_monitor)
  53                 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
  54 
  55         priv->band.bitrates = orinoco_rates;
  56         priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
  57 
  58         /* Only support channels allowed by the card EEPROM */
  59         for (i = 0; i < NUM_CHANNELS; i++) {
  60                 if (priv->channel_mask & (1 << i)) {
  61                         priv->channels[i].center_freq =
  62                                 ieee80211_channel_to_frequency(i + 1,
  63                                                            NL80211_BAND_2GHZ);
  64                         channels++;
  65                 }
  66         }
  67         priv->band.channels = priv->channels;
  68         priv->band.n_channels = channels;
  69 
  70         wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
  71         wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
  72 
  73         i = 0;
  74         if (priv->has_wep) {
  75                 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
  76                 i++;
  77 
  78                 if (priv->has_big_wep) {
  79                         priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
  80                         i++;
  81                 }
  82         }
  83         if (priv->has_wpa) {
  84                 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
  85                 i++;
  86         }
  87         wiphy->cipher_suites = priv->cipher_suites;
  88         wiphy->n_cipher_suites = i;
  89 
  90         wiphy->rts_threshold = priv->rts_thresh;
  91         if (!priv->has_mwo)
  92                 wiphy->frag_threshold = priv->frag_thresh + 1;
  93         wiphy->retry_short = priv->short_retry_limit;
  94         wiphy->retry_long = priv->long_retry_limit;
  95 
  96         return wiphy_register(wiphy);
  97 }
  98 
  99 static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
 100                               enum nl80211_iftype type,
 101                               struct vif_params *params)
 102 {
 103         struct orinoco_private *priv = wiphy_priv(wiphy);
 104         int err = 0;
 105         unsigned long lock;
 106 
 107         if (orinoco_lock(priv, &lock) != 0)
 108                 return -EBUSY;
 109 
 110         switch (type) {
 111         case NL80211_IFTYPE_ADHOC:
 112                 if (!priv->has_ibss && !priv->has_port3)
 113                         err = -EINVAL;
 114                 break;
 115 
 116         case NL80211_IFTYPE_STATION:
 117                 break;
 118 
 119         case NL80211_IFTYPE_MONITOR:
 120                 if (priv->broken_monitor && !force_monitor) {
 121                         wiphy_warn(wiphy,
 122                                    "Monitor mode support is buggy in this firmware, not enabling\n");
 123                         err = -EINVAL;
 124                 }
 125                 break;
 126 
 127         default:
 128                 err = -EINVAL;
 129         }
 130 
 131         if (!err) {
 132                 priv->iw_mode = type;
 133                 set_port_type(priv);
 134                 err = orinoco_commit(priv);
 135         }
 136 
 137         orinoco_unlock(priv, &lock);
 138 
 139         return err;
 140 }
 141 
 142 static int orinoco_scan(struct wiphy *wiphy,
 143                         struct cfg80211_scan_request *request)
 144 {
 145         struct orinoco_private *priv = wiphy_priv(wiphy);
 146         int err;
 147 
 148         if (!request)
 149                 return -EINVAL;
 150 
 151         if (priv->scan_request && priv->scan_request != request)
 152                 return -EBUSY;
 153 
 154         priv->scan_request = request;
 155 
 156         err = orinoco_hw_trigger_scan(priv, request->ssids);
 157         /* On error the we aren't processing the request */
 158         if (err)
 159                 priv->scan_request = NULL;
 160 
 161         return err;
 162 }
 163 
 164 static int orinoco_set_monitor_channel(struct wiphy *wiphy,
 165                                        struct cfg80211_chan_def *chandef)
 166 {
 167         struct orinoco_private *priv = wiphy_priv(wiphy);
 168         int err = 0;
 169         unsigned long flags;
 170         int channel;
 171 
 172         if (!chandef->chan)
 173                 return -EINVAL;
 174 
 175         if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
 176                 return -EINVAL;
 177 
 178         if (chandef->chan->band != NL80211_BAND_2GHZ)
 179                 return -EINVAL;
 180 
 181         channel = ieee80211_frequency_to_channel(chandef->chan->center_freq);
 182 
 183         if ((channel < 1) || (channel > NUM_CHANNELS) ||
 184              !(priv->channel_mask & (1 << (channel - 1))))
 185                 return -EINVAL;
 186 
 187         if (orinoco_lock(priv, &flags) != 0)
 188                 return -EBUSY;
 189 
 190         priv->channel = channel;
 191         if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 192                 /* Fast channel change - no commit if successful */
 193                 struct hermes *hw = &priv->hw;
 194                 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 195                                             HERMES_TEST_SET_CHANNEL,
 196                                         channel, NULL);
 197         }
 198         orinoco_unlock(priv, &flags);
 199 
 200         return err;
 201 }
 202 
 203 static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 204 {
 205         struct orinoco_private *priv = wiphy_priv(wiphy);
 206         int frag_value = -1;
 207         int rts_value = -1;
 208         int err = 0;
 209 
 210         if (changed & WIPHY_PARAM_RETRY_SHORT) {
 211                 /* Setting short retry not supported */
 212                 err = -EINVAL;
 213         }
 214 
 215         if (changed & WIPHY_PARAM_RETRY_LONG) {
 216                 /* Setting long retry not supported */
 217                 err = -EINVAL;
 218         }
 219 
 220         if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
 221                 /* Set fragmentation */
 222                 if (priv->has_mwo) {
 223                         if (wiphy->frag_threshold == -1)
 224                                 frag_value = 0;
 225                         else {
 226                                 printk(KERN_WARNING "%s: Fixed fragmentation "
 227                                        "is not supported on this firmware. "
 228                                        "Using MWO robust instead.\n",
 229                                        priv->ndev->name);
 230                                 frag_value = 1;
 231                         }
 232                 } else {
 233                         if (wiphy->frag_threshold == -1)
 234                                 frag_value = 2346;
 235                         else if ((wiphy->frag_threshold < 257) ||
 236                                  (wiphy->frag_threshold > 2347))
 237                                 err = -EINVAL;
 238                         else
 239                                 /* cfg80211 value is 257-2347 (odd only)
 240                                  * orinoco rid has range 256-2346 (even only) */
 241                                 frag_value = wiphy->frag_threshold & ~0x1;
 242                 }
 243         }
 244 
 245         if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
 246                 /* Set RTS.
 247                  *
 248                  * Prism documentation suggests default of 2432,
 249                  * and a range of 0-3000.
 250                  *
 251                  * Current implementation uses 2347 as the default and
 252                  * the upper limit.
 253                  */
 254 
 255                 if (wiphy->rts_threshold == -1)
 256                         rts_value = 2347;
 257                 else if (wiphy->rts_threshold > 2347)
 258                         err = -EINVAL;
 259                 else
 260                         rts_value = wiphy->rts_threshold;
 261         }
 262 
 263         if (!err) {
 264                 unsigned long flags;
 265 
 266                 if (orinoco_lock(priv, &flags) != 0)
 267                         return -EBUSY;
 268 
 269                 if (frag_value >= 0) {
 270                         if (priv->has_mwo)
 271                                 priv->mwo_robust = frag_value;
 272                         else
 273                                 priv->frag_thresh = frag_value;
 274                 }
 275                 if (rts_value >= 0)
 276                         priv->rts_thresh = rts_value;
 277 
 278                 err = orinoco_commit(priv);
 279 
 280                 orinoco_unlock(priv, &flags);
 281         }
 282 
 283         return err;
 284 }
 285 
 286 const struct cfg80211_ops orinoco_cfg_ops = {
 287         .change_virtual_intf = orinoco_change_vif,
 288         .set_monitor_channel = orinoco_set_monitor_channel,
 289         .scan = orinoco_scan,
 290         .set_wiphy_params = orinoco_set_wiphy_params,
 291 };

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