brintos

brintos / linux-shallow public Read only

0
0
Text · 43.4 KiB · 5b1d356 Raw
1737 lines · c
1/*2 * Copyright (c) 2010 Broadcom Corporation3 * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>4 *5 * Permission to use, copy, modify, and/or distribute this software for any6 * purpose with or without fee is hereby granted, provided that the above7 * copyright notice and this permission notice appear in all copies.8 *9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.16 */17 18#define __UNDEF_NO_VERSION__19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt20 21#include <linux/etherdevice.h>22#include <linux/sched.h>23#include <linux/firmware.h>24#include <linux/interrupt.h>25#include <linux/module.h>26#include <linux/bcma/bcma.h>27#include <net/mac80211.h>28#include <defs.h>29#include "phy/phy_int.h"30#include "d11.h"31#include "channel.h"32#include "scb.h"33#include "pub.h"34#include "ucode_loader.h"35#include "mac80211_if.h"36#include "main.h"37#include "debug.h"38#include "led.h"39 40#define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */41#define BRCMS_FLUSH_TIMEOUT	500 /* msec */42 43/* Flags we support */44#define MAC_FILTERS (FIF_ALLMULTI | \45	FIF_FCSFAIL | \46	FIF_CONTROL | \47	FIF_OTHER_BSS | \48	FIF_BCN_PRBRESP_PROMISC | \49	FIF_PSPOLL)50 51#define CHAN2GHZ(channel, freqency, chflags)  { \52	.band = NL80211_BAND_2GHZ, \53	.center_freq = (freqency), \54	.hw_value = (channel), \55	.flags = chflags, \56	.max_antenna_gain = 0, \57	.max_power = 19, \58}59 60#define CHAN5GHZ(channel, chflags)  { \61	.band = NL80211_BAND_5GHZ, \62	.center_freq = 5000 + 5*(channel), \63	.hw_value = (channel), \64	.flags = chflags, \65	.max_antenna_gain = 0, \66	.max_power = 21, \67}68 69#define RATE(rate100m, _flags) { \70	.bitrate = (rate100m), \71	.flags = (_flags), \72	.hw_value = (rate100m / 5), \73}74 75struct firmware_hdr {76	__le32 offset;77	__le32 len;78	__le32 idx;79};80 81static const char * const brcms_firmwares[MAX_FW_IMAGES] = {82	"brcm/bcm43xx",83	NULL84};85 86static int n_adapters_found;87 88MODULE_AUTHOR("Broadcom Corporation");89MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");90MODULE_LICENSE("Dual BSD/GPL");91/* This needs to be adjusted when brcms_firmwares changes */92MODULE_FIRMWARE("brcm/bcm43xx-0.fw");93MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw");94 95/* recognized BCMA Core IDs */96static struct bcma_device_id brcms_coreid_table[] = {97	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS),98	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),99	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),100	{},101};102MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);103 104#if defined(CONFIG_BRCMDBG)105/*106 * Module parameter for setting the debug message level. Available107 * flags are specified by the BRCM_DL_* macros in108 * drivers/net/wireless/brcm80211/include/defs.h.109 */110module_param_named(debug, brcm_msg_level, uint, 0644);111#endif112 113static struct ieee80211_channel brcms_2ghz_chantable[] = {114	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),115	CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),116	CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),117	CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),118	CHAN2GHZ(5, 2432, 0),119	CHAN2GHZ(6, 2437, 0),120	CHAN2GHZ(7, 2442, 0),121	CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),122	CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),123	CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),124	CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),125	CHAN2GHZ(12, 2467,126		 IEEE80211_CHAN_NO_IR |127		 IEEE80211_CHAN_NO_HT40PLUS),128	CHAN2GHZ(13, 2472,129		 IEEE80211_CHAN_NO_IR |130		 IEEE80211_CHAN_NO_HT40PLUS),131	CHAN2GHZ(14, 2484,132		 IEEE80211_CHAN_NO_IR |133		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS |134		 IEEE80211_CHAN_NO_OFDM)135};136 137static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {138	/* UNII-1 */139	CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),140	CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),141	CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),142	CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),143	/* UNII-2 */144	CHAN5GHZ(52,145		 IEEE80211_CHAN_RADAR |146		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),147	CHAN5GHZ(56,148		 IEEE80211_CHAN_RADAR |149		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),150	CHAN5GHZ(60,151		 IEEE80211_CHAN_RADAR |152		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),153	CHAN5GHZ(64,154		 IEEE80211_CHAN_RADAR |155		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),156	/* MID */157	CHAN5GHZ(100,158		 IEEE80211_CHAN_RADAR |159		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),160	CHAN5GHZ(104,161		 IEEE80211_CHAN_RADAR |162		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),163	CHAN5GHZ(108,164		 IEEE80211_CHAN_RADAR |165		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),166	CHAN5GHZ(112,167		 IEEE80211_CHAN_RADAR |168		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),169	CHAN5GHZ(116,170		 IEEE80211_CHAN_RADAR |171		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),172	CHAN5GHZ(120,173		 IEEE80211_CHAN_RADAR |174		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),175	CHAN5GHZ(124,176		 IEEE80211_CHAN_RADAR |177		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),178	CHAN5GHZ(128,179		 IEEE80211_CHAN_RADAR |180		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),181	CHAN5GHZ(132,182		 IEEE80211_CHAN_RADAR |183		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),184	CHAN5GHZ(136,185		 IEEE80211_CHAN_RADAR |186		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),187	CHAN5GHZ(140,188		 IEEE80211_CHAN_RADAR |189		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS |190		 IEEE80211_CHAN_NO_HT40MINUS),191	/* UNII-3 */192	CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),193	CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),194	CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),195	CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),196	CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)197};198 199/*200 * The rate table is used for both 2.4G and 5G rates. The201 * latter being a subset as it does not support CCK rates.202 */203static struct ieee80211_rate legacy_ratetable[] = {204	RATE(10, 0),205	RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),206	RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),207	RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),208	RATE(60, 0),209	RATE(90, 0),210	RATE(120, 0),211	RATE(180, 0),212	RATE(240, 0),213	RATE(360, 0),214	RATE(480, 0),215	RATE(540, 0),216};217 218static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = {219	.band = NL80211_BAND_2GHZ,220	.channels = brcms_2ghz_chantable,221	.n_channels = ARRAY_SIZE(brcms_2ghz_chantable),222	.bitrates = legacy_ratetable,223	.n_bitrates = ARRAY_SIZE(legacy_ratetable),224	.ht_cap = {225		   /* from include/linux/ieee80211.h */226		   .cap = IEEE80211_HT_CAP_GRN_FLD |227			  IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40,228		   .ht_supported = true,229		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,230		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,231		   .mcs = {232			   /* placeholders for now */233			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},234			   .rx_highest = cpu_to_le16(500),235			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}236		   }237};238 239static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = {240	.band = NL80211_BAND_5GHZ,241	.channels = brcms_5ghz_nphy_chantable,242	.n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),243	.bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET,244	.n_bitrates = ARRAY_SIZE(legacy_ratetable) -245			BRCMS_LEGACY_5G_RATE_OFFSET,246	.ht_cap = {247		   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |248			  IEEE80211_HT_CAP_SGI_40,249		   .ht_supported = true,250		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,251		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,252		   .mcs = {253			   /* placeholders for now */254			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},255			   .rx_highest = cpu_to_le16(500),256			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}257		   }258};259 260/* flags the given rate in rateset as requested */261static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)262{263	u32 i;264 265	for (i = 0; i < rs->count; i++) {266		if (rate != (rs->rates[i] & 0x7f))267			continue;268 269		if (is_br)270			rs->rates[i] |= BRCMS_RATE_FLAG;271		else272			rs->rates[i] &= BRCMS_RATE_MASK;273		return;274	}275}276 277/*278 * This function frees the WL per-device resources.279 *280 * This function frees resources owned by the WL device pointed to281 * by the wl parameter.282 *283 * precondition: can both be called locked and unlocked284 */285static void brcms_free(struct brcms_info *wl)286{287	struct brcms_timer *t, *next;288 289	/* free ucode data */290	if (wl->fw.fw_cnt)291		brcms_ucode_data_free(&wl->ucode);292	if (wl->irq)293		free_irq(wl->irq, wl);294 295	/* kill dpc */296	tasklet_kill(&wl->tasklet);297 298	if (wl->pub) {299		brcms_debugfs_detach(wl->pub);300		brcms_c_module_unregister(wl->pub, "linux", wl);301	}302 303	/* free common resources */304	if (wl->wlc) {305		brcms_c_detach(wl->wlc);306		wl->wlc = NULL;307		wl->pub = NULL;308	}309 310	/* virtual interface deletion is deferred so we cannot spinwait */311 312	/* wait for all pending callbacks to complete */313	while (atomic_read(&wl->callbacks) > 0)314		schedule();315 316	/* free timers */317	for (t = wl->timers; t; t = next) {318		next = t->next;319#ifdef DEBUG320		kfree(t->name);321#endif322		kfree(t);323	}324}325 326/*327* called from both kernel as from this kernel module (error flow on attach)328* precondition: perimeter lock is not acquired.329*/330static void brcms_remove(struct bcma_device *pdev)331{332	struct ieee80211_hw *hw = bcma_get_drvdata(pdev);333	struct brcms_info *wl = hw->priv;334 335	if (wl->wlc) {336		brcms_led_unregister(wl);337		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);338		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);339		ieee80211_unregister_hw(hw);340	}341 342	brcms_free(wl);343 344	bcma_set_drvdata(pdev, NULL);345	ieee80211_free_hw(hw);346}347 348/*349 * Precondition: Since this function is called in brcms_pci_probe() context,350 * no locking is required.351 */352static void brcms_release_fw(struct brcms_info *wl)353{354	int i;355	for (i = 0; i < MAX_FW_IMAGES; i++) {356		release_firmware(wl->fw.fw_bin[i]);357		release_firmware(wl->fw.fw_hdr[i]);358	}359}360 361/*362 * Precondition: Since this function is called in brcms_pci_probe() context,363 * no locking is required.364 */365static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)366{367	int status;368	struct device *device = &pdev->dev;369	char fw_name[100];370	int i;371 372	memset(&wl->fw, 0, sizeof(struct brcms_firmware));373	for (i = 0; i < MAX_FW_IMAGES; i++) {374		if (brcms_firmwares[i] == NULL)375			break;376		sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],377			UCODE_LOADER_API_VER);378		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);379		if (status) {380			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",381				  KBUILD_MODNAME, fw_name);382			return status;383		}384		sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],385			UCODE_LOADER_API_VER);386		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);387		if (status) {388			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",389				  KBUILD_MODNAME, fw_name);390			return status;391		}392		wl->fw.hdr_num_entries[i] =393		    wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));394	}395	wl->fw.fw_cnt = i;396	status = brcms_ucode_data_init(wl, &wl->ucode);397	brcms_release_fw(wl);398	return status;399}400 401static void brcms_ops_tx(struct ieee80211_hw *hw,402			 struct ieee80211_tx_control *control,403			 struct sk_buff *skb)404{405	struct brcms_info *wl = hw->priv;406	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);407 408	spin_lock_bh(&wl->lock);409	if (!wl->pub->up) {410		brcms_err(wl->wlc->hw->d11core, "ops->tx called while down\n");411		kfree_skb(skb);412		goto done;413	}414	if (brcms_c_sendpkt_mac80211(wl->wlc, skb, hw))415		tx_info->rate_driver_data[0] = control->sta;416 done:417	spin_unlock_bh(&wl->lock);418}419 420static int brcms_ops_start(struct ieee80211_hw *hw)421{422	struct brcms_info *wl = hw->priv;423	bool blocked;424	int err;425 426	if (!wl->ucode.bcm43xx_bomminor) {427		err = brcms_request_fw(wl, wl->wlc->hw->d11core);428		if (err)429			return -ENOENT;430	}431 432	ieee80211_wake_queues(hw);433	spin_lock_bh(&wl->lock);434	blocked = brcms_rfkill_set_hw_state(wl);435	spin_unlock_bh(&wl->lock);436	if (!blocked)437		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);438 439	spin_lock_bh(&wl->lock);440	/* avoid acknowledging frames before a non-monitor device is added */441	wl->mute_tx = true;442 443	if (!wl->pub->up)444		if (!blocked)445			err = brcms_up(wl);446		else447			err = -ERFKILL;448	else449		err = -ENODEV;450	spin_unlock_bh(&wl->lock);451 452	if (err != 0)453		brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",454			  __func__, err);455 456	bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, true);457	return err;458}459 460static void brcms_ops_stop(struct ieee80211_hw *hw, bool suspend)461{462	struct brcms_info *wl = hw->priv;463	int status;464 465	ieee80211_stop_queues(hw);466 467	if (wl->wlc == NULL)468		return;469 470	spin_lock_bh(&wl->lock);471	status = brcms_c_chipmatch(wl->wlc->hw->d11core);472	spin_unlock_bh(&wl->lock);473	if (!status) {474		brcms_err(wl->wlc->hw->d11core,475			  "wl: brcms_ops_stop: chipmatch failed\n");476		return;477	}478 479	bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, false);480 481	/* put driver in down state */482	spin_lock_bh(&wl->lock);483	brcms_down(wl);484	spin_unlock_bh(&wl->lock);485}486 487static int488brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)489{490	struct brcms_info *wl = hw->priv;491 492	/* Just STA, AP and ADHOC for now */493	if (vif->type != NL80211_IFTYPE_STATION &&494	    vif->type != NL80211_IFTYPE_AP &&495	    vif->type != NL80211_IFTYPE_ADHOC) {496		brcms_err(wl->wlc->hw->d11core,497			  "%s: Attempt to add type %d, only STA, AP and AdHoc for now\n",498			  __func__, vif->type);499		return -EOPNOTSUPP;500	}501 502	spin_lock_bh(&wl->lock);503	wl->wlc->vif = vif;504	wl->mute_tx = false;505	brcms_c_mute(wl->wlc, false);506	if (vif->type == NL80211_IFTYPE_STATION)507		brcms_c_start_station(wl->wlc, vif->addr);508	else if (vif->type == NL80211_IFTYPE_AP)509		brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid,510				 vif->cfg.ssid, vif->cfg.ssid_len);511	else if (vif->type == NL80211_IFTYPE_ADHOC)512		brcms_c_start_adhoc(wl->wlc, vif->addr);513	spin_unlock_bh(&wl->lock);514 515	return 0;516}517 518static void519brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)520{521	struct brcms_info *wl = hw->priv;522 523	spin_lock_bh(&wl->lock);524	wl->wlc->vif = NULL;525	spin_unlock_bh(&wl->lock);526}527 528static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)529{530	struct ieee80211_conf *conf = &hw->conf;531	struct brcms_info *wl = hw->priv;532	struct bcma_device *core = wl->wlc->hw->d11core;533	int err = 0;534	int new_int;535 536	spin_lock_bh(&wl->lock);537	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {538		brcms_c_set_beacon_listen_interval(wl->wlc,539						   conf->listen_interval);540	}541	if (changed & IEEE80211_CONF_CHANGE_MONITOR)542		brcms_dbg_info(core, "%s: change monitor mode: %s\n",543			       __func__, conf->flags & IEEE80211_CONF_MONITOR ?544			       "true" : "false");545	if (changed & IEEE80211_CONF_CHANGE_PS)546		brcms_err(core, "%s: change power-save mode: %s (implement)\n",547			  __func__, conf->flags & IEEE80211_CONF_PS ?548			  "true" : "false");549 550	if (changed & IEEE80211_CONF_CHANGE_POWER) {551		err = brcms_c_set_tx_power(wl->wlc, conf->power_level);552		if (err < 0) {553			brcms_err(core, "%s: Error setting power_level\n",554				  __func__);555			goto config_out;556		}557		new_int = brcms_c_get_tx_power(wl->wlc);558		if (new_int != conf->power_level)559			brcms_err(core,560				  "%s: Power level req != actual, %d %d\n",561				  __func__, conf->power_level,562				  new_int);563	}564	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {565		if (conf->chandef.width == NL80211_CHAN_WIDTH_20 ||566		    conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)567			err = brcms_c_set_channel(wl->wlc,568						  conf->chandef.chan->hw_value);569		else570			err = -ENOTSUPP;571	}572	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)573		err = brcms_c_set_rate_limit(wl->wlc,574					     conf->short_frame_max_tx_count,575					     conf->long_frame_max_tx_count);576 577 config_out:578	spin_unlock_bh(&wl->lock);579	return err;580}581 582static void583brcms_ops_bss_info_changed(struct ieee80211_hw *hw,584			struct ieee80211_vif *vif,585			struct ieee80211_bss_conf *info, u64 changed)586{587	struct brcms_info *wl = hw->priv;588	struct bcma_device *core = wl->wlc->hw->d11core;589 590	if (changed & BSS_CHANGED_ASSOC) {591		/* association status changed (associated/disassociated)592		 * also implies a change in the AID.593		 */594		brcms_err(core, "%s: %s: %sassociated\n", KBUILD_MODNAME,595			  __func__, vif->cfg.assoc ? "" : "dis");596		spin_lock_bh(&wl->lock);597		brcms_c_associate_upd(wl->wlc, vif->cfg.assoc);598		spin_unlock_bh(&wl->lock);599	}600	if (changed & BSS_CHANGED_ERP_SLOT) {601		s8 val;602 603		/* slot timing changed */604		if (info->use_short_slot)605			val = 1;606		else607			val = 0;608		spin_lock_bh(&wl->lock);609		brcms_c_set_shortslot_override(wl->wlc, val);610		spin_unlock_bh(&wl->lock);611	}612 613	if (changed & BSS_CHANGED_HT) {614		/* 802.11n parameters changed */615		u16 mode = info->ht_operation_mode;616 617		spin_lock_bh(&wl->lock);618		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG,619			mode & IEEE80211_HT_OP_MODE_PROTECTION);620		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF,621			mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);622		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS,623			mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);624		spin_unlock_bh(&wl->lock);625	}626	if (changed & BSS_CHANGED_BASIC_RATES) {627		struct ieee80211_supported_band *bi;628		u32 br_mask, i;629		u16 rate;630		struct brcm_rateset rs;631		int error;632 633		/* retrieve the current rates */634		spin_lock_bh(&wl->lock);635		brcms_c_get_current_rateset(wl->wlc, &rs);636		spin_unlock_bh(&wl->lock);637 638		br_mask = info->basic_rates;639		bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)];640		for (i = 0; i < bi->n_bitrates; i++) {641			/* convert to internal rate value */642			rate = (bi->bitrates[i].bitrate << 1) / 10;643 644			/* set/clear basic rate flag */645			brcms_set_basic_rate(&rs, rate, br_mask & 1);646			br_mask >>= 1;647		}648 649		/* update the rate set */650		spin_lock_bh(&wl->lock);651		error = brcms_c_set_rateset(wl->wlc, &rs);652		spin_unlock_bh(&wl->lock);653		if (error)654			brcms_err(core, "changing basic rates failed: %d\n",655				  error);656	}657	if (changed & BSS_CHANGED_BEACON_INT) {658		/* Beacon interval changed */659		spin_lock_bh(&wl->lock);660		brcms_c_set_beacon_period(wl->wlc, info->beacon_int);661		spin_unlock_bh(&wl->lock);662	}663	if (changed & BSS_CHANGED_BSSID) {664		/* BSSID changed, for whatever reason (IBSS and managed mode) */665		spin_lock_bh(&wl->lock);666		brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);667		spin_unlock_bh(&wl->lock);668	}669	if (changed & BSS_CHANGED_SSID) {670		/* BSSID changed, for whatever reason (IBSS and managed mode) */671		spin_lock_bh(&wl->lock);672		brcms_c_set_ssid(wl->wlc, vif->cfg.ssid, vif->cfg.ssid_len);673		spin_unlock_bh(&wl->lock);674	}675	if (changed & BSS_CHANGED_BEACON) {676		/* Beacon data changed, retrieve new beacon (beaconing modes) */677		struct sk_buff *beacon;678		u16 tim_offset = 0;679 680		spin_lock_bh(&wl->lock);681		beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL, 0);682		brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset,683				       info->dtim_period);684		spin_unlock_bh(&wl->lock);685	}686 687	if (changed & BSS_CHANGED_AP_PROBE_RESP) {688		struct sk_buff *probe_resp;689 690		spin_lock_bh(&wl->lock);691		probe_resp = ieee80211_proberesp_get(hw, vif);692		brcms_c_set_new_probe_resp(wl->wlc, probe_resp);693		spin_unlock_bh(&wl->lock);694	}695 696	if (changed & BSS_CHANGED_BEACON_ENABLED) {697		/* Beaconing should be enabled/disabled (beaconing modes) */698		brcms_err(core, "%s: Beacon enabled: %s\n", __func__,699			  info->enable_beacon ? "true" : "false");700		if (info->enable_beacon &&701		    hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) {702			brcms_c_enable_probe_resp(wl->wlc, true);703		} else {704			brcms_c_enable_probe_resp(wl->wlc, false);705		}706	}707 708	if (changed & BSS_CHANGED_CQM) {709		/* Connection quality monitor config changed */710		brcms_err(core, "%s: cqm change: threshold %d, hys %d "711			  " (implement)\n", __func__, info->cqm_rssi_thold,712			  info->cqm_rssi_hyst);713	}714 715	if (changed & BSS_CHANGED_IBSS) {716		/* IBSS join status changed */717		brcms_err(core, "%s: IBSS joined: %s (implement)\n",718			  __func__, vif->cfg.ibss_joined ? "true" : "false");719	}720 721	if (changed & BSS_CHANGED_ARP_FILTER) {722		/* Hardware ARP filter address list or state changed */723		brcms_err(core, "%s: arp filtering: %d addresses"724			  " (implement)\n", __func__, vif->cfg.arp_addr_cnt);725	}726 727	if (changed & BSS_CHANGED_QOS) {728		/*729		 * QoS for this association was enabled/disabled.730		 * Note that it is only ever disabled for station mode.731		 */732		brcms_err(core, "%s: qos enabled: %s (implement)\n",733			  __func__, info->qos ? "true" : "false");734	}735	return;736}737 738static void739brcms_ops_configure_filter(struct ieee80211_hw *hw,740			unsigned int changed_flags,741			unsigned int *total_flags, u64 multicast)742{743	struct brcms_info *wl = hw->priv;744	struct bcma_device *core = wl->wlc->hw->d11core;745 746	changed_flags &= MAC_FILTERS;747	*total_flags &= MAC_FILTERS;748 749	if (changed_flags & FIF_ALLMULTI)750		brcms_dbg_info(core, "FIF_ALLMULTI\n");751	if (changed_flags & FIF_FCSFAIL)752		brcms_dbg_info(core, "FIF_FCSFAIL\n");753	if (changed_flags & FIF_CONTROL)754		brcms_dbg_info(core, "FIF_CONTROL\n");755	if (changed_flags & FIF_OTHER_BSS)756		brcms_dbg_info(core, "FIF_OTHER_BSS\n");757	if (changed_flags & FIF_PSPOLL)758		brcms_dbg_info(core, "FIF_PSPOLL\n");759	if (changed_flags & FIF_BCN_PRBRESP_PROMISC)760		brcms_dbg_info(core, "FIF_BCN_PRBRESP_PROMISC\n");761 762	spin_lock_bh(&wl->lock);763	brcms_c_mac_promisc(wl->wlc, *total_flags);764	spin_unlock_bh(&wl->lock);765	return;766}767 768static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw,769				    struct ieee80211_vif *vif,770				    const u8 *mac_addr)771{772	struct brcms_info *wl = hw->priv;773	spin_lock_bh(&wl->lock);774	brcms_c_scan_start(wl->wlc);775	spin_unlock_bh(&wl->lock);776	return;777}778 779static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw,780				       struct ieee80211_vif *vif)781{782	struct brcms_info *wl = hw->priv;783	spin_lock_bh(&wl->lock);784	brcms_c_scan_stop(wl->wlc);785	spin_unlock_bh(&wl->lock);786	return;787}788 789static int790brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,791		  unsigned int link_id, u16 queue,792		  const struct ieee80211_tx_queue_params *params)793{794	struct brcms_info *wl = hw->priv;795 796	spin_lock_bh(&wl->lock);797	brcms_c_wme_setparams(wl->wlc, queue, params, true);798	spin_unlock_bh(&wl->lock);799 800	return 0;801}802 803static int804brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,805	       struct ieee80211_sta *sta)806{807	struct brcms_info *wl = hw->priv;808	struct scb *scb = &wl->wlc->pri_scb;809 810	brcms_c_init_scb(scb);811 812	wl->pub->global_ampdu = &(scb->scb_ampdu);813	wl->pub->global_ampdu->max_pdu = 16;814 815	/*816	 * minstrel_ht initiates addBA on our behalf by calling817	 * ieee80211_start_tx_ba_session()818	 */819	return 0;820}821 822static int823brcms_ops_ampdu_action(struct ieee80211_hw *hw,824		    struct ieee80211_vif *vif,825		    struct ieee80211_ampdu_params *params)826{827	struct brcms_info *wl = hw->priv;828	struct scb *scb = &wl->wlc->pri_scb;829	int status;830	struct ieee80211_sta *sta = params->sta;831	enum ieee80211_ampdu_mlme_action action = params->action;832	u16 tid = params->tid;833 834	if (WARN_ON(scb->magic != SCB_MAGIC))835		return -EIDRM;836	switch (action) {837	case IEEE80211_AMPDU_RX_START:838		break;839	case IEEE80211_AMPDU_RX_STOP:840		break;841	case IEEE80211_AMPDU_TX_START:842		spin_lock_bh(&wl->lock);843		status = brcms_c_aggregatable(wl->wlc, tid);844		spin_unlock_bh(&wl->lock);845		if (!status) {846			brcms_dbg_ht(wl->wlc->hw->d11core,847				     "START: tid %d is not agg\'able\n", tid);848			return -EINVAL;849		}850		return IEEE80211_AMPDU_TX_START_IMMEDIATE;851 852	case IEEE80211_AMPDU_TX_STOP_CONT:853	case IEEE80211_AMPDU_TX_STOP_FLUSH:854	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:855		spin_lock_bh(&wl->lock);856		brcms_c_ampdu_flush(wl->wlc, sta, tid);857		spin_unlock_bh(&wl->lock);858		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);859		break;860	case IEEE80211_AMPDU_TX_OPERATIONAL:861		/*862		 * BA window size from ADDBA response ('buf_size') defines how863		 * many outstanding MPDUs are allowed for the BA stream by864		 * recipient and traffic class (this is actually unused by the865		 * rest of the driver). 'ampdu_factor' gives maximum AMPDU size.866		 */867		spin_lock_bh(&wl->lock);868		brcms_c_ampdu_tx_operational(wl->wlc, tid,869			(1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +870			 sta->deflink.ht_cap.ampdu_factor)) - 1);871		spin_unlock_bh(&wl->lock);872		/* Power save wakeup */873		break;874	default:875		brcms_err(wl->wlc->hw->d11core,876			  "%s: Invalid command, ignoring\n", __func__);877	}878 879	return 0;880}881 882static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)883{884	struct brcms_info *wl = hw->priv;885	bool blocked;886 887	spin_lock_bh(&wl->lock);888	blocked = brcms_c_check_radio_disabled(wl->wlc);889	spin_unlock_bh(&wl->lock);890 891	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);892}893 894static bool brcms_tx_flush_completed(struct brcms_info *wl)895{896	bool result;897 898	spin_lock_bh(&wl->lock);899	result = brcms_c_tx_flush_completed(wl->wlc);900	spin_unlock_bh(&wl->lock);901	return result;902}903 904static void brcms_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,905			    u32 queues, bool drop)906{907	struct brcms_info *wl = hw->priv;908	int ret;909 910	no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");911 912	ret = wait_event_timeout(wl->tx_flush_wq,913				 brcms_tx_flush_completed(wl),914				 msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT));915 916	brcms_dbg_mac80211(wl->wlc->hw->d11core,917			   "ret=%d\n", jiffies_to_msecs(ret));918}919 920static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)921{922	struct brcms_info *wl = hw->priv;923	u64 tsf;924 925	spin_lock_bh(&wl->lock);926	tsf = brcms_c_tsf_get(wl->wlc);927	spin_unlock_bh(&wl->lock);928 929	return tsf;930}931 932static void brcms_ops_set_tsf(struct ieee80211_hw *hw,933			   struct ieee80211_vif *vif, u64 tsf)934{935	struct brcms_info *wl = hw->priv;936 937	spin_lock_bh(&wl->lock);938	brcms_c_tsf_set(wl->wlc, tsf);939	spin_unlock_bh(&wl->lock);940}941 942static int brcms_ops_beacon_set_tim(struct ieee80211_hw *hw,943				 struct ieee80211_sta *sta, bool set)944{945	struct brcms_info *wl = hw->priv;946	struct sk_buff *beacon = NULL;947	u16 tim_offset = 0;948 949	spin_lock_bh(&wl->lock);950	if (wl->wlc->vif)951		beacon = ieee80211_beacon_get_tim(hw, wl->wlc->vif,952						  &tim_offset, NULL, 0);953	if (beacon)954		brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset,955				       wl->wlc->vif->bss_conf.dtim_period);956	spin_unlock_bh(&wl->lock);957 958	return 0;959}960 961static const struct ieee80211_ops brcms_ops = {962	.add_chanctx = ieee80211_emulate_add_chanctx,963	.remove_chanctx = ieee80211_emulate_remove_chanctx,964	.change_chanctx = ieee80211_emulate_change_chanctx,965	.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,966	.tx = brcms_ops_tx,967	.wake_tx_queue = ieee80211_handle_wake_tx_queue,968	.start = brcms_ops_start,969	.stop = brcms_ops_stop,970	.add_interface = brcms_ops_add_interface,971	.remove_interface = brcms_ops_remove_interface,972	.config = brcms_ops_config,973	.bss_info_changed = brcms_ops_bss_info_changed,974	.configure_filter = brcms_ops_configure_filter,975	.sw_scan_start = brcms_ops_sw_scan_start,976	.sw_scan_complete = brcms_ops_sw_scan_complete,977	.conf_tx = brcms_ops_conf_tx,978	.sta_add = brcms_ops_sta_add,979	.ampdu_action = brcms_ops_ampdu_action,980	.rfkill_poll = brcms_ops_rfkill_poll,981	.flush = brcms_ops_flush,982	.get_tsf = brcms_ops_get_tsf,983	.set_tsf = brcms_ops_set_tsf,984	.set_tim = brcms_ops_beacon_set_tim,985};986 987void brcms_dpc(struct tasklet_struct *t)988{989	struct brcms_info *wl;990 991	wl = from_tasklet(wl, t, tasklet);992 993	spin_lock_bh(&wl->lock);994 995	/* call the common second level interrupt handler */996	if (wl->pub->up) {997		if (wl->resched) {998			unsigned long flags;999 1000			spin_lock_irqsave(&wl->isr_lock, flags);1001			brcms_c_intrsupd(wl->wlc);1002			spin_unlock_irqrestore(&wl->isr_lock, flags);1003		}1004 1005		wl->resched = brcms_c_dpc(wl->wlc, true);1006	}1007 1008	/* brcms_c_dpc() may bring the driver down */1009	if (!wl->pub->up)1010		goto done;1011 1012	/* re-schedule dpc */1013	if (wl->resched)1014		tasklet_schedule(&wl->tasklet);1015	else1016		/* re-enable interrupts */1017		brcms_intrson(wl);1018 1019 done:1020	spin_unlock_bh(&wl->lock);1021	wake_up(&wl->tx_flush_wq);1022}1023 1024static irqreturn_t brcms_isr(int irq, void *dev_id)1025{1026	struct brcms_info *wl;1027	irqreturn_t ret = IRQ_NONE;1028 1029	wl = (struct brcms_info *) dev_id;1030 1031	spin_lock(&wl->isr_lock);1032 1033	/* call common first level interrupt handler */1034	if (brcms_c_isr(wl->wlc)) {1035		/* schedule second level handler */1036		tasklet_schedule(&wl->tasklet);1037		ret = IRQ_HANDLED;1038	}1039 1040	spin_unlock(&wl->isr_lock);1041 1042	return ret;1043}1044 1045/*1046 * is called in brcms_pci_probe() context, therefore no locking required.1047 */1048static int ieee_hw_rate_init(struct ieee80211_hw *hw)1049{1050	struct brcms_info *wl = hw->priv;1051	struct brcms_c_info *wlc = wl->wlc;1052	struct ieee80211_supported_band *band;1053	u16 phy_type;1054 1055	hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL;1056	hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;1057 1058	phy_type = brcms_c_get_phy_type(wl->wlc, 0);1059	if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {1060		band = &wlc->bandstate[BAND_2G_INDEX]->band;1061		*band = brcms_band_2GHz_nphy_template;1062		if (phy_type == PHY_TYPE_LCN) {1063			/* Single stream */1064			band->ht_cap.mcs.rx_mask[1] = 0;1065			band->ht_cap.mcs.rx_highest = cpu_to_le16(72);1066		}1067		hw->wiphy->bands[NL80211_BAND_2GHZ] = band;1068	} else {1069		return -EPERM;1070	}1071 1072	/* Assume all bands use the same phy.  True for 11n devices. */1073	if (wl->pub->_nbands > 1) {1074		if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {1075			band = &wlc->bandstate[BAND_5G_INDEX]->band;1076			*band = brcms_band_5GHz_nphy_template;1077			hw->wiphy->bands[NL80211_BAND_5GHZ] = band;1078		} else {1079			return -EPERM;1080		}1081	}1082	return 0;1083}1084 1085/*1086 * is called in brcms_pci_probe() context, therefore no locking required.1087 */1088static int ieee_hw_init(struct ieee80211_hw *hw)1089{1090	ieee80211_hw_set(hw, AMPDU_AGGREGATION);1091	ieee80211_hw_set(hw, SIGNAL_DBM);1092	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);1093	ieee80211_hw_set(hw, MFP_CAPABLE);1094 1095	hw->extra_tx_headroom = brcms_c_get_header_len();1096	hw->queues = N_TX_QUEUES;1097	hw->max_rates = 2;	/* Primary rate and 1 fallback rate */1098 1099	/* channel change time is dependent on chip and band  */1100	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |1101				     BIT(NL80211_IFTYPE_AP) |1102				     BIT(NL80211_IFTYPE_ADHOC);1103 1104	/*1105	 * deactivate sending probe responses by ucude, because this will1106	 * cause problems when WPS is used.1107	 *1108	 * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;1109	 */1110 1111	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);1112 1113	hw->rate_control_algorithm = "minstrel_ht";1114 1115	hw->sta_data_size = 0;1116	return ieee_hw_rate_init(hw);1117}1118 1119/*1120 * attach to the WL device.1121 *1122 * Attach to the WL device identified by vendor and device parameters.1123 * regs is a host accessible memory address pointing to WL device registers.1124 *1125 * is called in brcms_bcma_probe() context, therefore no locking required.1126 */1127static struct brcms_info *brcms_attach(struct bcma_device *pdev)1128{1129	struct brcms_info *wl = NULL;1130	int unit, err;1131	struct ieee80211_hw *hw;1132	u8 perm[ETH_ALEN];1133 1134	unit = n_adapters_found;1135	err = 0;1136 1137	if (unit < 0)1138		return NULL;1139 1140	/* allocate private info */1141	hw = bcma_get_drvdata(pdev);1142	if (hw != NULL)1143		wl = hw->priv;1144	if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))1145		return NULL;1146	wl->wiphy = hw->wiphy;1147 1148	atomic_set(&wl->callbacks, 0);1149 1150	init_waitqueue_head(&wl->tx_flush_wq);1151 1152	/* setup the bottom half handler */1153	tasklet_setup(&wl->tasklet, brcms_dpc);1154 1155	spin_lock_init(&wl->lock);1156	spin_lock_init(&wl->isr_lock);1157 1158	/* common load-time initialization */1159	wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);1160	if (!wl->wlc) {1161		wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",1162			  KBUILD_MODNAME, err);1163		goto fail;1164	}1165	wl->pub = brcms_c_pub(wl->wlc);1166 1167	wl->pub->ieee_hw = hw;1168 1169	/* register our interrupt handler */1170	if (request_irq(pdev->irq, brcms_isr,1171			IRQF_SHARED, KBUILD_MODNAME, wl)) {1172		wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);1173		goto fail;1174	}1175	wl->irq = pdev->irq;1176 1177	/* register module */1178	brcms_c_module_register(wl->pub, "linux", wl, NULL);1179 1180	if (ieee_hw_init(hw)) {1181		wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,1182			  __func__);1183		goto fail;1184	}1185 1186	brcms_c_regd_init(wl->wlc);1187 1188	memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);1189	if (WARN_ON(!is_valid_ether_addr(perm)))1190		goto fail;1191	SET_IEEE80211_PERM_ADDR(hw, perm);1192 1193	err = ieee80211_register_hw(hw);1194	if (err)1195		wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"1196			  "%d\n", __func__, err);1197 1198	if (wl->pub->srom_ccode[0] &&1199	    regulatory_hint(wl->wiphy, wl->pub->srom_ccode))1200		wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__);1201 1202	brcms_debugfs_attach(wl->pub);1203	brcms_debugfs_create_files(wl->pub);1204	n_adapters_found++;1205	return wl;1206 1207fail:1208	brcms_free(wl);1209	return NULL;1210}1211 1212 1213 1214/*1215 * determines if a device is a WL device, and if so, attaches it.1216 *1217 * This function determines if a device pointed to by pdev is a WL device,1218 * and if so, performs a brcms_attach() on it.1219 *1220 * Perimeter lock is initialized in the course of this function.1221 */1222static int brcms_bcma_probe(struct bcma_device *pdev)1223{1224	struct brcms_info *wl;1225	struct ieee80211_hw *hw;1226	int ret;1227 1228	dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",1229		 pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,1230		 pdev->irq);1231 1232	if ((pdev->id.manuf != BCMA_MANUF_BCM) ||1233	    (pdev->id.id != BCMA_CORE_80211))1234		return -ENODEV;1235 1236	hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);1237	if (!hw) {1238		pr_err("%s: ieee80211_alloc_hw failed\n", __func__);1239		return -ENOMEM;1240	}1241 1242	SET_IEEE80211_DEV(hw, &pdev->dev);1243 1244	bcma_set_drvdata(pdev, hw);1245 1246	memset(hw->priv, 0, sizeof(*wl));1247 1248	wl = brcms_attach(pdev);1249	if (!wl) {1250		pr_err("%s: brcms_attach failed!\n", __func__);1251		ret = -ENODEV;1252		goto err_free_ieee80211;1253	}1254	brcms_led_register(wl);1255 1256	return 0;1257 1258err_free_ieee80211:1259	ieee80211_free_hw(hw);1260	return ret;1261}1262 1263static int brcms_suspend(struct bcma_device *pdev)1264{1265	struct brcms_info *wl;1266	struct ieee80211_hw *hw;1267 1268	hw = bcma_get_drvdata(pdev);1269	wl = hw->priv;1270	if (!wl) {1271		pr_err("%s: %s: no driver private struct!\n", KBUILD_MODNAME,1272		       __func__);1273		return -ENODEV;1274	}1275 1276	/* only need to flag hw is down for proper resume */1277	spin_lock_bh(&wl->lock);1278	wl->pub->hw_up = false;1279	spin_unlock_bh(&wl->lock);1280 1281	brcms_dbg_info(wl->wlc->hw->d11core, "brcms_suspend ok\n");1282 1283	return 0;1284}1285 1286static int brcms_resume(struct bcma_device *pdev)1287{1288	return 0;1289}1290 1291static struct bcma_driver brcms_bcma_driver = {1292	.name     = KBUILD_MODNAME,1293	.probe    = brcms_bcma_probe,1294	.suspend  = brcms_suspend,1295	.resume   = brcms_resume,1296	.remove   = brcms_remove,1297	.id_table = brcms_coreid_table,1298};1299 1300/*1301 * This is the main entry point for the brcmsmac driver.1302 *1303 * This function is scheduled upon module initialization and1304 * does the driver registration, which result in brcms_bcma_probe()1305 * call resulting in the driver bringup.1306 */1307static void brcms_driver_init(struct work_struct *work)1308{1309	int error;1310 1311	error = bcma_driver_register(&brcms_bcma_driver);1312	if (error)1313		pr_err("%s: register returned %d\n", __func__, error);1314}1315 1316static DECLARE_WORK(brcms_driver_work, brcms_driver_init);1317 1318static int __init brcms_module_init(void)1319{1320	brcms_debugfs_init();1321	if (!schedule_work(&brcms_driver_work))1322		return -EBUSY;1323 1324	return 0;1325}1326 1327/*1328 * This function unloads the brcmsmac driver from the system.1329 *1330 * This function unconditionally unloads the brcmsmac driver module from the1331 * system.1332 *1333 */1334static void __exit brcms_module_exit(void)1335{1336	cancel_work_sync(&brcms_driver_work);1337	bcma_driver_unregister(&brcms_bcma_driver);1338	brcms_debugfs_exit();1339}1340 1341module_init(brcms_module_init);1342module_exit(brcms_module_exit);1343 1344/*1345 * precondition: perimeter lock has been acquired1346 */1347void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,1348			 bool state, int prio)1349{1350	brcms_err(wl->wlc->hw->d11core, "Shouldn't be here %s\n", __func__);1351}1352 1353/*1354 * precondition: perimeter lock has been acquired1355 */1356void brcms_init(struct brcms_info *wl)1357{1358	brcms_dbg_info(wl->wlc->hw->d11core, "Initializing wl%d\n",1359		       wl->pub->unit);1360	brcms_reset(wl);1361	brcms_c_init(wl->wlc, wl->mute_tx);1362}1363 1364/*1365 * precondition: perimeter lock has been acquired1366 */1367uint brcms_reset(struct brcms_info *wl)1368{1369	brcms_dbg_info(wl->wlc->hw->d11core, "Resetting wl%d\n", wl->pub->unit);1370	brcms_c_reset(wl->wlc);1371 1372	/* dpc will not be rescheduled */1373	wl->resched = false;1374 1375	/* inform publicly that interface is down */1376	wl->pub->up = false;1377 1378	return 0;1379}1380 1381void brcms_fatal_error(struct brcms_info *wl)1382{1383	brcms_err(wl->wlc->hw->d11core, "wl%d: fatal error, reinitializing\n",1384		  wl->wlc->pub->unit);1385	brcms_reset(wl);1386	ieee80211_restart_hw(wl->pub->ieee_hw);1387}1388 1389/*1390 * These are interrupt on/off entry points. Disable interrupts1391 * during interrupt state transition.1392 */1393void brcms_intrson(struct brcms_info *wl)1394{1395	unsigned long flags;1396 1397	spin_lock_irqsave(&wl->isr_lock, flags);1398	brcms_c_intrson(wl->wlc);1399	spin_unlock_irqrestore(&wl->isr_lock, flags);1400}1401 1402u32 brcms_intrsoff(struct brcms_info *wl)1403{1404	unsigned long flags;1405	u32 status;1406 1407	spin_lock_irqsave(&wl->isr_lock, flags);1408	status = brcms_c_intrsoff(wl->wlc);1409	spin_unlock_irqrestore(&wl->isr_lock, flags);1410	return status;1411}1412 1413void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask)1414{1415	unsigned long flags;1416 1417	spin_lock_irqsave(&wl->isr_lock, flags);1418	brcms_c_intrsrestore(wl->wlc, macintmask);1419	spin_unlock_irqrestore(&wl->isr_lock, flags);1420}1421 1422/*1423 * precondition: perimeter lock has been acquired1424 */1425int brcms_up(struct brcms_info *wl)1426{1427	int error = 0;1428 1429	if (wl->pub->up)1430		return 0;1431 1432	error = brcms_c_up(wl->wlc);1433 1434	return error;1435}1436 1437/*1438 * precondition: perimeter lock has been acquired1439 */1440void brcms_down(struct brcms_info *wl)1441	__must_hold(&wl->lock)1442{1443	uint callbacks, ret_val = 0;1444 1445	/* call common down function */1446	ret_val = brcms_c_down(wl->wlc);1447	callbacks = atomic_read(&wl->callbacks) - ret_val;1448 1449	/* wait for down callbacks to complete */1450	spin_unlock_bh(&wl->lock);1451 1452	/* For HIGH_only driver, it's important to actually schedule other work,1453	 * not just spin wait since everything runs at schedule level1454	 */1455	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);1456 1457	spin_lock_bh(&wl->lock);1458}1459 1460/*1461* precondition: perimeter lock is not acquired1462 */1463static void _brcms_timer(struct work_struct *work)1464{1465	struct brcms_timer *t = container_of(work, struct brcms_timer,1466					     dly_wrk.work);1467 1468	spin_lock_bh(&t->wl->lock);1469 1470	if (t->set) {1471		if (t->periodic) {1472			atomic_inc(&t->wl->callbacks);1473			ieee80211_queue_delayed_work(t->wl->pub->ieee_hw,1474						     &t->dly_wrk,1475						     msecs_to_jiffies(t->ms));1476		} else {1477			t->set = false;1478		}1479 1480		t->fn(t->arg);1481	}1482 1483	atomic_dec(&t->wl->callbacks);1484 1485	spin_unlock_bh(&t->wl->lock);1486}1487 1488/*1489 * Adds a timer to the list. Caller supplies a timer function.1490 * Is called from wlc.1491 *1492 * precondition: perimeter lock has been acquired1493 */1494struct brcms_timer *brcms_init_timer(struct brcms_info *wl,1495				     void (*fn) (void *arg),1496				     void *arg, const char *name)1497{1498	struct brcms_timer *t;1499 1500	t = kzalloc(sizeof(*t), GFP_ATOMIC);1501	if (!t)1502		return NULL;1503 1504	INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer);1505	t->wl = wl;1506	t->fn = fn;1507	t->arg = arg;1508	t->next = wl->timers;1509	wl->timers = t;1510 1511#ifdef DEBUG1512	t->name = kstrdup(name, GFP_ATOMIC);1513#endif1514 1515	return t;1516}1517 1518/*1519 * adds only the kernel timer since it's going to be more accurate1520 * as well as it's easier to make it periodic1521 *1522 * precondition: perimeter lock has been acquired1523 */1524void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)1525{1526	struct ieee80211_hw *hw = t->wl->pub->ieee_hw;1527 1528#ifdef DEBUG1529	if (t->set)1530		brcms_dbg_info(t->wl->wlc->hw->d11core,1531			       "%s: Already set. Name: %s, per %d\n",1532			       __func__, t->name, periodic);1533#endif1534	t->ms = ms;1535	t->periodic = (bool) periodic;1536	if (!t->set) {1537		t->set = true;1538		atomic_inc(&t->wl->callbacks);1539	}1540 1541	ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));1542}1543 1544/*1545 * return true if timer successfully deleted, false if still pending1546 *1547 * precondition: perimeter lock has been acquired1548 */1549bool brcms_del_timer(struct brcms_timer *t)1550{1551	if (t->set) {1552		t->set = false;1553		if (!cancel_delayed_work(&t->dly_wrk))1554			return false;1555 1556		atomic_dec(&t->wl->callbacks);1557	}1558 1559	return true;1560}1561 1562/*1563 * precondition: perimeter lock has been acquired1564 */1565void brcms_free_timer(struct brcms_timer *t)1566{1567	struct brcms_info *wl = t->wl;1568	struct brcms_timer *tmp;1569 1570	/* delete the timer in case it is active */1571	brcms_del_timer(t);1572 1573	if (wl->timers == t) {1574		wl->timers = wl->timers->next;1575#ifdef DEBUG1576		kfree(t->name);1577#endif1578		kfree(t);1579		return;1580 1581	}1582 1583	tmp = wl->timers;1584	while (tmp) {1585		if (tmp->next == t) {1586			tmp->next = t->next;1587#ifdef DEBUG1588			kfree(t->name);1589#endif1590			kfree(t);1591			return;1592		}1593		tmp = tmp->next;1594	}1595 1596}1597 1598/*1599 * precondition: no locking required1600 */1601int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)1602{1603	int i, entry;1604	const u8 *pdata;1605	struct firmware_hdr *hdr;1606	for (i = 0; i < wl->fw.fw_cnt; i++) {1607		hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;1608		for (entry = 0; entry < wl->fw.hdr_num_entries[i];1609		     entry++, hdr++) {1610			u32 len = le32_to_cpu(hdr->len);1611			if (le32_to_cpu(hdr->idx) == idx) {1612				pdata = wl->fw.fw_bin[i]->data +1613					le32_to_cpu(hdr->offset);1614				*pbuf = kvmemdup(pdata, len, GFP_KERNEL);1615				if (*pbuf == NULL)1616					return -ENOMEM;1617				return 0;1618			}1619		}1620	}1621	brcms_err(wl->wlc->hw->d11core,1622		  "ERROR: ucode buf tag:%d can not be found!\n", idx);1623	*pbuf = NULL;1624	return -ENODATA;1625}1626 1627/*1628 * Precondition: Since this function is called in brcms_bcma_probe() context,1629 * no locking is required.1630 */1631int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)1632{1633	int i, entry;1634	const u8 *pdata;1635	struct firmware_hdr *hdr;1636	for (i = 0; i < wl->fw.fw_cnt; i++) {1637		hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;1638		for (entry = 0; entry < wl->fw.hdr_num_entries[i];1639		     entry++, hdr++) {1640			if (le32_to_cpu(hdr->idx) == idx) {1641				pdata = wl->fw.fw_bin[i]->data +1642					le32_to_cpu(hdr->offset);1643				if (le32_to_cpu(hdr->len) != 4) {1644					brcms_err(wl->wlc->hw->d11core,1645						  "ERROR: fw hdr len\n");1646					return -ENOMSG;1647				}1648				*n_bytes = le32_to_cpu(*((__le32 *) pdata));1649				return 0;1650			}1651		}1652	}1653	brcms_err(wl->wlc->hw->d11core,1654		  "ERROR: ucode tag:%d can not be found!\n", idx);1655	return -ENOMSG;1656}1657 1658/*1659 * precondition: can both be called locked and unlocked1660 */1661void brcms_ucode_free_buf(void *p)1662{1663	kvfree(p);1664}1665 1666/*1667 * checks validity of all firmware images loaded from user space1668 *1669 * Precondition: Since this function is called in brcms_bcma_probe() context,1670 * no locking is required.1671 */1672int brcms_check_firmwares(struct brcms_info *wl)1673{1674	int i;1675	int entry;1676	int rc = 0;1677	const struct firmware *fw;1678	const struct firmware *fw_hdr;1679	struct firmware_hdr *ucode_hdr;1680	for (i = 0; i < MAX_FW_IMAGES && rc == 0; i++) {1681		fw =  wl->fw.fw_bin[i];1682		fw_hdr = wl->fw.fw_hdr[i];1683		if (fw == NULL && fw_hdr == NULL) {1684			break;1685		} else if (fw == NULL || fw_hdr == NULL) {1686			wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n",1687				  __func__);1688			rc = -EBADF;1689		} else if (fw_hdr->size % sizeof(struct firmware_hdr)) {1690			wiphy_err(wl->wiphy, "%s: non integral fw hdr file "1691				"size %zu/%zu\n", __func__, fw_hdr->size,1692				sizeof(struct firmware_hdr));1693			rc = -EBADF;1694		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {1695			wiphy_err(wl->wiphy, "%s: out of bounds fw file size %zu\n",1696				  __func__, fw->size);1697			rc = -EBADF;1698		} else {1699			/* check if ucode section overruns firmware image */1700			ucode_hdr = (struct firmware_hdr *)fw_hdr->data;1701			for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&1702			     !rc; entry++, ucode_hdr++) {1703				if (le32_to_cpu(ucode_hdr->offset) +1704				    le32_to_cpu(ucode_hdr->len) >1705				    fw->size) {1706					wiphy_err(wl->wiphy,1707						  "%s: conflicting bin/hdr\n",1708						  __func__);1709					rc = -EBADF;1710				}1711			}1712		}1713	}1714	if (rc == 0 && wl->fw.fw_cnt != i) {1715		wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__,1716			wl->fw.fw_cnt);1717		rc = -EBADF;1718	}1719	return rc;1720}1721 1722/*1723 * precondition: perimeter lock has been acquired1724 */1725bool brcms_rfkill_set_hw_state(struct brcms_info *wl)1726	__must_hold(&wl->lock)1727{1728	bool blocked = brcms_c_check_radio_disabled(wl->wlc);1729 1730	spin_unlock_bh(&wl->lock);1731	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);1732	if (blocked)1733		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);1734	spin_lock_bh(&wl->lock);1735	return blocked;1736}1737