diff --git a/ath.h b/ath.h index f02a308a9ffc..34654f710d8a 100644 --- a/ath.h +++ b/ath.h @@ -1,337 +1,339 @@ /* * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef ATH_H #define ATH_H #include #include #include #include #include /* * The key cache is used for h/w cipher state and also for * tracking station state such as the current tx antenna. * We also setup a mapping table between key cache slot indices * and station state to short-circuit node lookups on rx. * Different parts have different size key caches. We handle * up to ATH_KEYMAX entries (could dynamically allocate state). */ #define ATH_KEYMAX 128 /* max key cache size we handle */ struct ath_ani { bool caldone; unsigned int longcal_timer; unsigned int shortcal_timer; unsigned int resetcal_timer; unsigned int checkani_timer; struct timer_list timer; }; struct ath_cycle_counters { u32 cycles; u32 rx_busy; u32 rx_frame; u32 tx_frame; }; enum ath_device_state { ATH_HW_UNAVAILABLE, ATH_HW_INITIALIZED, }; enum ath_op_flags { ATH_OP_INVALID, ATH_OP_BEACONS, ATH_OP_ANI_RUN, ATH_OP_PRIM_STA_VIF, ATH_OP_HW_RESET, ATH_OP_SCANNING, ATH_OP_MULTI_CHANNEL, ATH_OP_WOW_ENABLED, }; enum ath_bus_type { ATH_PCI, ATH_AHB, ATH_USB, }; struct reg_dmn_pair_mapping { u16 reg_domain; u16 reg_5ghz_ctl; u16 reg_2ghz_ctl; }; struct ath_regulatory { char alpha2[2]; enum nl80211_dfs_regions region; u16 country_code; u16 max_power_level; u16 current_rd; int16_t power_limit; struct reg_dmn_pair_mapping *regpair; }; enum ath_crypt_caps { ATH_CRYPT_CAP_CIPHER_AESCCM = BIT(0), ATH_CRYPT_CAP_MIC_COMBINED = BIT(1), }; struct ath_keyval { u8 kv_type; u8 kv_pad; u16 kv_len; struct_group(kv_values, u8 kv_val[16]; /* TK */ u8 kv_mic[8]; /* Michael MIC key */ u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware * supports both MIC keys in the same key cache entry; * in that case, kv_mic is the RX key) */ ); }; enum ath_cipher { ATH_CIPHER_WEP = 0, ATH_CIPHER_AES_OCB = 1, ATH_CIPHER_AES_CCM = 2, ATH_CIPHER_CKIP = 3, ATH_CIPHER_TKIP = 4, ATH_CIPHER_CLR = 5, ATH_CIPHER_MIC = 127 }; /** * struct ath_ops - Register read/write operations * * @read: Register read * @multi_read: Multiple register read * @write: Register write * @enable_write_buffer: Enable multiple register writes * @write_flush: flush buffered register writes and disable buffering */ struct ath_ops { unsigned int (*read)(void *, u32 reg_offset); void (*multi_read)(void *, u32 *addr, u32 *val, u16 count); void (*write)(void *, u32 val, u32 reg_offset); void (*enable_write_buffer)(void *); void (*write_flush) (void *); u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); void (*enable_rmw_buffer)(void *); void (*rmw_flush) (void *); }; struct ath_common; struct ath_bus_ops; struct ath_ps_ops { void (*wakeup)(struct ath_common *common); void (*restore)(struct ath_common *common); }; struct ath_common { void *ah; void *priv; struct ieee80211_hw *hw; int debug_mask; enum ath_device_state state; unsigned long op_flags; struct ath_ani ani; u16 cachelsz; u16 curaid; u8 macaddr[ETH_ALEN]; u8 curbssid[ETH_ALEN] __aligned(2); u8 bssidmask[ETH_ALEN]; u32 rx_bufsize; u32 keymax; DECLARE_BITMAP(keymap, ATH_KEYMAX); DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); DECLARE_BITMAP(ccmp_keymap, ATH_KEYMAX); enum ath_crypt_caps crypt_caps; unsigned int clockrate; spinlock_t cc_lock; - struct ath_cycle_counters cc_ani; - struct ath_cycle_counters cc_survey; + struct_group(cc, + struct ath_cycle_counters cc_ani; + struct ath_cycle_counters cc_survey; + ); struct ath_regulatory regulatory; struct ath_regulatory reg_world_copy; const struct ath_ops *ops; const struct ath_bus_ops *bus_ops; const struct ath_ps_ops *ps_ops; bool btcoex_enabled; bool disable_ani; bool bt_ant_diversity; int last_rssi; struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; }; static inline const struct ath_ps_ops *ath_ps_ops(struct ath_common *common) { return common->ps_ops; } struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, u32 len, gfp_t gfp_mask); bool ath_is_mybeacon(struct ath_common *common, struct ieee80211_hdr *hdr); void ath_hw_setbssidmask(struct ath_common *common); void ath_key_delete(struct ath_common *common, u8 hw_key_idx); int ath_key_config(struct ath_common *common, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); bool ath_hw_keyreset(struct ath_common *common, u16 entry); bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac); void ath_hw_cycle_counters_update(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common); __printf(3, 4) void ath_printk(const char *level, const struct ath_common *common, const char *fmt, ...); #define ath_emerg(common, fmt, ...) \ ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) #define ath_alert(common, fmt, ...) \ ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) #define ath_crit(common, fmt, ...) \ ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) #define ath_err(common, fmt, ...) \ ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) #define ath_warn(common, fmt, ...) \ ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) #define ath_notice(common, fmt, ...) \ ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) #define ath_info(common, fmt, ...) \ ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) /** * enum ath_debug_level - atheros wireless debug level * * @ATH_DBG_RESET: reset processing * @ATH_DBG_QUEUE: hardware queue management * @ATH_DBG_EEPROM: eeprom processing * @ATH_DBG_CALIBRATE: periodic calibration * @ATH_DBG_INTERRUPT: interrupt processing * @ATH_DBG_REGULATORY: regulatory processing * @ATH_DBG_ANI: adaptive noise immunitive processing * @ATH_DBG_XMIT: basic xmit operation * @ATH_DBG_BEACON: beacon handling * @ATH_DBG_CONFIG: configuration of the hardware * @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT * @ATH_DBG_PS: power save processing * @ATH_DBG_HWTIMER: hardware timer handling * @ATH_DBG_BTCOEX: bluetooth coexistance * @ATH_DBG_BSTUCK: stuck beacons * @ATH_DBG_MCI: Message Coexistence Interface, a private protocol * used exclusively for WLAN-BT coexistence starting from * AR9462. * @ATH_DBG_DFS: radar datection * @ATH_DBG_WOW: Wake on Wireless * @ATH_DBG_DYNACK: dynack handling * @ATH_DBG_SPECTRAL_SCAN: FFT spectral scan * @ATH_DBG_ANY: enable all debugging * * The debug level is used to control the amount and type of debugging output * we want to see. Each driver has its own method for enabling debugging and * modifying debug level states -- but this is typically done through a * module parameter 'debug' along with a respective 'debug' debugfs file * entry. */ enum ATH_DEBUG { ATH_DBG_RESET = 0x00000001, ATH_DBG_QUEUE = 0x00000002, ATH_DBG_EEPROM = 0x00000004, ATH_DBG_CALIBRATE = 0x00000008, ATH_DBG_INTERRUPT = 0x00000010, ATH_DBG_REGULATORY = 0x00000020, ATH_DBG_ANI = 0x00000040, ATH_DBG_XMIT = 0x00000080, ATH_DBG_BEACON = 0x00000100, ATH_DBG_CONFIG = 0x00000200, ATH_DBG_FATAL = 0x00000400, ATH_DBG_PS = 0x00000800, ATH_DBG_BTCOEX = 0x00001000, ATH_DBG_WMI = 0x00002000, ATH_DBG_BSTUCK = 0x00004000, ATH_DBG_MCI = 0x00008000, ATH_DBG_DFS = 0x00010000, ATH_DBG_WOW = 0x00020000, ATH_DBG_CHAN_CTX = 0x00040000, ATH_DBG_DYNACK = 0x00080000, ATH_DBG_SPECTRAL_SCAN = 0x00100000, ATH_DBG_ANY = 0xffffffff }; #define ATH_DBG_DEFAULT (ATH_DBG_FATAL) #define ATH_DBG_MAX_LEN 512 #ifdef CONFIG_ATH_DEBUG #define ath_dbg(common, dbg_mask, fmt, ...) \ do { \ if ((common)->debug_mask & ATH_DBG_##dbg_mask) \ ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ } while (0) #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo) #else static inline __attribute__ ((format (printf, 3, 4))) void _ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, const char *fmt, ...) { } #define ath_dbg(common, dbg_mask, fmt, ...) \ _ath_dbg(common, ATH_DBG_##dbg_mask, fmt, ##__VA_ARGS__) #define ATH_DBG_WARN(foo, arg...) do {} while (0) #define ATH_DBG_WARN_ON_ONCE(foo) ({ \ int __ret_warn_once = !!(foo); \ unlikely(__ret_warn_once); \ }) #endif /* CONFIG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ #ifdef CONFIG_ATH_DEBUG const char *ath_opmode_to_string(enum nl80211_iftype opmode); #else static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) { return "UNKNOWN"; } #endif extern const char *ath_bus_type_strings[]; static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype) { return ath_bus_type_strings[bustype]; } #endif /* ATH_H */ diff --git a/dfs_pattern_detector.c b/dfs_pattern_detector.c index 27f4d74a41c8..700da9f4531e 100644 --- a/dfs_pattern_detector.c +++ b/dfs_pattern_detector.c @@ -1,377 +1,372 @@ /* * Copyright (c) 2012 Neratec Solutions AG * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "dfs_pattern_detector.h" #include "dfs_pri_detector.h" #include "ath.h" /** * struct radar_types - contains array of patterns defined for one DFS domain * @region: regulatory DFS region * @num_radar_types: number of radar types to follow * @radar_types: radar types array */ struct radar_types { enum nl80211_dfs_regions region; u32 num_radar_types; const struct radar_detector_specs *radar_types; }; /* percentage on ppb threshold to trigger detection */ #define MIN_PPB_THRESH 50 #define PPB_THRESH_RATE(PPB, RATE) ((PPB * RATE + 100 - RATE) / 100) #define PPB_THRESH(PPB) PPB_THRESH_RATE(PPB, MIN_PPB_THRESH) #define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF) /* percentage of pulse width tolerance */ #define WIDTH_TOLERANCE 5 #define WIDTH_LOWER(X) ((X*(100-WIDTH_TOLERANCE)+50)/100) #define WIDTH_UPPER(X) ((X*(100+WIDTH_TOLERANCE)+50)/100) #define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, CHIRP) \ { \ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ (PRF2PRI(PMAX) - PRI_TOLERANCE), \ (PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF, \ PPB_THRESH(PPB), PRI_TOLERANCE, CHIRP \ } /* radar types as defined by ETSI EN-301-893 v1.5.1 */ static const struct radar_detector_specs etsi_radar_ref_types_v15[] = { ETSI_PATTERN(0, 0, 1, 700, 700, 1, 18, false), ETSI_PATTERN(1, 0, 5, 200, 1000, 1, 10, false), ETSI_PATTERN(2, 0, 15, 200, 1600, 1, 15, false), ETSI_PATTERN(3, 0, 15, 2300, 4000, 1, 25, false), ETSI_PATTERN(4, 20, 30, 2000, 4000, 1, 20, false), ETSI_PATTERN(5, 0, 2, 300, 400, 3, 10, false), ETSI_PATTERN(6, 0, 2, 400, 1200, 3, 15, false), }; static const struct radar_types etsi_radar_types_v15 = { .region = NL80211_DFS_ETSI, .num_radar_types = ARRAY_SIZE(etsi_radar_ref_types_v15), .radar_types = etsi_radar_ref_types_v15, }; #define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, CHIRP) \ { \ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ PMIN - PRI_TOLERANCE, \ PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \ PPB_THRESH(PPB), PRI_TOLERANCE, CHIRP \ } /* radar types released on August 14, 2014 * type 1 PRI values randomly selected within the range of 518 and 3066. * divide it to 3 groups is good enough for both of radar detection and * avoiding false detection based on practical test results * collected for more than a year. */ static const struct radar_detector_specs fcc_radar_ref_types[] = { FCC_PATTERN(0, 0, 1, 1428, 1428, 1, 18, false), FCC_PATTERN(101, 0, 1, 518, 938, 1, 57, false), FCC_PATTERN(102, 0, 1, 938, 2000, 1, 27, false), FCC_PATTERN(103, 0, 1, 2000, 3066, 1, 18, false), FCC_PATTERN(2, 0, 5, 150, 230, 1, 23, false), FCC_PATTERN(3, 6, 10, 200, 500, 1, 16, false), FCC_PATTERN(4, 11, 20, 200, 500, 1, 12, false), FCC_PATTERN(5, 50, 100, 1000, 2000, 1, 1, true), FCC_PATTERN(6, 0, 1, 333, 333, 1, 9, false), }; static const struct radar_types fcc_radar_types = { .region = NL80211_DFS_FCC, .num_radar_types = ARRAY_SIZE(fcc_radar_ref_types), .radar_types = fcc_radar_ref_types, }; #define JP_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, RATE, CHIRP) \ { \ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ PMIN - PRI_TOLERANCE, \ PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \ PPB_THRESH_RATE(PPB, RATE), PRI_TOLERANCE, CHIRP \ } static const struct radar_detector_specs jp_radar_ref_types[] = { JP_PATTERN(0, 0, 1, 1428, 1428, 1, 18, 29, false), JP_PATTERN(1, 2, 3, 3846, 3846, 1, 18, 29, false), JP_PATTERN(2, 0, 1, 1388, 1388, 1, 18, 50, false), JP_PATTERN(3, 0, 4, 4000, 4000, 1, 18, 50, false), JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false), JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false), JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false), JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, true), JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false), }; static const struct radar_types jp_radar_types = { .region = NL80211_DFS_JP, .num_radar_types = ARRAY_SIZE(jp_radar_ref_types), .radar_types = jp_radar_ref_types, }; static const struct radar_types *dfs_domains[] = { &etsi_radar_types_v15, &fcc_radar_types, &jp_radar_types, }; /** * get_dfs_domain_radar_types() - get radar types for a given DFS domain * @region: regulatory DFS region * * Return value: radar_types ptr on success, NULL if DFS domain is not supported */ static const struct radar_types * get_dfs_domain_radar_types(enum nl80211_dfs_regions region) { u32 i; for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { if (dfs_domains[i]->region == region) return dfs_domains[i]; } return NULL; } /** * struct channel_detector - detector elements for a DFS channel * @head: list_head * @freq: frequency for this channel detector in MHz * @detectors: array of dynamically created detector elements for this freq * * Channel detectors are required to provide multi-channel DFS detection, e.g. * to support off-channel scanning. A pattern detector has a list of channels * radar pulses have been reported for in the past. */ struct channel_detector { struct list_head head; u16 freq; - struct pri_detector **detectors; + struct pri_detector *detectors[]; }; /* channel_detector_reset() - reset detector lines for a given channel */ static void channel_detector_reset(struct dfs_pattern_detector *dpd, struct channel_detector *cd) { u32 i; if (cd == NULL) return; for (i = 0; i < dpd->num_radar_types; i++) cd->detectors[i]->reset(cd->detectors[i], dpd->last_pulse_ts); } /* channel_detector_exit() - destructor */ static void channel_detector_exit(struct dfs_pattern_detector *dpd, struct channel_detector *cd) { u32 i; if (cd == NULL) return; list_del(&cd->head); - if (cd->detectors) { - for (i = 0; i < dpd->num_radar_types; i++) { - struct pri_detector *de = cd->detectors[i]; - if (de != NULL) - de->exit(de); - } + + for (i = 0; i < dpd->num_radar_types; i++) { + struct pri_detector *de = cd->detectors[i]; + if (de != NULL) + de->exit(de); } - kfree(cd->detectors); + kfree(cd); } static struct channel_detector * channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) { u32 i; struct channel_detector *cd; - cd = kmalloc(sizeof(*cd), GFP_ATOMIC); + cd = kzalloc(struct_size(cd, detectors, dpd->num_radar_types), GFP_ATOMIC); if (cd == NULL) goto fail; INIT_LIST_HEAD(&cd->head); cd->freq = freq; - cd->detectors = kmalloc_array(dpd->num_radar_types, - sizeof(*cd->detectors), GFP_ATOMIC); - if (cd->detectors == NULL) - goto fail; for (i = 0; i < dpd->num_radar_types; i++) { const struct radar_detector_specs *rs = &dpd->radar_spec[i]; struct pri_detector *de = pri_detector_init(rs); if (de == NULL) goto fail; cd->detectors[i] = de; } list_add(&cd->head, &dpd->channel_detectors); return cd; fail: ath_dbg(dpd->common, DFS, "failed to allocate channel_detector for freq=%d\n", freq); channel_detector_exit(dpd, cd); return NULL; } /** * channel_detector_get() - get channel detector for given frequency * @dpd: DPD instance pointer * @freq: freq frequency in MHz * * Return value: pointer to channel detector on success, NULL otherwise * * Return existing channel detector for the given frequency or return a * newly create one. */ static struct channel_detector * channel_detector_get(struct dfs_pattern_detector *dpd, u16 freq) { struct channel_detector *cd; list_for_each_entry(cd, &dpd->channel_detectors, head) { if (cd->freq == freq) return cd; } return channel_detector_create(dpd, freq); } /* * DFS Pattern Detector */ /* dpd_reset(): reset all channel detectors */ static void dpd_reset(struct dfs_pattern_detector *dpd) { struct channel_detector *cd; list_for_each_entry(cd, &dpd->channel_detectors, head) channel_detector_reset(dpd, cd); } static void dpd_exit(struct dfs_pattern_detector *dpd) { struct channel_detector *cd, *cd0; list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head) channel_detector_exit(dpd, cd); kfree(dpd); } static bool dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event, struct radar_detector_specs *rs) { u32 i; struct channel_detector *cd; /* * pulses received for a non-supported or un-initialized * domain are treated as detected radars for fail-safety */ if (dpd->region == NL80211_DFS_UNSET) return true; cd = channel_detector_get(dpd, event->freq); if (cd == NULL) return false; /* reset detector on time stamp wraparound, caused by TSF reset */ if (event->ts < dpd->last_pulse_ts) dpd_reset(dpd); dpd->last_pulse_ts = event->ts; /* do type individual pattern matching */ for (i = 0; i < dpd->num_radar_types; i++) { struct pri_detector *pd = cd->detectors[i]; struct pri_sequence *ps = pd->add_pulse(pd, event); if (ps != NULL) { if (rs != NULL) memcpy(rs, pd->rs, sizeof(*rs)); ath_dbg(dpd->common, DFS, "DFS: radar found on freq=%d: id=%d, pri=%d, " "count=%d, count_false=%d\n", event->freq, pd->rs->type_id, ps->pri, ps->count, ps->count_falses); pd->reset(pd, dpd->last_pulse_ts); return true; } } return false; } static struct ath_dfs_pool_stats dpd_get_stats(struct dfs_pattern_detector *dpd) { return global_dfs_pool_stats; } static bool dpd_set_domain(struct dfs_pattern_detector *dpd, enum nl80211_dfs_regions region) { const struct radar_types *rt; struct channel_detector *cd, *cd0; if (dpd->region == region) return true; dpd->region = NL80211_DFS_UNSET; rt = get_dfs_domain_radar_types(region); if (rt == NULL) return false; /* delete all channel detectors for previous DFS domain */ list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head) channel_detector_exit(dpd, cd); dpd->radar_spec = rt->radar_types; dpd->num_radar_types = rt->num_radar_types; dpd->region = region; return true; } static const struct dfs_pattern_detector default_dpd = { .exit = dpd_exit, .set_dfs_domain = dpd_set_domain, .add_pulse = dpd_add_pulse, .get_stats = dpd_get_stats, .region = NL80211_DFS_UNSET, }; struct dfs_pattern_detector * dfs_pattern_detector_init(struct ath_common *common, enum nl80211_dfs_regions region) { struct dfs_pattern_detector *dpd; if (!IS_ENABLED(CONFIG_CFG80211_CERTIFICATION_ONUS)) return NULL; dpd = kmalloc(sizeof(*dpd), GFP_KERNEL); if (dpd == NULL) return NULL; *dpd = default_dpd; INIT_LIST_HEAD(&dpd->channel_detectors); dpd->common = common; if (dpd->set_dfs_domain(dpd, region)) return dpd; ath_dbg(common, DFS,"Could not set DFS domain to %d", region); kfree(dpd); return NULL; } EXPORT_SYMBOL(dfs_pattern_detector_init); diff --git a/hw.c b/hw.c index 85955572a705..b301e6fbce6c 100644 --- a/hw.c +++ b/hw.c @@ -1,190 +1,190 @@ /* * Copyright (c) 2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include -#include +#include #include "ath.h" #include "reg.h" #define REG_READ (common->ops->read) #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) /** * ath_hw_setbssidmask - filter out bssids we listen * * @common: the ath_common struct for the device. * * BSSID masking is a method used by AR5212 and newer hardware to inform PCU * which bits of the interface's MAC address should be looked at when trying * to decide which packets to ACK. In station mode and AP mode with a single * BSS every bit matters since we lock to only one BSS. In AP mode with * multiple BSSes (virtual interfaces) not every bit matters because hw must * accept frames for all BSSes and so we tweak some bits of our mac address * in order to have multiple BSSes. * * NOTE: This is a simple filter and does *not* filter out all * relevant frames. Some frames that are not for us might get ACKed from us * by PCU because they just match the mask. * * When handling multiple BSSes you can get the BSSID mask by computing the * set of ~ ( MAC XOR BSSID ) for all bssids we handle. * * When you do this you are essentially computing the common bits of all your * BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with * the MAC address to obtain the relevant bits and compare the result with * (frame's BSSID & mask) to see if they match. * * Simple example: on your card you have two BSSes you have created with * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. * There is another BSSID-03 but you are not part of it. For simplicity's sake, * assuming only 4 bits for a mac address and for BSSIDs you can then have: * * \ * MAC: 0001 | * BSSID-01: 0100 | --> Belongs to us * BSSID-02: 1001 | * / * ------------------- * BSSID-03: 0110 | --> External * ------------------- * * Our bssid_mask would then be: * * On loop iteration for BSSID-01: * ~(0001 ^ 0100) -> ~(0101) * -> 1010 * bssid_mask = 1010 * * On loop iteration for BSSID-02: * bssid_mask &= ~(0001 ^ 1001) * bssid_mask = (1010) & ~(0001 ^ 1001) * bssid_mask = (1010) & ~(1000) * bssid_mask = (1010) & (0111) * bssid_mask = 0010 * * A bssid_mask of 0010 means "only pay attention to the second least * significant bit". This is because its the only bit common * amongst the MAC and all BSSIDs we support. To findout what the real * common bit is we can simply "&" the bssid_mask now with any BSSID we have * or our MAC address (we assume the hardware uses the MAC address). * * Now, suppose there's an incoming frame for BSSID-03: * * IFRAME-01: 0110 * * An easy eye-inspeciton of this already should tell you that this frame * will not pass our check. This is because the bssid_mask tells the * hardware to only look at the second least significant bit and the * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB * as 1, which does not match 0. * * So with IFRAME-01 we *assume* the hardware will do: * * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; * --> allow = (0010) == 0000 ? 1 : 0; * --> allow = 0 * * Lets now test a frame that should work: * * IFRAME-02: 0001 (we should allow) * * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; * --> allow = (0000) == (0000) * --> allow = 1 * * Other examples: * * IFRAME-03: 0100 --> allowed * IFRAME-04: 1001 --> allowed * IFRAME-05: 1101 --> allowed but its not for us!!! * */ void ath_hw_setbssidmask(struct ath_common *common) { void *ah = common->ah; u32 id1; REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); id1 = REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_SADH_MASK; id1 |= get_unaligned_le16(common->macaddr + 4); REG_WRITE(ah, AR_STA_ID1, id1); REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask)); REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4)); } EXPORT_SYMBOL(ath_hw_setbssidmask); /** * ath_hw_cycle_counters_update - common function to update cycle counters * * @common: the ath_common struct for the device. * * This function is used to update all cycle counters in one place. * It has to be called while holding common->cc_lock! */ void ath_hw_cycle_counters_update(struct ath_common *common) { u32 cycles, busy, rx, tx; void *ah = common->ah; /* freeze */ REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); /* read */ cycles = REG_READ(ah, AR_CCCNT); busy = REG_READ(ah, AR_RCCNT); rx = REG_READ(ah, AR_RFCNT); tx = REG_READ(ah, AR_TFCNT); /* clear */ REG_WRITE(ah, AR_CCCNT, 0); REG_WRITE(ah, AR_RFCNT, 0); REG_WRITE(ah, AR_RCCNT, 0); REG_WRITE(ah, AR_TFCNT, 0); /* unfreeze */ REG_WRITE(ah, AR_MIBC, 0); /* update all cycle counters here */ common->cc_ani.cycles += cycles; common->cc_ani.rx_busy += busy; common->cc_ani.rx_frame += rx; common->cc_ani.tx_frame += tx; common->cc_survey.cycles += cycles; common->cc_survey.rx_busy += busy; common->cc_survey.rx_frame += rx; common->cc_survey.tx_frame += tx; } EXPORT_SYMBOL(ath_hw_cycle_counters_update); int32_t ath_hw_get_listen_time(struct ath_common *common) { struct ath_cycle_counters *cc = &common->cc_ani; int32_t listen_time; listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) / (common->clockrate * 1000); memset(cc, 0, sizeof(*cc)); return listen_time; } EXPORT_SYMBOL(ath_hw_get_listen_time); diff --git a/key.c b/key.c index b7b61d4f02ba..0ae436bd9b66 100644 --- a/key.c +++ b/key.c @@ -1,618 +1,618 @@ /* * Copyright (c) 2009 Atheros Communications Inc. * Copyright (c) 2010 Bruno Randolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include -#include +#include #include #include "ath.h" #include "reg.h" #define REG_READ (common->ops->read) #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) #define ENABLE_REGWRITE_BUFFER(_ah) \ if (common->ops->enable_write_buffer) \ common->ops->enable_write_buffer((_ah)); #define REGWRITE_BUFFER_FLUSH(_ah) \ if (common->ops->write_flush) \ common->ops->write_flush((_ah)); #define IEEE80211_WEP_NKID 4 /* number of key ids */ /************************/ /* Key Cache Management */ /************************/ bool ath_hw_keyreset(struct ath_common *common, u16 entry) { u32 keyType; void *ah = common->ah; if (entry >= common->keymax) { ath_err(common, "keyreset: keycache entry %u out of range\n", entry); return false; } keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); if (keyType == AR_KEYTABLE_TYPE_TKIP) { u16 micentry = entry + 64; REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) { REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); } } REGWRITE_BUFFER_FLUSH(ah); return true; } EXPORT_SYMBOL(ath_hw_keyreset); bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) { u32 macHi, macLo; u32 unicast_flag = AR_KEYTABLE_VALID; void *ah = common->ah; if (entry >= common->keymax) { ath_err(common, "keysetmac: keycache entry %u out of range\n", entry); return false; } if (mac != NULL) { /* * AR_KEYTABLE_VALID indicates that the address is a unicast * address, which must match the transmitter address for * decrypting frames. * Not setting this bit allows the hardware to use the key * for multicast frame decryption. */ - if (mac[0] & 0x01) + if (is_multicast_ether_addr(mac)) unicast_flag = 0; macLo = get_unaligned_le32(mac); macHi = get_unaligned_le16(mac + 4); macLo >>= 1; macLo |= (macHi & 1) << 31; macHi >>= 1; } else { macLo = macHi = 0; } ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); REGWRITE_BUFFER_FLUSH(ah); return true; } EXPORT_SYMBOL(ath_hw_keysetmac); static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, const struct ath_keyval *k, const u8 *mac) { void *ah = common->ah; u32 key0, key1, key2, key3, key4; u32 keyType; if (entry >= common->keymax) { ath_err(common, "set-entry: keycache entry %u out of range\n", entry); return false; } switch (k->kv_type) { case ATH_CIPHER_AES_OCB: keyType = AR_KEYTABLE_TYPE_AES; break; case ATH_CIPHER_AES_CCM: if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) { ath_dbg(common, ANY, "AES-CCM not supported by this mac rev\n"); return false; } keyType = AR_KEYTABLE_TYPE_CCM; break; case ATH_CIPHER_TKIP: keyType = AR_KEYTABLE_TYPE_TKIP; if (entry + 64 >= common->keymax) { ath_dbg(common, ANY, "entry %u inappropriate for TKIP\n", entry); return false; } break; case ATH_CIPHER_WEP: if (k->kv_len < WLAN_KEY_LEN_WEP40) { ath_dbg(common, ANY, "WEP key length %u too small\n", k->kv_len); return false; } if (k->kv_len <= WLAN_KEY_LEN_WEP40) keyType = AR_KEYTABLE_TYPE_40; else if (k->kv_len <= WLAN_KEY_LEN_WEP104) keyType = AR_KEYTABLE_TYPE_104; else keyType = AR_KEYTABLE_TYPE_128; break; case ATH_CIPHER_CLR: keyType = AR_KEYTABLE_TYPE_CLR; break; default: ath_err(common, "cipher %u not supported\n", k->kv_type); return false; } key0 = get_unaligned_le32(k->kv_val + 0); key1 = get_unaligned_le16(k->kv_val + 4); key2 = get_unaligned_le32(k->kv_val + 6); key3 = get_unaligned_le16(k->kv_val + 10); key4 = get_unaligned_le32(k->kv_val + 12); if (k->kv_len <= WLAN_KEY_LEN_WEP104) key4 &= 0xff; /* * Note: Key cache registers access special memory area that requires * two 32-bit writes to actually update the values in the internal * memory. Consequently, the exact order and pairs used here must be * maintained. */ if (keyType == AR_KEYTABLE_TYPE_TKIP) { u16 micentry = entry + 64; /* * Write inverted key[47:0] first to avoid Michael MIC errors * on frames that could be sent or received at the same time. * The correct key will be written in the end once everything * else is ready. */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); /* Write key[95:48] */ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); /* Write key[127:96] and key type */ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); /* Write MAC address for the entry */ (void) ath_hw_keysetmac(common, entry, mac); if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) { /* * TKIP uses two key cache entries: * Michael MIC TX/RX keys in the same key cache entry * (idx = main index + 64): * key0 [31:0] = RX key [31:0] * key1 [15:0] = TX key [31:16] * key1 [31:16] = reserved * key2 [31:0] = RX key [63:32] * key3 [15:0] = TX key [15:0] * key3 [31:16] = reserved * key4 [31:0] = TX key [63:32] */ u32 mic0, mic1, mic2, mic3, mic4; mic0 = get_unaligned_le32(k->kv_mic + 0); mic2 = get_unaligned_le32(k->kv_mic + 4); mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; mic4 = get_unaligned_le32(k->kv_txmic + 4); ENABLE_REGWRITE_BUFFER(ah); /* Write RX[31:0] and TX[31:16] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); /* Write RX[63:32] and TX[15:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); /* Write TX[63:32] and keyType(reserved) */ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); REGWRITE_BUFFER_FLUSH(ah); } else { /* * TKIP uses four key cache entries (two for group * keys): * Michael MIC TX/RX keys are in different key cache * entries (idx = main index + 64 for TX and * main index + 32 + 96 for RX): * key0 [31:0] = TX/RX MIC key [31:0] * key1 [31:0] = reserved * key2 [31:0] = TX/RX MIC key [63:32] * key3 [31:0] = reserved * key4 [31:0] = reserved * * Upper layer code will call this function separately * for TX and RX keys when these registers offsets are * used. */ u32 mic0, mic2; mic0 = get_unaligned_le32(k->kv_mic + 0); mic2 = get_unaligned_le32(k->kv_mic + 4); ENABLE_REGWRITE_BUFFER(ah); /* Write MIC key[31:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); /* Write MIC key[63:32] */ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); /* Write TX[63:32] and keyType(reserved) */ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); REGWRITE_BUFFER_FLUSH(ah); } ENABLE_REGWRITE_BUFFER(ah); /* MAC address registers are reserved for the MIC entry */ REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); /* * Write the correct (un-inverted) key[47:0] last to enable * TKIP now that all other registers are set with correct * values. */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); REGWRITE_BUFFER_FLUSH(ah); } else { ENABLE_REGWRITE_BUFFER(ah); /* Write key[47:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); /* Write key[95:48] */ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); /* Write key[127:96] and key type */ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); REGWRITE_BUFFER_FLUSH(ah); /* Write MAC address for the entry */ (void) ath_hw_keysetmac(common, entry, mac); } return true; } static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, struct ath_keyval *hk, const u8 *addr, bool authenticator) { const u8 *key_rxmic; const u8 *key_txmic; key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; if (addr == NULL) { /* * Group key installation - only two key cache entries are used * regardless of splitmic capability since group key is only * used either for TX or RX. */ if (authenticator) { memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); } else { memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); } return ath_hw_set_keycache_entry(common, keyix, hk, addr); } if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) { /* TX and RX keys share the same key cache entry. */ memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); return ath_hw_set_keycache_entry(common, keyix, hk, addr); } /* Separate key cache entries for TX and RX */ /* TX key goes at first index, RX key at +32. */ memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) { /* TX MIC entry failed. No need to proceed further */ ath_err(common, "Setting TX MIC Key Failed\n"); return 0; } memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); /* XXX delete tx key on failure? */ return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr); } static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) { int i; for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { if (test_bit(i, common->keymap) || test_bit(i + 64, common->keymap)) continue; /* At least one part of TKIP key allocated */ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) && (test_bit(i + 32, common->keymap) || test_bit(i + 64 + 32, common->keymap))) continue; /* At least one part of TKIP key allocated */ /* Found a free slot for a TKIP key */ return i; } return -1; } static int ath_reserve_key_cache_slot(struct ath_common *common, u32 cipher) { int i; if (cipher == WLAN_CIPHER_SUITE_TKIP) return ath_reserve_key_cache_slot_tkip(common); /* First, try to find slots that would not be available for TKIP. */ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { if (!test_bit(i, common->keymap) && (test_bit(i + 32, common->keymap) || test_bit(i + 64, common->keymap) || test_bit(i + 64 + 32, common->keymap))) return i; if (!test_bit(i + 32, common->keymap) && (test_bit(i, common->keymap) || test_bit(i + 64, common->keymap) || test_bit(i + 64 + 32, common->keymap))) return i + 32; if (!test_bit(i + 64, common->keymap) && (test_bit(i , common->keymap) || test_bit(i + 32, common->keymap) || test_bit(i + 64 + 32, common->keymap))) return i + 64; if (!test_bit(i + 64 + 32, common->keymap) && (test_bit(i, common->keymap) || test_bit(i + 32, common->keymap) || test_bit(i + 64, common->keymap))) return i + 64 + 32; } } else { for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { if (!test_bit(i, common->keymap) && test_bit(i + 64, common->keymap)) return i; if (test_bit(i, common->keymap) && !test_bit(i + 64, common->keymap)) return i + 64; } } /* No partially used TKIP slots, pick any available slot */ for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { /* Do not allow slots that could be needed for TKIP group keys * to be used. This limitation could be removed if we know that * TKIP will not be used. */ if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) continue; if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) continue; if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) continue; } if (!test_bit(i, common->keymap)) return i; /* Found a free slot for a key */ } /* No free slot found */ return -1; } /* * Configure encryption in the HW. */ int ath_key_config(struct ath_common *common, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct ath_keyval hk; const u8 *mac = NULL; u8 gmac[ETH_ALEN]; int ret = 0; int idx; memset(&hk, 0, sizeof(hk)); switch (key->cipher) { case 0: hk.kv_type = ATH_CIPHER_CLR; break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: hk.kv_type = ATH_CIPHER_WEP; break; case WLAN_CIPHER_SUITE_TKIP: hk.kv_type = ATH_CIPHER_TKIP; break; case WLAN_CIPHER_SUITE_CCMP: hk.kv_type = ATH_CIPHER_AES_CCM; break; default: return -EOPNOTSUPP; } hk.kv_len = key->keylen; if (key->keylen) memcpy(&hk.kv_values, key->key, key->keylen); if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { switch (vif->type) { case NL80211_IFTYPE_AP: memcpy(gmac, vif->addr, ETH_ALEN); gmac[0] |= 0x01; mac = gmac; idx = ath_reserve_key_cache_slot(common, key->cipher); break; case NL80211_IFTYPE_ADHOC: if (!sta) { idx = key->keyidx; break; } memcpy(gmac, sta->addr, ETH_ALEN); gmac[0] |= 0x01; mac = gmac; idx = ath_reserve_key_cache_slot(common, key->cipher); break; default: idx = key->keyidx; break; } } else if (key->keyidx) { if (WARN_ON(!sta)) return -EOPNOTSUPP; mac = sta->addr; if (vif->type != NL80211_IFTYPE_AP) { /* Only keyidx 0 should be used with unicast key, but * allow this for client mode for now. */ idx = key->keyidx; } else return -EIO; } else { if (WARN_ON(!sta)) return -EOPNOTSUPP; mac = sta->addr; idx = ath_reserve_key_cache_slot(common, key->cipher); } if (idx < 0) return -ENOSPC; /* no free key cache entries */ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, vif->type == NL80211_IFTYPE_AP); else ret = ath_hw_set_keycache_entry(common, idx, &hk, mac); if (!ret) return -EIO; set_bit(idx, common->keymap); if (key->cipher == WLAN_CIPHER_SUITE_CCMP) set_bit(idx, common->ccmp_keymap); if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { set_bit(idx + 64, common->keymap); set_bit(idx, common->tkip_keymap); set_bit(idx + 64, common->tkip_keymap); if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { set_bit(idx + 32, common->keymap); set_bit(idx + 64 + 32, common->keymap); set_bit(idx + 32, common->tkip_keymap); set_bit(idx + 64 + 32, common->tkip_keymap); } } return idx; } EXPORT_SYMBOL(ath_key_config); /* * Delete Key. */ void ath_key_delete(struct ath_common *common, u8 hw_key_idx) { /* Leave CCMP and TKIP (main key) configured to avoid disabling * encryption for potentially pending frames already in a TXQ with the * keyix pointing to this key entry. Instead, only clear the MAC address * to prevent RX processing from using this key cache entry. */ if (test_bit(hw_key_idx, common->ccmp_keymap) || test_bit(hw_key_idx, common->tkip_keymap)) ath_hw_keysetmac(common, hw_key_idx, NULL); else ath_hw_keyreset(common, hw_key_idx); if (hw_key_idx < IEEE80211_WEP_NKID) return; clear_bit(hw_key_idx, common->keymap); clear_bit(hw_key_idx, common->ccmp_keymap); if (!test_bit(hw_key_idx, common->tkip_keymap)) return; clear_bit(hw_key_idx + 64, common->keymap); clear_bit(hw_key_idx, common->tkip_keymap); clear_bit(hw_key_idx + 64, common->tkip_keymap); if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { ath_hw_keyreset(common, hw_key_idx + 32); clear_bit(hw_key_idx + 32, common->keymap); clear_bit(hw_key_idx + 64 + 32, common->keymap); clear_bit(hw_key_idx + 32, common->tkip_keymap); clear_bit(hw_key_idx + 64 + 32, common->tkip_keymap); } } EXPORT_SYMBOL(ath_key_delete); diff --git a/trace.h b/trace.h index 9935cf475b6d..82aac0a4baff 100644 --- a/trace.h +++ b/trace.h @@ -1,68 +1,68 @@ /* * Copyright (c) 2014 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #if !defined(_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_H #include #include "ath.h" #undef TRACE_SYSTEM #define TRACE_SYSTEM ath #if !defined(CONFIG_ATH_TRACEPOINTS) #undef TRACE_EVENT #define TRACE_EVENT(name, proto, ...) static inline void trace_ ## name(proto) {} #endif /* CONFIG_ATH_TRACEPOINTS */ TRACE_EVENT(ath_log, TP_PROTO(struct wiphy *wiphy, struct va_format *vaf), TP_ARGS(wiphy, vaf), TP_STRUCT__entry( __string(device, wiphy_name(wiphy)) __string(driver, KBUILD_MODNAME) __vstring(msg, vaf->fmt, vaf->va) ), TP_fast_assign( - __assign_str(device, wiphy_name(wiphy)); - __assign_str(driver, KBUILD_MODNAME); + __assign_str(device); + __assign_str(driver); __assign_vstr(msg, vaf->fmt, vaf->va); ), TP_printk( "%s %s %s", __get_str(driver), __get_str(device), __get_str(msg) ) ); #endif /* _TRACE_H || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH . #undef TRACE_INCLUDE_FILE #define TRACE_INCLUDE_FILE trace /* This part must be outside protection */ #include