brintos

brintos / linux-shallow public Read only

0
0
Text · 21.1 KiB · 42111bb Raw
867 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * mac80211 glue code for mac80211 Prism54 drivers4 *5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>6 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>8 *9 * Based on:10 * - the islsm (softmac prism54) driver, which is:11 *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.12 * - stlc45xx driver13 *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).14 */15 16#include <linux/slab.h>17#include <linux/firmware.h>18#include <linux/etherdevice.h>19#include <linux/module.h>20 21#include <net/mac80211.h>22 23#include "p54.h"24#include "lmac.h"25 26static bool modparam_nohwcrypt;27module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);28MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");29MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");30MODULE_DESCRIPTION("Softmac Prism54 common code");31MODULE_LICENSE("GPL");32MODULE_ALIAS("prism54common");33 34static int p54_sta_add_remove(struct ieee80211_hw *hw,35			      struct ieee80211_vif *vif,36			      struct ieee80211_sta *sta)37{38	struct p54_common *priv = hw->priv;39 40	/*41	 * Notify the firmware that we don't want or we don't42	 * need to buffer frames for this station anymore.43	 */44 45	p54_sta_unlock(priv, sta->addr);46 47	return 0;48}49 50static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,51			      enum sta_notify_cmd notify_cmd,52			      struct ieee80211_sta *sta)53{54	struct p54_common *priv = dev->priv;55 56	switch (notify_cmd) {57	case STA_NOTIFY_AWAKE:58		/* update the firmware's filter table */59		p54_sta_unlock(priv, sta->addr);60		break;61	default:62		break;63	}64}65 66static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,67			bool set)68{69	struct p54_common *priv = dev->priv;70 71	return p54_update_beacon_tim(priv, sta->aid, set);72}73 74u8 *p54_find_ie(struct sk_buff *skb, u8 ie)75{76	struct ieee80211_mgmt *mgmt = (void *)skb->data;77	u8 *pos, *end;78 79	if (skb->len <= sizeof(mgmt))80		return NULL;81 82	pos = (u8 *)mgmt->u.beacon.variable;83	end = skb->data + skb->len;84	while (pos < end) {85		if (pos + 2 + pos[1] > end)86			return NULL;87 88		if (pos[0] == ie)89			return pos;90 91		pos += 2 + pos[1];92	}93	return NULL;94}95 96static int p54_beacon_format_ie_tim(struct sk_buff *skb)97{98	/*99	 * the good excuse for this mess is ... the firmware.100	 * The dummy TIM MUST be at the end of the beacon frame,101	 * because it'll be overwritten!102	 */103	u8 *tim;104	u8 dtim_len;105	u8 dtim_period;106	u8 *next;107 108	tim = p54_find_ie(skb, WLAN_EID_TIM);109	if (!tim)110		return 0;111 112	dtim_len = tim[1];113	dtim_period = tim[3];114	next = tim + 2 + dtim_len;115 116	if (dtim_len < 3)117		return -EINVAL;118 119	memmove(tim, next, skb_tail_pointer(skb) - next);120	tim = skb_tail_pointer(skb) - (dtim_len + 2);121 122	/* add the dummy at the end */123	tim[0] = WLAN_EID_TIM;124	tim[1] = 3;125	tim[2] = 0;126	tim[3] = dtim_period;127	tim[4] = 0;128 129	if (dtim_len > 3)130		skb_trim(skb, skb->len - (dtim_len - 3));131 132	return 0;133}134 135static int p54_beacon_update(struct p54_common *priv,136			struct ieee80211_vif *vif)137{138	struct ieee80211_tx_control control = { };139	struct sk_buff *beacon;140	int ret;141 142	beacon = ieee80211_beacon_get(priv->hw, vif, 0);143	if (!beacon)144		return -ENOMEM;145	ret = p54_beacon_format_ie_tim(beacon);146	if (ret)147		return ret;148 149	/*150	 * During operation, the firmware takes care of beaconing.151	 * The driver only needs to upload a new beacon template, once152	 * the template was changed by the stack or userspace.153	 *154	 * LMAC API 3.2.2 also specifies that the driver does not need155	 * to cancel the old beacon template by hand, instead the firmware156	 * will release the previous one through the feedback mechanism.157	 */158	p54_tx_80211(priv->hw, &control, beacon);159	priv->tsf_high32 = 0;160	priv->tsf_low32 = 0;161 162	return 0;163}164 165static int p54_start(struct ieee80211_hw *dev)166{167	struct p54_common *priv = dev->priv;168	int err;169 170	mutex_lock(&priv->conf_mutex);171	err = priv->open(dev);172	if (err)173		goto out;174	P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);175	P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);176	P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);177	P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);178	err = p54_set_edcf(priv);179	if (err)180		goto out;181 182	eth_broadcast_addr(priv->bssid);183	priv->mode = NL80211_IFTYPE_MONITOR;184	err = p54_setup_mac(priv);185	if (err) {186		priv->mode = NL80211_IFTYPE_UNSPECIFIED;187		goto out;188	}189 190	ieee80211_queue_delayed_work(dev, &priv->work, 0);191 192	priv->softled_state = 0;193	err = p54_set_leds(priv);194 195out:196	mutex_unlock(&priv->conf_mutex);197	return err;198}199 200static void p54_stop(struct ieee80211_hw *dev, bool suspend)201{202	struct p54_common *priv = dev->priv;203	int i;204 205	priv->mode = NL80211_IFTYPE_UNSPECIFIED;206	priv->softled_state = 0;207	cancel_delayed_work_sync(&priv->work);208	mutex_lock(&priv->conf_mutex);209	p54_set_leds(priv);210	priv->stop(dev);211	skb_queue_purge(&priv->tx_pending);212	skb_queue_purge(&priv->tx_queue);213	for (i = 0; i < P54_QUEUE_NUM; i++) {214		priv->tx_stats[i].count = 0;215		priv->tx_stats[i].len = 0;216	}217 218	priv->beacon_req_id = cpu_to_le32(0);219	priv->tsf_high32 = priv->tsf_low32 = 0;220	mutex_unlock(&priv->conf_mutex);221}222 223static int p54_add_interface(struct ieee80211_hw *dev,224			     struct ieee80211_vif *vif)225{226	struct p54_common *priv = dev->priv;227	int err;228 229	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;230 231	mutex_lock(&priv->conf_mutex);232	if (priv->mode != NL80211_IFTYPE_MONITOR) {233		mutex_unlock(&priv->conf_mutex);234		return -EOPNOTSUPP;235	}236 237	priv->vif = vif;238 239	switch (vif->type) {240	case NL80211_IFTYPE_STATION:241	case NL80211_IFTYPE_ADHOC:242	case NL80211_IFTYPE_AP:243	case NL80211_IFTYPE_MESH_POINT:244		priv->mode = vif->type;245		break;246	default:247		mutex_unlock(&priv->conf_mutex);248		return -EOPNOTSUPP;249	}250 251	memcpy(priv->mac_addr, vif->addr, ETH_ALEN);252	err = p54_setup_mac(priv);253	mutex_unlock(&priv->conf_mutex);254	return err;255}256 257static void p54_remove_interface(struct ieee80211_hw *dev,258				 struct ieee80211_vif *vif)259{260	struct p54_common *priv = dev->priv;261 262	mutex_lock(&priv->conf_mutex);263	priv->vif = NULL;264 265	/*266	 * LMAC API 3.2.2 states that any active beacon template must be267	 * canceled by the driver before attempting a mode transition.268	 */269	if (le32_to_cpu(priv->beacon_req_id) != 0) {270		p54_tx_cancel(priv, priv->beacon_req_id);271		wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ);272	}273	priv->mode = NL80211_IFTYPE_MONITOR;274	eth_zero_addr(priv->mac_addr);275	eth_zero_addr(priv->bssid);276	p54_setup_mac(priv);277	mutex_unlock(&priv->conf_mutex);278}279 280static int p54_wait_for_stats(struct ieee80211_hw *dev)281{282	struct p54_common *priv = dev->priv;283	int ret;284 285	priv->update_stats = true;286	ret = p54_fetch_statistics(priv);287	if (ret)288		return ret;289 290	ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ);291	if (ret == 0)292		return -ETIMEDOUT;293 294	return 0;295}296 297static void p54_reset_stats(struct p54_common *priv)298{299	struct ieee80211_channel *chan = priv->curchan;300 301	if (chan) {302		struct survey_info *info = &priv->survey[chan->hw_value];303 304		/* only reset channel statistics, don't touch .filled, etc. */305		info->time = 0;306		info->time_busy = 0;307		info->time_tx = 0;308	}309 310	priv->update_stats = true;311	priv->survey_raw.active = 0;312	priv->survey_raw.cca = 0;313	priv->survey_raw.tx = 0;314}315 316static int p54_config(struct ieee80211_hw *dev, u32 changed)317{318	int ret = 0;319	struct p54_common *priv = dev->priv;320	struct ieee80211_conf *conf = &dev->conf;321 322	mutex_lock(&priv->conf_mutex);323	if (changed & IEEE80211_CONF_CHANGE_POWER)324		priv->output_power = conf->power_level << 2;325	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {326		struct ieee80211_channel *oldchan;327		WARN_ON(p54_wait_for_stats(dev));328		oldchan = priv->curchan;329		priv->curchan = NULL;330		ret = p54_scan(priv, P54_SCAN_EXIT, 0);331		if (ret) {332			priv->curchan = oldchan;333			goto out;334		}335		/*336		 * TODO: Use the LM_SCAN_TRAP to determine the current337		 * operating channel.338		 */339		priv->curchan = priv->hw->conf.chandef.chan;340		p54_reset_stats(priv);341		WARN_ON(p54_fetch_statistics(priv));342	}343	if (changed & IEEE80211_CONF_CHANGE_PS) {344		WARN_ON(p54_wait_for_stats(dev));345		ret = p54_set_ps(priv);346		if (ret)347			goto out;348		WARN_ON(p54_wait_for_stats(dev));349	}350	if (changed & IEEE80211_CONF_CHANGE_IDLE) {351		WARN_ON(p54_wait_for_stats(dev));352		ret = p54_setup_mac(priv);353		if (ret)354			goto out;355		WARN_ON(p54_wait_for_stats(dev));356	}357 358out:359	mutex_unlock(&priv->conf_mutex);360	return ret;361}362 363static u64 p54_prepare_multicast(struct ieee80211_hw *dev,364				 struct netdev_hw_addr_list *mc_list)365{366	struct p54_common *priv = dev->priv;367	struct netdev_hw_addr *ha;368	int i;369 370	BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) !=371		ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list));372	/*373	 * The first entry is reserved for the global broadcast MAC.374	 * Otherwise the firmware will drop it and ARP will no longer work.375	 */376	i = 1;377	priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i;378	netdev_hw_addr_list_for_each(ha, mc_list) {379		memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN);380		i++;381		if (i >= ARRAY_SIZE(priv->mc_maclist))382			break;383	}384 385	return 1; /* update */386}387 388static void p54_configure_filter(struct ieee80211_hw *dev,389				 unsigned int changed_flags,390				 unsigned int *total_flags,391				 u64 multicast)392{393	struct p54_common *priv = dev->priv;394 395	*total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS;396 397	priv->filter_flags = *total_flags;398 399	if (changed_flags & FIF_OTHER_BSS)400		p54_setup_mac(priv);401 402	if (changed_flags & FIF_ALLMULTI || multicast)403		p54_set_groupfilter(priv);404}405 406static int p54_conf_tx(struct ieee80211_hw *dev,407		       struct ieee80211_vif *vif,408		       unsigned int link_id, u16 queue,409		       const struct ieee80211_tx_queue_params *params)410{411	struct p54_common *priv = dev->priv;412	int ret;413 414	mutex_lock(&priv->conf_mutex);415	P54_SET_QUEUE(priv->qos_params[queue], params->aifs,416		      params->cw_min, params->cw_max, params->txop);417	ret = p54_set_edcf(priv);418	mutex_unlock(&priv->conf_mutex);419	return ret;420}421 422static void p54_work(struct work_struct *work)423{424	struct p54_common *priv = container_of(work, struct p54_common,425					       work.work);426 427	if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))428		return ;429 430	/*431	 * TODO: walk through tx_queue and do the following tasks432	 * 	1. initiate bursts.433	 *      2. cancel stuck frames / reset the device if necessary.434	 */435 436	mutex_lock(&priv->conf_mutex);437	WARN_ON_ONCE(p54_fetch_statistics(priv));438	mutex_unlock(&priv->conf_mutex);439}440 441static int p54_get_stats(struct ieee80211_hw *dev,442			 struct ieee80211_low_level_stats *stats)443{444	struct p54_common *priv = dev->priv;445 446	memcpy(stats, &priv->stats, sizeof(*stats));447	return 0;448}449 450static void p54_bss_info_changed(struct ieee80211_hw *dev,451				 struct ieee80211_vif *vif,452				 struct ieee80211_bss_conf *info,453				 u64 changed)454{455	struct p54_common *priv = dev->priv;456 457	mutex_lock(&priv->conf_mutex);458	if (changed & BSS_CHANGED_BSSID) {459		memcpy(priv->bssid, info->bssid, ETH_ALEN);460		p54_setup_mac(priv);461	}462 463	if (changed & BSS_CHANGED_BEACON) {464		p54_scan(priv, P54_SCAN_EXIT, 0);465		p54_setup_mac(priv);466		p54_beacon_update(priv, vif);467		p54_set_edcf(priv);468	}469 470	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) {471		priv->use_short_slot = info->use_short_slot;472		p54_set_edcf(priv);473	}474	if (changed & BSS_CHANGED_BASIC_RATES) {475		if (dev->conf.chandef.chan->band == NL80211_BAND_5GHZ)476			priv->basic_rate_mask = (info->basic_rates << 4);477		else478			priv->basic_rate_mask = info->basic_rates;479		p54_setup_mac(priv);480		if (priv->fw_var >= 0x500)481			p54_scan(priv, P54_SCAN_EXIT, 0);482	}483	if (changed & BSS_CHANGED_ASSOC) {484		if (vif->cfg.assoc) {485			priv->aid = vif->cfg.aid;486			priv->wakeup_timer = info->beacon_int *487					     info->dtim_period * 5;488			p54_setup_mac(priv);489		} else {490			priv->wakeup_timer = 500;491			priv->aid = 0;492		}493	}494 495	mutex_unlock(&priv->conf_mutex);496}497 498static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,499		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,500		       struct ieee80211_key_conf *key)501{502	struct p54_common *priv = dev->priv;503	int slot, ret = 0;504	u8 algo = 0;505	u8 *addr = NULL;506 507	if (modparam_nohwcrypt)508		return -EOPNOTSUPP;509 510	if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {511		/*512		 * Unfortunately most/all firmwares are trying to decrypt513		 * incoming management frames if a suitable key can be found.514		 * However, in doing so the data in these frames gets515		 * corrupted. So, we can't have firmware supported crypto516		 * offload in this case.517		 */518		return -EOPNOTSUPP;519	}520 521	mutex_lock(&priv->conf_mutex);522	if (cmd == SET_KEY) {523		switch (key->cipher) {524		case WLAN_CIPHER_SUITE_TKIP:525			if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |526			      BR_DESC_PRIV_CAP_TKIP))) {527				ret = -EOPNOTSUPP;528				goto out_unlock;529			}530			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;531			algo = P54_CRYPTO_TKIPMICHAEL;532			break;533		case WLAN_CIPHER_SUITE_WEP40:534		case WLAN_CIPHER_SUITE_WEP104:535			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {536				ret = -EOPNOTSUPP;537				goto out_unlock;538			}539			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;540			algo = P54_CRYPTO_WEP;541			break;542		case WLAN_CIPHER_SUITE_CCMP:543			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {544				ret = -EOPNOTSUPP;545				goto out_unlock;546			}547			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;548			algo = P54_CRYPTO_AESCCMP;549			break;550		default:551			ret = -EOPNOTSUPP;552			goto out_unlock;553		}554		slot = bitmap_find_free_region(priv->used_rxkeys,555					       priv->rx_keycache_size, 0);556 557		if (slot < 0) {558			/*559			 * The device supports the chosen algorithm, but the560			 * firmware does not provide enough key slots to store561			 * all of them.562			 * But encryption offload for outgoing frames is always563			 * possible, so we just pretend that the upload was564			 * successful and do the decryption in software.565			 */566 567			/* mark the key as invalid. */568			key->hw_key_idx = 0xff;569			goto out_unlock;570		}571 572		key->flags |= IEEE80211_KEY_FLAG_RESERVE_TAILROOM;573	} else {574		slot = key->hw_key_idx;575 576		if (slot == 0xff) {577			/* This key was not uploaded into the rx key cache. */578 579			goto out_unlock;580		}581 582		bitmap_release_region(priv->used_rxkeys, slot, 0);583		algo = 0;584	}585 586	if (sta)587		addr = sta->addr;588 589	ret = p54_upload_key(priv, algo, slot, key->keyidx,590			     key->keylen, addr, key->key);591	if (ret) {592		bitmap_release_region(priv->used_rxkeys, slot, 0);593		ret = -EOPNOTSUPP;594		goto out_unlock;595	}596 597	key->hw_key_idx = slot;598 599out_unlock:600	mutex_unlock(&priv->conf_mutex);601	return ret;602}603 604static int p54_get_survey(struct ieee80211_hw *dev, int idx,605				struct survey_info *survey)606{607	struct p54_common *priv = dev->priv;608	struct ieee80211_channel *chan;609	int err, tries;610	bool in_use = false;611 612	if (idx >= priv->chan_num)613		return -ENOENT;614 615#define MAX_TRIES 1616	for (tries = 0; tries < MAX_TRIES; tries++) {617		chan = priv->curchan;618		if (chan && chan->hw_value == idx) {619			mutex_lock(&priv->conf_mutex);620			err = p54_wait_for_stats(dev);621			mutex_unlock(&priv->conf_mutex);622			if (err)623				return err;624 625			in_use = true;626		}627 628		memcpy(survey, &priv->survey[idx], sizeof(*survey));629 630		if (in_use) {631			/* test if the reported statistics are valid. */632			if  (survey->time != 0) {633				survey->filled |= SURVEY_INFO_IN_USE;634			} else {635				/*636				 * hw/fw has not accumulated enough sample sets.637				 * Wait for 100ms, this ought to be enough to638				 * get at least one non-null set of channel639				 * usage statistics.640				 */641				msleep(100);642				continue;643			}644		}645		return 0;646	}647	return -ETIMEDOUT;648#undef MAX_TRIES649}650 651static unsigned int p54_flush_count(struct p54_common *priv)652{653	unsigned int total = 0, i;654 655	BUILD_BUG_ON(P54_QUEUE_NUM > ARRAY_SIZE(priv->tx_stats));656 657	/*658	 * Because the firmware has the sole control over any frames659	 * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they660	 * don't really count as pending or active.661	 */662	for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++)663		total += priv->tx_stats[i].len;664	return total;665}666 667static void p54_flush(struct ieee80211_hw *dev, struct ieee80211_vif *vif,668		      u32 queues, bool drop)669{670	struct p54_common *priv = dev->priv;671	unsigned int total, i;672 673	/*674	 * Currently, it wouldn't really matter if we wait for one second675	 * or 15 minutes. But once someone gets around and completes the676	 * TODOs [ancel stuck frames / reset device] in p54_work, it will677	 * suddenly make sense to wait that long.678	 */679	i = P54_STATISTICS_UPDATE * 2 / 20;680 681	/*682	 * In this case no locking is required because as we speak the683	 * queues have already been stopped and no new frames can sneak684	 * up from behind.685	 */686	while ((total = p54_flush_count(priv)) && i--) {687		/* waste time */688		msleep(20);689	}690 691	WARN(total, "tx flush timeout, unresponsive firmware");692}693 694static void p54_set_coverage_class(struct ieee80211_hw *dev,695				   s16 coverage_class)696{697	struct p54_common *priv = dev->priv;698 699	mutex_lock(&priv->conf_mutex);700	/* support all coverage class values as in 802.11-2007 Table 7-27 */701	priv->coverage_class = clamp_t(u8, coverage_class, 0, 31);702	p54_set_edcf(priv);703	mutex_unlock(&priv->conf_mutex);704}705 706static const struct ieee80211_ops p54_ops = {707	.add_chanctx = ieee80211_emulate_add_chanctx,708	.remove_chanctx = ieee80211_emulate_remove_chanctx,709	.change_chanctx = ieee80211_emulate_change_chanctx,710	.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,711	.tx			= p54_tx_80211,712	.wake_tx_queue		= ieee80211_handle_wake_tx_queue,713	.start			= p54_start,714	.stop			= p54_stop,715	.add_interface		= p54_add_interface,716	.remove_interface	= p54_remove_interface,717	.set_tim		= p54_set_tim,718	.sta_notify		= p54_sta_notify,719	.sta_add		= p54_sta_add_remove,720	.sta_remove		= p54_sta_add_remove,721	.set_key		= p54_set_key,722	.config			= p54_config,723	.flush			= p54_flush,724	.bss_info_changed	= p54_bss_info_changed,725	.prepare_multicast	= p54_prepare_multicast,726	.configure_filter	= p54_configure_filter,727	.conf_tx		= p54_conf_tx,728	.get_stats		= p54_get_stats,729	.get_survey		= p54_get_survey,730	.set_coverage_class	= p54_set_coverage_class,731};732 733struct ieee80211_hw *p54_init_common(size_t priv_data_len)734{735	struct ieee80211_hw *dev;736	struct p54_common *priv;737 738	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);739	if (!dev)740		return NULL;741 742	priv = dev->priv;743	priv->hw = dev;744	priv->mode = NL80211_IFTYPE_UNSPECIFIED;745	priv->basic_rate_mask = 0x15f;746	spin_lock_init(&priv->tx_stats_lock);747	skb_queue_head_init(&priv->tx_queue);748	skb_queue_head_init(&priv->tx_pending);749	ieee80211_hw_set(dev, REPORTS_TX_ACK_STATUS);750	ieee80211_hw_set(dev, MFP_CAPABLE);751	ieee80211_hw_set(dev, PS_NULLFUNC_STACK);752	ieee80211_hw_set(dev, SUPPORTS_PS);753	ieee80211_hw_set(dev, RX_INCLUDES_FCS);754	ieee80211_hw_set(dev, SIGNAL_DBM);755 756	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |757				      BIT(NL80211_IFTYPE_ADHOC) |758				      BIT(NL80211_IFTYPE_AP) |759				      BIT(NL80211_IFTYPE_MESH_POINT);760 761	priv->beacon_req_id = cpu_to_le32(0);762	priv->tx_stats[P54_QUEUE_BEACON].limit = 1;763	priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;764	priv->tx_stats[P54_QUEUE_MGMT].limit = 3;765	priv->tx_stats[P54_QUEUE_CAB].limit = 3;766	priv->tx_stats[P54_QUEUE_DATA].limit = 5;767	dev->queues = 1;768	priv->noise = -94;769	/*770	 * We support at most 8 tries no matter which rate they're at,771	 * we cannot support max_rates * max_rate_tries as we set it772	 * here, but setting it correctly to 4/2 or so would limit us773	 * artificially if the RC algorithm wants just two rates, so774	 * let's say 4/7, we'll redistribute it at TX time, see the775	 * comments there.776	 */777	dev->max_rates = 4;778	dev->max_rate_tries = 7;779	dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +780				 sizeof(struct p54_tx_data);781 782	/*783	 * For now, disable PS by default because it affects784	 * link stability significantly.785	 */786	dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;787 788	mutex_init(&priv->conf_mutex);789	mutex_init(&priv->eeprom_mutex);790	init_completion(&priv->stat_comp);791	init_completion(&priv->eeprom_comp);792	init_completion(&priv->beacon_comp);793	INIT_DELAYED_WORK(&priv->work, p54_work);794 795	eth_broadcast_addr(priv->mc_maclist[0]);796	priv->curchan = NULL;797	p54_reset_stats(priv);798	return dev;799}800EXPORT_SYMBOL_GPL(p54_init_common);801 802int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)803{804	struct p54_common __maybe_unused *priv = dev->priv;805	int err;806 807	err = ieee80211_register_hw(dev);808	if (err) {809		dev_err(pdev, "Cannot register device (%d).\n", err);810		return err;811	}812	priv->registered = true;813 814#ifdef CONFIG_P54_LEDS815	err = p54_init_leds(priv);816	if (err) {817		p54_unregister_common(dev);818		return err;819	}820#endif /* CONFIG_P54_LEDS */821 822	dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy));823	return 0;824}825EXPORT_SYMBOL_GPL(p54_register_common);826 827void p54_free_common(struct ieee80211_hw *dev)828{829	struct p54_common *priv = dev->priv;830	unsigned int i;831 832	for (i = 0; i < NUM_NL80211_BANDS; i++)833		kfree(priv->band_table[i]);834 835	kfree(priv->iq_autocal);836	kfree(priv->output_limit);837	kfree(priv->curve_data);838	kfree(priv->rssi_db);839	bitmap_free(priv->used_rxkeys);840	kfree(priv->survey);841	priv->iq_autocal = NULL;842	priv->output_limit = NULL;843	priv->curve_data = NULL;844	priv->rssi_db = NULL;845	priv->used_rxkeys = NULL;846	priv->survey = NULL;847	ieee80211_free_hw(dev);848}849EXPORT_SYMBOL_GPL(p54_free_common);850 851void p54_unregister_common(struct ieee80211_hw *dev)852{853	struct p54_common *priv = dev->priv;854 855	if (priv->registered) {856		priv->registered = false;857#ifdef CONFIG_P54_LEDS858		p54_unregister_leds(priv);859#endif /* CONFIG_P54_LEDS */860		ieee80211_unregister_hw(dev);861	}862 863	mutex_destroy(&priv->conf_mutex);864	mutex_destroy(&priv->eeprom_mutex);865}866EXPORT_SYMBOL_GPL(p54_unregister_common);867