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