diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-25 03:53:42 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-25 03:53:42 -0300 |
commit | 03dd4cb26d967f9588437b0fc9cc0e8353322bb7 (patch) | |
tree | fa581f6dc1c0596391690d1f67eceef3af8246dc /drivers/net/wireless/p54/main.c | |
parent | d4e493caf788ef44982e131ff9c786546904d934 (diff) |
Linux-libre 4.5-gnu
Diffstat (limited to 'drivers/net/wireless/p54/main.c')
-rw-r--r-- | drivers/net/wireless/p54/main.c | 867 |
1 files changed, 0 insertions, 867 deletions
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c deleted file mode 100644 index 7805864e7..000000000 --- a/drivers/net/wireless/p54/main.c +++ /dev/null @@ -1,867 +0,0 @@ -/* - * mac80211 glue code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> - * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de> - * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. - * - stlc45xx driver - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/slab.h> -#include <linux/firmware.h> -#include <linux/etherdevice.h> -#include <linux/module.h> - -#include <net/mac80211.h> - -#include "p54.h" -#include "lmac.h" - -static bool modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); -MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); -MODULE_DESCRIPTION("Softmac Prism54 common code"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54common"); - -static int p54_sta_add_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct p54_common *priv = hw->priv; - - /* - * Notify the firmware that we don't want or we don't - * need to buffer frames for this station anymore. - */ - - p54_sta_unlock(priv, sta->addr); - - return 0; -} - -static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, - enum sta_notify_cmd notify_cmd, - struct ieee80211_sta *sta) -{ - struct p54_common *priv = dev->priv; - - switch (notify_cmd) { - case STA_NOTIFY_AWAKE: - /* update the firmware's filter table */ - p54_sta_unlock(priv, sta->addr); - break; - default: - break; - } -} - -static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, - bool set) -{ - struct p54_common *priv = dev->priv; - - return p54_update_beacon_tim(priv, sta->aid, set); -} - -u8 *p54_find_ie(struct sk_buff *skb, u8 ie) -{ - struct ieee80211_mgmt *mgmt = (void *)skb->data; - u8 *pos, *end; - - if (skb->len <= sizeof(mgmt)) - return NULL; - - pos = (u8 *)mgmt->u.beacon.variable; - end = skb->data + skb->len; - while (pos < end) { - if (pos + 2 + pos[1] > end) - return NULL; - - if (pos[0] == ie) - return pos; - - pos += 2 + pos[1]; - } - return NULL; -} - -static int p54_beacon_format_ie_tim(struct sk_buff *skb) -{ - /* - * the good excuse for this mess is ... the firmware. - * The dummy TIM MUST be at the end of the beacon frame, - * because it'll be overwritten! - */ - u8 *tim; - u8 dtim_len; - u8 dtim_period; - u8 *next; - - tim = p54_find_ie(skb, WLAN_EID_TIM); - if (!tim) - return 0; - - dtim_len = tim[1]; - dtim_period = tim[3]; - next = tim + 2 + dtim_len; - - if (dtim_len < 3) - return -EINVAL; - - memmove(tim, next, skb_tail_pointer(skb) - next); - tim = skb_tail_pointer(skb) - (dtim_len + 2); - - /* add the dummy at the end */ - tim[0] = WLAN_EID_TIM; - tim[1] = 3; - tim[2] = 0; - tim[3] = dtim_period; - tim[4] = 0; - - if (dtim_len > 3) - skb_trim(skb, skb->len - (dtim_len - 3)); - - return 0; -} - -static int p54_beacon_update(struct p54_common *priv, - struct ieee80211_vif *vif) -{ - struct ieee80211_tx_control control = { }; - struct sk_buff *beacon; - int ret; - - beacon = ieee80211_beacon_get(priv->hw, vif); - if (!beacon) - return -ENOMEM; - ret = p54_beacon_format_ie_tim(beacon); - if (ret) - return ret; - - /* - * During operation, the firmware takes care of beaconing. - * The driver only needs to upload a new beacon template, once - * the template was changed by the stack or userspace. - * - * LMAC API 3.2.2 also specifies that the driver does not need - * to cancel the old beacon template by hand, instead the firmware - * will release the previous one through the feedback mechanism. - */ - p54_tx_80211(priv->hw, &control, beacon); - priv->tsf_high32 = 0; - priv->tsf_low32 = 0; - - return 0; -} - -static int p54_start(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int err; - - mutex_lock(&priv->conf_mutex); - err = priv->open(dev); - if (err) - goto out; - P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47); - P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94); - P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0); - P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0); - err = p54_set_edcf(priv); - if (err) - goto out; - - eth_broadcast_addr(priv->bssid); - priv->mode = NL80211_IFTYPE_MONITOR; - err = p54_setup_mac(priv); - if (err) { - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - goto out; - } - - ieee80211_queue_delayed_work(dev, &priv->work, 0); - - priv->softled_state = 0; - err = p54_set_leds(priv); - -out: - mutex_unlock(&priv->conf_mutex); - return err; -} - -static void p54_stop(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int i; - - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - priv->softled_state = 0; - cancel_delayed_work_sync(&priv->work); - mutex_lock(&priv->conf_mutex); - p54_set_leds(priv); - priv->stop(dev); - skb_queue_purge(&priv->tx_pending); - skb_queue_purge(&priv->tx_queue); - for (i = 0; i < P54_QUEUE_NUM; i++) { - priv->tx_stats[i].count = 0; - priv->tx_stats[i].len = 0; - } - - priv->beacon_req_id = cpu_to_le32(0); - priv->tsf_high32 = priv->tsf_low32 = 0; - mutex_unlock(&priv->conf_mutex); -} - -static int p54_add_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct p54_common *priv = dev->priv; - int err; - - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; - - mutex_lock(&priv->conf_mutex); - if (priv->mode != NL80211_IFTYPE_MONITOR) { - mutex_unlock(&priv->conf_mutex); - return -EOPNOTSUPP; - } - - priv->vif = vif; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - priv->mode = vif->type; - break; - default: - mutex_unlock(&priv->conf_mutex); - return -EOPNOTSUPP; - } - - memcpy(priv->mac_addr, vif->addr, ETH_ALEN); - err = p54_setup_mac(priv); - mutex_unlock(&priv->conf_mutex); - return err; -} - -static void p54_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); - priv->vif = NULL; - - /* - * LMAC API 3.2.2 states that any active beacon template must be - * canceled by the driver before attempting a mode transition. - */ - if (le32_to_cpu(priv->beacon_req_id) != 0) { - p54_tx_cancel(priv, priv->beacon_req_id); - wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ); - } - priv->mode = NL80211_IFTYPE_MONITOR; - eth_zero_addr(priv->mac_addr); - eth_zero_addr(priv->bssid); - p54_setup_mac(priv); - mutex_unlock(&priv->conf_mutex); -} - -static int p54_wait_for_stats(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int ret; - - priv->update_stats = true; - ret = p54_fetch_statistics(priv); - if (ret) - return ret; - - ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ); - if (ret == 0) - return -ETIMEDOUT; - - return 0; -} - -static void p54_reset_stats(struct p54_common *priv) -{ - struct ieee80211_channel *chan = priv->curchan; - - if (chan) { - struct survey_info *info = &priv->survey[chan->hw_value]; - - /* only reset channel statistics, don't touch .filled, etc. */ - info->time = 0; - info->time_busy = 0; - info->time_tx = 0; - } - - priv->update_stats = true; - priv->survey_raw.active = 0; - priv->survey_raw.cca = 0; - priv->survey_raw.tx = 0; -} - -static int p54_config(struct ieee80211_hw *dev, u32 changed) -{ - int ret = 0; - struct p54_common *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - - mutex_lock(&priv->conf_mutex); - if (changed & IEEE80211_CONF_CHANGE_POWER) - priv->output_power = conf->power_level << 2; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - struct ieee80211_channel *oldchan; - WARN_ON(p54_wait_for_stats(dev)); - oldchan = priv->curchan; - priv->curchan = NULL; - ret = p54_scan(priv, P54_SCAN_EXIT, 0); - if (ret) { - priv->curchan = oldchan; - goto out; - } - /* - * TODO: Use the LM_SCAN_TRAP to determine the current - * operating channel. - */ - priv->curchan = priv->hw->conf.chandef.chan; - p54_reset_stats(priv); - WARN_ON(p54_fetch_statistics(priv)); - } - if (changed & IEEE80211_CONF_CHANGE_PS) { - WARN_ON(p54_wait_for_stats(dev)); - ret = p54_set_ps(priv); - if (ret) - goto out; - WARN_ON(p54_wait_for_stats(dev)); - } - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - WARN_ON(p54_wait_for_stats(dev)); - ret = p54_setup_mac(priv); - if (ret) - goto out; - WARN_ON(p54_wait_for_stats(dev)); - } - -out: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static u64 p54_prepare_multicast(struct ieee80211_hw *dev, - struct netdev_hw_addr_list *mc_list) -{ - struct p54_common *priv = dev->priv; - struct netdev_hw_addr *ha; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) != - ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list)); - /* - * The first entry is reserved for the global broadcast MAC. - * Otherwise the firmware will drop it and ARP will no longer work. - */ - i = 1; - priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i; - netdev_hw_addr_list_for_each(ha, mc_list) { - memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN); - i++; - if (i >= ARRAY_SIZE(priv->mc_maclist)) - break; - } - - return 1; /* update */ -} - -static void p54_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct p54_common *priv = dev->priv; - - *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS; - - priv->filter_flags = *total_flags; - - if (changed_flags & FIF_OTHER_BSS) - p54_setup_mac(priv); - - if (changed_flags & FIF_ALLMULTI || multicast) - p54_set_groupfilter(priv); -} - -static int p54_conf_tx(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct p54_common *priv = dev->priv; - int ret; - - mutex_lock(&priv->conf_mutex); - if (queue < dev->queues) { - P54_SET_QUEUE(priv->qos_params[queue], params->aifs, - params->cw_min, params->cw_max, params->txop); - ret = p54_set_edcf(priv); - } else - ret = -EINVAL; - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void p54_work(struct work_struct *work) -{ - struct p54_common *priv = container_of(work, struct p54_common, - work.work); - - if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) - return ; - - /* - * TODO: walk through tx_queue and do the following tasks - * 1. initiate bursts. - * 2. cancel stuck frames / reset the device if necessary. - */ - - mutex_lock(&priv->conf_mutex); - WARN_ON_ONCE(p54_fetch_statistics(priv)); - mutex_unlock(&priv->conf_mutex); -} - -static int p54_get_stats(struct ieee80211_hw *dev, - struct ieee80211_low_level_stats *stats) -{ - struct p54_common *priv = dev->priv; - - memcpy(stats, &priv->stats, sizeof(*stats)); - return 0; -} - -static void p54_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); - if (changed & BSS_CHANGED_BSSID) { - memcpy(priv->bssid, info->bssid, ETH_ALEN); - p54_setup_mac(priv); - } - - if (changed & BSS_CHANGED_BEACON) { - p54_scan(priv, P54_SCAN_EXIT, 0); - p54_setup_mac(priv); - p54_beacon_update(priv, vif); - p54_set_edcf(priv); - } - - if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) { - priv->use_short_slot = info->use_short_slot; - p54_set_edcf(priv); - } - if (changed & BSS_CHANGED_BASIC_RATES) { - if (dev->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) - priv->basic_rate_mask = (info->basic_rates << 4); - else - priv->basic_rate_mask = info->basic_rates; - p54_setup_mac(priv); - if (priv->fw_var >= 0x500) - p54_scan(priv, P54_SCAN_EXIT, 0); - } - if (changed & BSS_CHANGED_ASSOC) { - if (info->assoc) { - priv->aid = info->aid; - priv->wakeup_timer = info->beacon_int * - info->dtim_period * 5; - p54_setup_mac(priv); - } else { - priv->wakeup_timer = 500; - priv->aid = 0; - } - } - - mutex_unlock(&priv->conf_mutex); -} - -static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct p54_common *priv = dev->priv; - int slot, ret = 0; - u8 algo = 0; - u8 *addr = NULL; - - if (modparam_nohwcrypt) - return -EOPNOTSUPP; - - if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) { - /* - * Unfortunately most/all firmwares are trying to decrypt - * incoming management frames if a suitable key can be found. - * However, in doing so the data in these frames gets - * corrupted. So, we can't have firmware supported crypto - * offload in this case. - */ - return -EOPNOTSUPP; - } - - mutex_lock(&priv->conf_mutex); - if (cmd == SET_KEY) { - switch (key->cipher) { - case WLAN_CIPHER_SUITE_TKIP: - if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | - BR_DESC_PRIV_CAP_TKIP))) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - algo = P54_CRYPTO_TKIPMICHAEL; - break; - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - algo = P54_CRYPTO_WEP; - break; - case WLAN_CIPHER_SUITE_CCMP: - if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - algo = P54_CRYPTO_AESCCMP; - break; - default: - ret = -EOPNOTSUPP; - goto out_unlock; - } - slot = bitmap_find_free_region(priv->used_rxkeys, - priv->rx_keycache_size, 0); - - if (slot < 0) { - /* - * The device supports the chosen algorithm, but the - * firmware does not provide enough key slots to store - * all of them. - * But encryption offload for outgoing frames is always - * possible, so we just pretend that the upload was - * successful and do the decryption in software. - */ - - /* mark the key as invalid. */ - key->hw_key_idx = 0xff; - goto out_unlock; - } - - key->flags |= IEEE80211_KEY_FLAG_RESERVE_TAILROOM; - } else { - slot = key->hw_key_idx; - - if (slot == 0xff) { - /* This key was not uploaded into the rx key cache. */ - - goto out_unlock; - } - - bitmap_release_region(priv->used_rxkeys, slot, 0); - algo = 0; - } - - if (sta) - addr = sta->addr; - - ret = p54_upload_key(priv, algo, slot, key->keyidx, - key->keylen, addr, key->key); - if (ret) { - bitmap_release_region(priv->used_rxkeys, slot, 0); - ret = -EOPNOTSUPP; - goto out_unlock; - } - - key->hw_key_idx = slot; - -out_unlock: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static int p54_get_survey(struct ieee80211_hw *dev, int idx, - struct survey_info *survey) -{ - struct p54_common *priv = dev->priv; - struct ieee80211_channel *chan; - int err, tries; - bool in_use = false; - - if (idx >= priv->chan_num) - return -ENOENT; - -#define MAX_TRIES 1 - for (tries = 0; tries < MAX_TRIES; tries++) { - chan = priv->curchan; - if (chan && chan->hw_value == idx) { - mutex_lock(&priv->conf_mutex); - err = p54_wait_for_stats(dev); - mutex_unlock(&priv->conf_mutex); - if (err) - return err; - - in_use = true; - } - - memcpy(survey, &priv->survey[idx], sizeof(*survey)); - - if (in_use) { - /* test if the reported statistics are valid. */ - if (survey->time != 0) { - survey->filled |= SURVEY_INFO_IN_USE; - } else { - /* - * hw/fw has not accumulated enough sample sets. - * Wait for 100ms, this ought to be enough to - * to get at least one non-null set of channel - * usage statistics. - */ - msleep(100); - continue; - } - } - return 0; - } - return -ETIMEDOUT; -#undef MAX_TRIES -} - -static unsigned int p54_flush_count(struct p54_common *priv) -{ - unsigned int total = 0, i; - - BUILD_BUG_ON(P54_QUEUE_NUM > ARRAY_SIZE(priv->tx_stats)); - - /* - * Because the firmware has the sole control over any frames - * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they - * don't really count as pending or active. - */ - for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++) - total += priv->tx_stats[i].len; - return total; -} - -static void p54_flush(struct ieee80211_hw *dev, struct ieee80211_vif *vif, - u32 queues, bool drop) -{ - struct p54_common *priv = dev->priv; - unsigned int total, i; - - /* - * Currently, it wouldn't really matter if we wait for one second - * or 15 minutes. But once someone gets around and completes the - * TODOs [ancel stuck frames / reset device] in p54_work, it will - * suddenly make sense to wait that long. - */ - i = P54_STATISTICS_UPDATE * 2 / 20; - - /* - * In this case no locking is required because as we speak the - * queues have already been stopped and no new frames can sneak - * up from behind. - */ - while ((total = p54_flush_count(priv) && i--)) { - /* waste time */ - msleep(20); - } - - WARN(total, "tx flush timeout, unresponsive firmware"); -} - -static void p54_set_coverage_class(struct ieee80211_hw *dev, - s16 coverage_class) -{ - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); - /* support all coverage class values as in 802.11-2007 Table 7-27 */ - priv->coverage_class = clamp_t(u8, coverage_class, 0, 31); - p54_set_edcf(priv); - mutex_unlock(&priv->conf_mutex); -} - -static const struct ieee80211_ops p54_ops = { - .tx = p54_tx_80211, - .start = p54_start, - .stop = p54_stop, - .add_interface = p54_add_interface, - .remove_interface = p54_remove_interface, - .set_tim = p54_set_tim, - .sta_notify = p54_sta_notify, - .sta_add = p54_sta_add_remove, - .sta_remove = p54_sta_add_remove, - .set_key = p54_set_key, - .config = p54_config, - .flush = p54_flush, - .bss_info_changed = p54_bss_info_changed, - .prepare_multicast = p54_prepare_multicast, - .configure_filter = p54_configure_filter, - .conf_tx = p54_conf_tx, - .get_stats = p54_get_stats, - .get_survey = p54_get_survey, - .set_coverage_class = p54_set_coverage_class, -}; - -struct ieee80211_hw *p54_init_common(size_t priv_data_len) -{ - struct ieee80211_hw *dev; - struct p54_common *priv; - - dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); - if (!dev) - return NULL; - - priv = dev->priv; - priv->hw = dev; - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - priv->basic_rate_mask = 0x15f; - spin_lock_init(&priv->tx_stats_lock); - skb_queue_head_init(&priv->tx_queue); - skb_queue_head_init(&priv->tx_pending); - ieee80211_hw_set(dev, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(dev, MFP_CAPABLE); - ieee80211_hw_set(dev, PS_NULLFUNC_STACK); - ieee80211_hw_set(dev, SUPPORTS_PS); - ieee80211_hw_set(dev, RX_INCLUDES_FCS); - ieee80211_hw_set(dev, SIGNAL_DBM); - - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT); - - priv->beacon_req_id = cpu_to_le32(0); - priv->tx_stats[P54_QUEUE_BEACON].limit = 1; - priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; - priv->tx_stats[P54_QUEUE_MGMT].limit = 3; - priv->tx_stats[P54_QUEUE_CAB].limit = 3; - priv->tx_stats[P54_QUEUE_DATA].limit = 5; - dev->queues = 1; - priv->noise = -94; - /* - * We support at most 8 tries no matter which rate they're at, - * we cannot support max_rates * max_rate_tries as we set it - * here, but setting it correctly to 4/2 or so would limit us - * artificially if the RC algorithm wants just two rates, so - * let's say 4/7, we'll redistribute it at TX time, see the - * comments there. - */ - dev->max_rates = 4; - dev->max_rate_tries = 7; - dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 + - sizeof(struct p54_tx_data); - - /* - * For now, disable PS by default because it affects - * link stability significantly. - */ - dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - - mutex_init(&priv->conf_mutex); - mutex_init(&priv->eeprom_mutex); - init_completion(&priv->stat_comp); - init_completion(&priv->eeprom_comp); - init_completion(&priv->beacon_comp); - INIT_DELAYED_WORK(&priv->work, p54_work); - - eth_broadcast_addr(priv->mc_maclist[0]); - priv->curchan = NULL; - p54_reset_stats(priv); - return dev; -} -EXPORT_SYMBOL_GPL(p54_init_common); - -int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) -{ - struct p54_common __maybe_unused *priv = dev->priv; - int err; - - err = ieee80211_register_hw(dev); - if (err) { - dev_err(pdev, "Cannot register device (%d).\n", err); - return err; - } - priv->registered = true; - -#ifdef CONFIG_P54_LEDS - err = p54_init_leds(priv); - if (err) { - p54_unregister_common(dev); - return err; - } -#endif /* CONFIG_P54_LEDS */ - - dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); - return 0; -} -EXPORT_SYMBOL_GPL(p54_register_common); - -void p54_free_common(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - unsigned int i; - - for (i = 0; i < IEEE80211_NUM_BANDS; i++) - kfree(priv->band_table[i]); - - kfree(priv->iq_autocal); - kfree(priv->output_limit); - kfree(priv->curve_data); - kfree(priv->rssi_db); - kfree(priv->used_rxkeys); - kfree(priv->survey); - priv->iq_autocal = NULL; - priv->output_limit = NULL; - priv->curve_data = NULL; - priv->rssi_db = NULL; - priv->used_rxkeys = NULL; - priv->survey = NULL; - ieee80211_free_hw(dev); -} -EXPORT_SYMBOL_GPL(p54_free_common); - -void p54_unregister_common(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - -#ifdef CONFIG_P54_LEDS - p54_unregister_leds(priv); -#endif /* CONFIG_P54_LEDS */ - - if (priv->registered) { - priv->registered = false; - ieee80211_unregister_hw(dev); - } - - mutex_destroy(&priv->conf_mutex); - mutex_destroy(&priv->eeprom_mutex); -} -EXPORT_SYMBOL_GPL(p54_unregister_common); |