linux/drivers/net/wireless/ath/ath9k/common.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2009-2011 Atheros Communications Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17/*
  18 * Module for common driver code between ath9k and ath9k_htc
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23
  24#include "common.h"
  25
  26MODULE_AUTHOR("Atheros Communications");
  27MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
  28MODULE_LICENSE("Dual BSD/GPL");
  29
  30int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
  31{
  32        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
  33
  34        if (tx_info->control.hw_key) {
  35                switch (tx_info->control.hw_key->cipher) {
  36                case WLAN_CIPHER_SUITE_WEP40:
  37                case WLAN_CIPHER_SUITE_WEP104:
  38                        return ATH9K_KEY_TYPE_WEP;
  39                case WLAN_CIPHER_SUITE_TKIP:
  40                        return ATH9K_KEY_TYPE_TKIP;
  41                case WLAN_CIPHER_SUITE_CCMP:
  42                        return ATH9K_KEY_TYPE_AES;
  43                default:
  44                        break;
  45                }
  46        }
  47
  48        return ATH9K_KEY_TYPE_CLEAR;
  49}
  50EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
  51
  52static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef)
  53{
  54        u32 chanmode = 0;
  55
  56        switch (chandef->chan->band) {
  57        case IEEE80211_BAND_2GHZ:
  58                switch (chandef->width) {
  59                case NL80211_CHAN_WIDTH_20_NOHT:
  60                case NL80211_CHAN_WIDTH_20:
  61                        chanmode = CHANNEL_G_HT20;
  62                        break;
  63                case NL80211_CHAN_WIDTH_40:
  64                        if (chandef->center_freq1 > chandef->chan->center_freq)
  65                                chanmode = CHANNEL_G_HT40PLUS;
  66                        else
  67                                chanmode = CHANNEL_G_HT40MINUS;
  68                        break;
  69                default:
  70                        break;
  71                }
  72                break;
  73        case IEEE80211_BAND_5GHZ:
  74                switch (chandef->width) {
  75                case NL80211_CHAN_WIDTH_20_NOHT:
  76                case NL80211_CHAN_WIDTH_20:
  77                        chanmode = CHANNEL_A_HT20;
  78                        break;
  79                case NL80211_CHAN_WIDTH_40:
  80                        if (chandef->center_freq1 > chandef->chan->center_freq)
  81                                chanmode = CHANNEL_A_HT40PLUS;
  82                        else
  83                                chanmode = CHANNEL_A_HT40MINUS;
  84                        break;
  85                default:
  86                        break;
  87                }
  88                break;
  89        default:
  90                break;
  91        }
  92
  93        return chanmode;
  94}
  95
  96/*
  97 * Update internal channel flags.
  98 */
  99void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
 100                               struct cfg80211_chan_def *chandef)
 101{
 102        ichan->channel = chandef->chan->center_freq;
 103        ichan->chan = chandef->chan;
 104
 105        if (chandef->chan->band == IEEE80211_BAND_2GHZ) {
 106                ichan->chanmode = CHANNEL_G;
 107                ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
 108        } else {
 109                ichan->chanmode = CHANNEL_A;
 110                ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
 111        }
 112
 113        switch (chandef->width) {
 114        case NL80211_CHAN_WIDTH_5:
 115                ichan->channelFlags |= CHANNEL_QUARTER;
 116                break;
 117        case NL80211_CHAN_WIDTH_10:
 118                ichan->channelFlags |= CHANNEL_HALF;
 119                break;
 120        case NL80211_CHAN_WIDTH_20_NOHT:
 121                break;
 122        case NL80211_CHAN_WIDTH_20:
 123        case NL80211_CHAN_WIDTH_40:
 124                ichan->chanmode = ath9k_get_extchanmode(chandef);
 125                break;
 126        default:
 127                WARN_ON(1);
 128        }
 129}
 130EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
 131
 132/*
 133 * Get the internal channel reference.
 134 */
 135struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 136                                               struct ath_hw *ah)
 137{
 138        struct ieee80211_channel *curchan = hw->conf.chandef.chan;
 139        struct ath9k_channel *channel;
 140        u8 chan_idx;
 141
 142        chan_idx = curchan->hw_value;
 143        channel = &ah->channels[chan_idx];
 144        ath9k_cmn_update_ichannel(channel, &hw->conf.chandef);
 145
 146        return channel;
 147}
 148EXPORT_SYMBOL(ath9k_cmn_get_curchannel);
 149
 150int ath9k_cmn_count_streams(unsigned int chainmask, int max)
 151{
 152        int streams = 0;
 153
 154        do {
 155                if (++streams == max)
 156                        break;
 157        } while ((chainmask = chainmask & (chainmask - 1)));
 158
 159        return streams;
 160}
 161EXPORT_SYMBOL(ath9k_cmn_count_streams);
 162
 163void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
 164                            u16 new_txpow, u16 *txpower)
 165{
 166        struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 167
 168        if (reg->power_limit != new_txpow) {
 169                ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
 170                /* read back in case value is clamped */
 171                *txpower = reg->max_power_level;
 172        }
 173}
 174EXPORT_SYMBOL(ath9k_cmn_update_txpow);
 175
 176void ath9k_cmn_init_crypto(struct ath_hw *ah)
 177{
 178        struct ath_common *common = ath9k_hw_common(ah);
 179        int i = 0;
 180
 181        /* Get the hardware key cache size. */
 182        common->keymax = AR_KEYTABLE_SIZE;
 183
 184        /*
 185         * Check whether the separate key cache entries
 186         * are required to handle both tx+rx MIC keys.
 187         * With split mic keys the number of stations is limited
 188         * to 27 otherwise 59.
 189         */
 190        if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
 191                common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
 192
 193        /*
 194         * Reset the key cache since some parts do not
 195         * reset the contents on initial power up.
 196         */
 197        for (i = 0; i < common->keymax; i++)
 198                ath_hw_keyreset(common, (u16) i);
 199}
 200EXPORT_SYMBOL(ath9k_cmn_init_crypto);
 201
 202static int __init ath9k_cmn_init(void)
 203{
 204        return 0;
 205}
 206module_init(ath9k_cmn_init);
 207
 208static void __exit ath9k_cmn_exit(void)
 209{
 210        return;
 211}
 212module_exit(ath9k_cmn_exit);
 213