cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cfg.c (6673B)


      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 */
     14static struct ieee80211_rate orinoco_rates[] = {
     15	{ .bitrate = 10 },
     16	{ .bitrate = 20 },
     17	{ .bitrate = 55 },
     18	{ .bitrate = 110 },
     19};
     20
     21static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
     22
     23/* Called after orinoco_private is allocated. */
     24void 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 */
     34int 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
     99static 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
    142static 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
    164static 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
    203static 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
    286const 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};