diff options
author | Jeff Garzik <jeff@garzik.org> | 2012-07-25 23:58:48 +0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2012-07-25 23:58:48 +0400 |
commit | 8407884dd9164ec18ed2afc00f56b87e36c51fcf (patch) | |
tree | b6ea42c231d7d39f454de28a068d78ce11709770 /drivers/net/wireless/brcm80211 | |
parent | dc7f71f486f4f5fa96f6dcf86833da020cde8a11 (diff) | |
parent | bdc0077af574800d24318b6945cf2344e8dbb050 (diff) | |
download | linux-8407884dd9164ec18ed2afc00f56b87e36c51fcf.tar.xz |
Merge branch 'master' [vanilla Linus master] into libata-dev.git/upstream
Two bits were appended to the end of the bitfield
list in struct scsi_device. Resolve that conflict
by including both bits.
Conflicts:
include/scsi/scsi_device.h
Diffstat (limited to 'drivers/net/wireless/brcm80211')
27 files changed, 1216 insertions, 1678 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index abb48032753b..9d5170b6df50 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -34,3 +34,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ sdio_chip.o brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ usb.o +brcmfmac-$(CONFIG_BRCMDBG) += \ + dhd_dbg.o
\ No newline at end of file diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 82f51dbd0d66..49765d34b4e0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -44,6 +44,7 @@ #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 +#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 #define SDIO_FUNC1_BLOCKSIZE 64 #define SDIO_FUNC2_BLOCKSIZE 512 @@ -52,6 +53,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, + {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 9f637014486e..a11fe54f5950 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -613,6 +613,9 @@ struct brcmf_pub { struct work_struct multicast_work; u8 macvalue[ETH_ALEN]; atomic_t pend_8021x_cnt; +#ifdef DEBUG + struct dentry *dbgfs_dir; +#endif }; struct brcmf_if_event { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 366916494be4..537f499cc5d2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -36,6 +36,13 @@ struct dngl_stats { unsigned long multicast; /* multicast packets received */ }; +struct brcmf_bus_dcmd { + char *name; + char *param; + int param_len; + struct list_head list; +}; + /* interface structure between common and bus layer */ struct brcmf_bus { u8 type; /* bus type */ @@ -50,6 +57,7 @@ struct brcmf_bus { unsigned long tx_realloc; /* Tx packets realloced for headroom */ struct dngl_stats dstats; /* Stats for dongle-based data */ u8 align; /* bus alignment requirement */ + struct list_head dcmd_list; /* interface functions pointers */ /* Stop bus module: clear pending frames, disable data flow */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 236cb9fa460c..2621dd3d7dcd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -800,13 +800,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ char buf[128], *ptr; - u32 dongle_align = drvr->bus_if->align; - u32 glom = 0; u32 roaming = 1; uint bcn_timeout = 3; int scan_assoc_time = 40; int scan_unassoc_time = 40; int i; + struct brcmf_bus_dcmd *cmdlst; + struct list_head *cur, *q; mutex_lock(&drvr->proto_block); @@ -827,17 +827,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) /* Print fw version info */ brcmf_dbg(ERROR, "Firmware version = %s\n", buf); - /* Match Host and Dongle rx alignment */ - brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, - sizeof(iovbuf)); - brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, - sizeof(iovbuf)); - - /* disable glom option per default */ - brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, - sizeof(iovbuf)); - /* Setup timeout if Beacons are lost and roam is off to report link down */ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, @@ -874,6 +863,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) 0, true); } + /* set bus specific command if there is any */ + list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) { + cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); + if (cmdlst->name && cmdlst->param && cmdlst->param_len) { + brcmf_c_mkiovar(cmdlst->name, cmdlst->param, + cmdlst->param_len, iovbuf, + sizeof(iovbuf)); + brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, + iovbuf, sizeof(iovbuf)); + } + list_del(cur); + kfree(cmdlst); + } + mutex_unlock(&drvr->proto_block); return 0; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c new file mode 100644 index 000000000000..7f89540b56da --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <linux/debugfs.h> +#include <linux/if_ether.h> +#include <linux/if.h> +#include <linux/ieee80211.h> +#include <linux/module.h> + +#include <defs.h> +#include <brcmu_wifi.h> +#include <brcmu_utils.h> +#include "dhd.h" +#include "dhd_bus.h" +#include "dhd_dbg.h" + +static struct dentry *root_folder; + +void brcmf_debugfs_init(void) +{ + root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (IS_ERR(root_folder)) + root_folder = NULL; +} + +void brcmf_debugfs_exit(void) +{ + if (!root_folder) + return; + + debugfs_remove_recursive(root_folder); + root_folder = NULL; +} + +int brcmf_debugfs_attach(struct brcmf_pub *drvr) +{ + if (!root_folder) + return -ENODEV; + + drvr->dbgfs_dir = debugfs_create_dir(dev_name(drvr->dev), root_folder); + return PTR_RET(drvr->dbgfs_dir); +} + +void brcmf_debugfs_detach(struct brcmf_pub *drvr) +{ + if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) + debugfs_remove_recursive(drvr->dbgfs_dir); +} + +struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) +{ + return drvr->dbgfs_dir; +} + +static +ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data, + size_t count, loff_t *ppos) +{ + struct brcmf_sdio_count *sdcnt = f->private_data; + char buf[750]; + int res; + + /* only allow read from start */ + if (*ppos > 0) + return 0; + + res = scnprintf(buf, sizeof(buf), + "intrcount: %u\nlastintrs: %u\n" + "pollcnt: %u\nregfails: %u\n" + "tx_sderrs: %u\nfcqueued: %u\n" + "rxrtx: %u\nrx_toolong: %u\n" + "rxc_errors: %u\nrx_hdrfail: %u\n" + "rx_badhdr: %u\nrx_badseq: %u\n" + "fc_rcvd: %u\nfc_xoff: %u\n" + "fc_xon: %u\nrxglomfail: %u\n" + "rxglomframes: %u\nrxglompkts: %u\n" + "f2rxhdrs: %u\nf2rxdata: %u\n" + "f2txdata: %u\nf1regdata: %u\n" + "tickcnt: %u\ntx_ctlerrs: %lu\n" + "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n" + "rx_ctlpkts: %lu\nrx_readahead: %lu\n", + sdcnt->intrcount, sdcnt->lastintrs, + sdcnt->pollcnt, sdcnt->regfails, + sdcnt->tx_sderrs, sdcnt->fcqueued, + sdcnt->rxrtx, sdcnt->rx_toolong, + sdcnt->rxc_errors, sdcnt->rx_hdrfail, + sdcnt->rx_badhdr, sdcnt->rx_badseq, + sdcnt->fc_rcvd, sdcnt->fc_xoff, + sdcnt->fc_xon, sdcnt->rxglomfail, + sdcnt->rxglomframes, sdcnt->rxglompkts, + sdcnt->f2rxhdrs, sdcnt->f2rxdata, + sdcnt->f2txdata, sdcnt->f1regdata, + sdcnt->tickcnt, sdcnt->tx_ctlerrs, + sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs, + sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt); + + return simple_read_from_buffer(data, count, ppos, buf, res); +} + +static const struct file_operations brcmf_debugfs_sdio_counter_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = brcmf_debugfs_sdio_counter_read +}; + +void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, + struct brcmf_sdio_count *sdcnt) +{ + struct dentry *dentry = drvr->dbgfs_dir; + + if (!IS_ERR_OR_NULL(dentry)) + debugfs_create_file("counters", S_IRUGO, dentry, + sdcnt, &brcmf_debugfs_sdio_counter_ops); +} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index a2c4576cf9ff..b784920532d3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -76,4 +76,63 @@ do { \ extern int brcmf_msg_level; +/* + * hold counter variables used in brcmfmac sdio driver. + */ +struct brcmf_sdio_count { + uint intrcount; /* Count of device interrupt callbacks */ + uint lastintrs; /* Count as of last watchdog timer */ + uint pollcnt; /* Count of active polls */ + uint regfails; /* Count of R_REG failures */ + uint tx_sderrs; /* Count of tx attempts with sd errors */ + uint fcqueued; /* Tx packets that got queued */ + uint rxrtx; /* Count of rtx requests (NAK to dongle) */ + uint rx_toolong; /* Receive frames too long to receive */ + uint rxc_errors; /* SDIO errors when reading control frames */ + uint rx_hdrfail; /* SDIO errors on header reads */ + uint rx_badhdr; /* Bad received headers (roosync?) */ + uint rx_badseq; /* Mismatched rx sequence number */ + uint fc_rcvd; /* Number of flow-control events received */ + uint fc_xoff; /* Number which turned on flow-control */ + uint fc_xon; /* Number which turned off flow-control */ + uint rxglomfail; /* Failed deglom attempts */ + uint rxglomframes; /* Number of glom frames (superframes) */ + uint rxglompkts; /* Number of packets from glom frames */ + uint f2rxhdrs; /* Number of header reads */ + uint f2rxdata; /* Number of frame data reads */ + uint f2txdata; /* Number of f2 frame writes */ + uint f1regdata; /* Number of f1 register accesses */ + uint tickcnt; /* Number of watchdog been schedule */ + ulong tx_ctlerrs; /* Err of sending ctrl frames */ + ulong tx_ctlpkts; /* Ctrl frames sent to dongle */ + ulong rx_ctlerrs; /* Err of processing rx ctrl frames */ + ulong rx_ctlpkts; /* Ctrl frames processed from dongle */ + ulong rx_readahead_cnt; /* packets where header read-ahead was used */ +}; + +struct brcmf_pub; +#ifdef DEBUG +void brcmf_debugfs_init(void); +void brcmf_debugfs_exit(void); +int brcmf_debugfs_attach(struct brcmf_pub *drvr); +void brcmf_debugfs_detach(struct brcmf_pub *drvr); +struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); +void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, + struct brcmf_sdio_count *sdcnt); +#else +static inline void brcmf_debugfs_init(void) +{ +} +static inline void brcmf_debugfs_exit(void) +{ +} +static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) +{ + return 0; +} +static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) +{ +} +#endif + #endif /* _BRCMF_DBG_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 8933f9b31a9a..57bf1d7ee80f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -1007,6 +1007,9 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) drvr->bus_if->drvr = drvr; drvr->dev = dev; + /* create device debugfs folder */ + brcmf_debugfs_attach(drvr); + /* Attach and link in the protocol */ ret = brcmf_proto_attach(drvr); if (ret != 0) { @@ -1017,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address); INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list); + INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); + return ret; fail: @@ -1123,6 +1128,7 @@ void brcmf_detach(struct device *dev) brcmf_proto_detach(drvr); } + brcmf_debugfs_detach(drvr); bus_if->drvr = NULL; kfree(drvr); } @@ -1192,6 +1198,8 @@ exit: static void brcmf_driver_init(struct work_struct *work) { + brcmf_debugfs_init(); + #ifdef CONFIG_BRCMFMAC_SDIO brcmf_sdio_init(); #endif @@ -1219,6 +1227,7 @@ static void __exit brcmfmac_module_exit(void) #ifdef CONFIG_BRCMFMAC_USB brcmf_usb_exit(); #endif + brcmf_debugfs_exit(); } module_init(brcmfmac_module_init); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 1dbf2be478c8..472f2ef5c652 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -31,6 +31,8 @@ #include <linux/firmware.h> #include <linux/module.h> #include <linux/bcma/bcma.h> +#include <linux/debugfs.h> +#include <linux/vmalloc.h> #include <asm/unaligned.h> #include <defs.h> #include <brcmu_wifi.h> @@ -48,6 +50,9 @@ #define CBUF_LEN (128) +/* Device console log buffer state */ +#define CONSOLE_BUFFER_MAX 2024 + struct rte_log_le { __le32 buf; /* Can't be pointer on (64-bit) hosts */ __le32 buf_size; @@ -281,7 +286,7 @@ struct rte_console { * Shared structure between dongle and the host. * The structure contains pointers to trap or assert information. */ -#define SDPCM_SHARED_VERSION 0x0002 +#define SDPCM_SHARED_VERSION 0x0003 #define SDPCM_SHARED_VERSION_MASK 0x00FF #define SDPCM_SHARED_ASSERT_BUILT 0x0100 #define SDPCM_SHARED_ASSERT 0x0200 @@ -428,6 +433,29 @@ struct brcmf_console { u8 *buf; /* Log buffer (host copy) */ uint last; /* Last buffer read index */ }; + +struct brcmf_trap_info { + __le32 type; + __le32 epc; + __le32 cpsr; + __le32 spsr; + __le32 r0; /* a1 */ + __le32 r1; /* a2 */ + __le32 r2; /* a3 */ + __le32 r3; /* a4 */ + __le32 r4; /* v1 */ + __le32 r5; /* v2 */ + __le32 r6; /* v3 */ + __le32 r7; /* v4 */ + __le32 r8; /* v5 */ + __le32 r9; /* sb/v6 */ + __le32 r10; /* sl/v7 */ + __le32 r11; /* fp/v8 */ + __le32 r12; /* ip */ + __le32 r13; /* sp */ + __le32 r14; /* lr */ + __le32 pc; /* r15 */ +}; #endif /* DEBUG */ struct sdpcm_shared { @@ -439,6 +467,7 @@ struct sdpcm_shared { u32 console_addr; /* Address of struct rte_console */ u32 msgtrace_addr; u8 tag[32]; + u32 brpt_addr; }; struct sdpcm_shared_le { @@ -450,6 +479,7 @@ struct sdpcm_shared_le { __le32 console_addr; /* Address of struct rte_console */ __le32 msgtrace_addr; u8 tag[32]; + __le32 brpt_addr; }; @@ -502,12 +532,9 @@ struct brcmf_sdio { bool intr; /* Use interrupts */ bool poll; /* Use polling */ bool ipend; /* Device interrupt is pending */ - uint intrcount; /* Count of device interrupt callbacks */ - uint lastintrs; /* Count as of last watchdog timer */ uint spurious; /* Count of spurious interrupts */ uint pollrate; /* Ticks between device polls */ uint polltick; /* Tick counter */ - uint pollcnt; /* Count of active polls */ #ifdef DEBUG uint console_interval; @@ -515,8 +542,6 @@ struct brcmf_sdio { uint console_addr; /* Console address from shared struct */ #endif /* DEBUG */ - uint regfails; /* Count of R_REG failures */ - uint clkstate; /* State of sd and backplane clock(s) */ bool activity; /* Activity flag for clock down */ s32 idletime; /* Control for activity timeout */ @@ -531,33 +556,6 @@ struct brcmf_sdio { /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ bool usebufpool; - /* Some additional counters */ - uint tx_sderrs; /* Count of tx attempts with sd errors */ - uint fcqueued; /* Tx packets that got queued */ - uint rxrtx; /* Count of rtx requests (NAK to dongle) */ - uint rx_toolong; /* Receive frames too long to receive */ - uint rxc_errors; /* SDIO errors when reading control frames */ - uint rx_hdrfail; /* SDIO errors on header reads */ - uint rx_badhdr; /* Bad received headers (roosync?) */ - uint rx_badseq; /* Mismatched rx sequence number */ - uint fc_rcvd; /* Number of flow-control events received */ - uint fc_xoff; /* Number which turned on flow-control */ - uint fc_xon; /* Number which turned off flow-control */ - uint rxglomfail; /* Failed deglom attempts */ - uint rxglomframes; /* Number of glom frames (superframes) */ - uint rxglompkts; /* Number of packets from glom frames */ - uint f2rxhdrs; /* Number of header reads */ - uint f2rxdata; /* Number of frame data reads */ - uint f2txdata; /* Number of f2 frame writes */ - uint f1regdata; /* Number of f1 register accesses */ - uint tickcnt; /* Number of watchdog been schedule */ - unsigned long tx_ctlerrs; /* Err of sending ctrl frames */ - unsigned long tx_ctlpkts; /* Ctrl frames sent to dongle */ - unsigned long rx_ctlerrs; /* Err of processing rx ctrl frames */ - unsigned long rx_ctlpkts; /* Ctrl frames processed from dongle */ - unsigned long rx_readahead_cnt; /* Number of packets where header - * read-ahead was used. */ - u8 *ctrl_frame_buf; u32 ctrl_frame_len; bool ctrl_frame_stat; @@ -583,6 +581,7 @@ struct brcmf_sdio { u32 fw_ptr; bool txoff; /* Transmit flow-controlled */ + struct brcmf_sdio_count sdcnt; }; /* clkstate */ @@ -945,7 +944,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) if (ret == 0) w_sdreg32(bus, SMB_INT_ACK, offsetof(struct sdpcmd_regs, tosbmailbox)); - bus->f1regdata += 2; + bus->sdcnt.f1regdata += 2; /* Dongle recomposed rx frames, accept them again */ if (hmb_data & HMB_DATA_NAKHANDLED) { @@ -984,12 +983,12 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) HMB_DATA_FCDATA_SHIFT; if (fcbits & ~bus->flowcontrol) - bus->fc_xoff++; + bus->sdcnt.fc_xoff++; if (bus->flowcontrol & ~fcbits) - bus->fc_xon++; + bus->sdcnt.fc_xon++; - bus->fc_rcvd++; + bus->sdcnt.fc_rcvd++; bus->flowcontrol = fcbits; } @@ -1021,7 +1020,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); - bus->f1regdata++; + bus->sdcnt.f1regdata++; /* Wait until the packet has been flushed (device/FIFO stable) */ for (lastrbc = retries = 0xffff; retries > 0; retries--) { @@ -1029,7 +1028,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) SBSDIO_FUNC1_RFRAMEBCHI, &err); lo = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCLO, &err); - bus->f1regdata += 2; + bus->sdcnt.f1regdata += 2; if ((hi == 0) && (lo == 0)) break; @@ -1047,11 +1046,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); if (rtx) { - bus->rxrtx++; + bus->sdcnt.rxrtx++; err = w_sdreg32(bus, SMB_NAK, offsetof(struct sdpcmd_regs, tosbmailbox)); - bus->f1regdata++; + bus->sdcnt.f1regdata++; if (err == 0) bus->rxskip = true; } @@ -1243,7 +1242,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) dlen); errcode = -1; } - bus->f2rxdata++; + bus->sdcnt.f2rxdata++; /* On failure, kill the superframe, allow a couple retries */ if (errcode < 0) { @@ -1256,7 +1255,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } else { bus->glomerr = 0; brcmf_sdbrcm_rxfail(bus, true, false); - bus->rxglomfail++; + bus->sdcnt.rxglomfail++; brcmf_sdbrcm_free_glom(bus); } return 0; @@ -1312,7 +1311,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) if (rxseq != seq) { brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", seq, rxseq); - bus->rx_badseq++; + bus->sdcnt.rx_badseq++; rxseq = seq; } @@ -1376,7 +1375,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } else { bus->glomerr = 0; brcmf_sdbrcm_rxfail(bus, true, false); - bus->rxglomfail++; + bus->sdcnt.rxglomfail++; brcmf_sdbrcm_free_glom(bus); } bus->nextlen = 0; @@ -1402,7 +1401,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) if (rxseq != seq) { brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", seq, rxseq); - bus->rx_badseq++; + bus->sdcnt.rx_badseq++; rxseq = seq; } rxseq++; @@ -1441,8 +1440,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) down(&bus->sdsem); } - bus->rxglomframes++; - bus->rxglompkts += bus->glom.qlen; + bus->sdcnt.rxglomframes++; + bus->sdcnt.rxglompkts += bus->glom.qlen; } return num; } @@ -1526,7 +1525,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", len, len - doff, bus->sdiodev->bus_if->maxctl); bus->sdiodev->bus_if->dstats.rx_errors++; - bus->rx_toolong++; + bus->sdcnt.rx_toolong++; brcmf_sdbrcm_rxfail(bus, false, false); goto done; } @@ -1536,13 +1535,13 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen); - bus->f2rxdata++; + bus->sdcnt.f2rxdata++; /* Control frame failures need retransmission */ if (sdret < 0) { brcmf_dbg(ERROR, "read %d control bytes failed: %d\n", rdlen, sdret); - bus->rxc_errors++; + bus->sdcnt.rxc_errors++; brcmf_sdbrcm_rxfail(bus, true, true); goto done; } @@ -1589,7 +1588,7 @@ brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, /* Read the entire frame */ sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, *pkt); - bus->f2rxdata++; + bus->sdcnt.f2rxdata++; if (sdret < 0) { brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", @@ -1630,7 +1629,7 @@ brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, if ((u16)~(*len ^ check)) { brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", nextlen, *len, check); - bus->rx_badhdr++; + bus->sdcnt.rx_badhdr++; brcmf_sdbrcm_rxfail(bus, false, false); goto fail; } @@ -1746,7 +1745,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) bus->nextlen = 0; } - bus->rx_readahead_cnt++; + bus->sdcnt.rx_readahead_cnt++; /* Handle Flow Control */ fcbits = SDPCM_FCMASK_VALUE( @@ -1754,12 +1753,12 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) if (bus->flowcontrol != fcbits) { if (~bus->flowcontrol & fcbits) - bus->fc_xoff++; + bus->sdcnt.fc_xoff++; if (bus->flowcontrol & ~fcbits) - bus->fc_xon++; + bus->sdcnt.fc_xon++; - bus->fc_rcvd++; + bus->sdcnt.fc_rcvd++; bus->flowcontrol = fcbits; } @@ -1767,7 +1766,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) if (rxseq != seq) { brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", seq, rxseq); - bus->rx_badseq++; + bus->sdcnt.rx_badseq++; rxseq = seq; } @@ -1814,11 +1813,11 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, bus->rxhdr, BRCMF_FIRSTREAD); - bus->f2rxhdrs++; + bus->sdcnt.f2rxhdrs++; if (sdret < 0) { brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); - bus->rx_hdrfail++; + bus->sdcnt.rx_hdrfail++; brcmf_sdbrcm_rxfail(bus, true, true); continue; } @@ -1840,7 +1839,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) if ((u16) ~(len ^ check)) { brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", len, check); - bus->rx_badhdr++; + bus->sdcnt.rx_badhdr++; brcmf_sdbrcm_rxfail(bus, false, false); continue; } @@ -1861,7 +1860,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) if ((doff < SDPCM_HDRLEN) || (doff > len)) { brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", doff, len, SDPCM_HDRLEN, seq); - bus->rx_badhdr++; + bus->sdcnt.rx_badhdr++; brcmf_sdbrcm_rxfail(bus, false, false); continue; } @@ -1880,19 +1879,19 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) if (bus->flowcontrol != fcbits) { if (~bus->flowcontrol & fcbits) - bus->fc_xoff++; + bus->sdcnt.fc_xoff++; if (bus->flowcontrol & ~fcbits) - bus->fc_xon++; + bus->sdcnt.fc_xon++; - bus->fc_rcvd++; + bus->sdcnt.fc_rcvd++; bus->flowcontrol = fcbits; } /* Check and update sequence number */ if (rxseq != seq) { brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); - bus->rx_badseq++; + bus->sdcnt.rx_badseq++; rxseq = seq; } @@ -1937,7 +1936,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", len, rdlen); bus->sdiodev->bus_if->dstats.rx_errors++; - bus->rx_toolong++; + bus->sdcnt.rx_toolong++; brcmf_sdbrcm_rxfail(bus, false, false); continue; } @@ -1960,7 +1959,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) /* Read the remaining frame data */ sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, pkt); - bus->f2rxdata++; + bus->sdcnt.f2rxdata++; if (sdret < 0) { brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, @@ -2147,18 +2146,18 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, pkt); - bus->f2txdata++; + bus->sdcnt.f2txdata++; if (ret < 0) { /* On failure, abort the command and terminate the frame */ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ret); - bus->tx_sderrs++; + bus->sdcnt.tx_sderrs++; brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); - bus->f1regdata++; + bus->sdcnt.f1regdata++; for (i = 0; i < 3; i++) { u8 hi, lo; @@ -2166,7 +2165,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, SBSDIO_FUNC1_WFRAMEBCHI, NULL); lo = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL); - bus->f1regdata += 2; + bus->sdcnt.f1regdata += 2; if ((hi == 0) && (lo == 0)) break; } @@ -2224,7 +2223,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) ret = r_sdreg32(bus, &intstatus, offsetof(struct sdpcmd_regs, intstatus)); - bus->f2txdata++; + bus->sdcnt.f2txdata++; if (ret != 0) break; if (intstatus & bus->hostintmask) @@ -2417,7 +2416,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) bus->ipend = false; err = r_sdreg32(bus, &newstatus, offsetof(struct sdpcmd_regs, intstatus)); - bus->f1regdata++; + bus->sdcnt.f1regdata++; if (err != 0) newstatus = 0; newstatus &= bus->hostintmask; @@ -2426,7 +2425,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) err = w_sdreg32(bus, newstatus, offsetof(struct sdpcmd_regs, intstatus)); - bus->f1regdata++; + bus->sdcnt.f1regdata++; } } @@ -2445,7 +2444,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) err = r_sdreg32(bus, &newstatus, offsetof(struct sdpcmd_regs, intstatus)); - bus->f1regdata += 2; + bus->sdcnt.f1regdata += 2; bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); intstatus |= (newstatus & bus->hostintmask); @@ -2502,7 +2501,7 @@ clkwait: int ret, i; ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf, + SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, (u32) bus->ctrl_frame_len); if (ret < 0) { @@ -2510,13 +2509,13 @@ clkwait: terminate the frame */ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ret); - bus->tx_sderrs++; + bus->sdcnt.tx_sderrs++; brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, &err); - bus->f1regdata++; + bus->sdcnt.f1regdata++; for (i = 0; i < 3; i++) { u8 hi, lo; @@ -2526,7 +2525,7 @@ clkwait: lo = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, &err); - bus->f1regdata += 2; + bus->sdcnt.f1regdata += 2; if ((hi == 0) && (lo == 0)) break; } @@ -2657,7 +2656,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) /* Check for existing queue, current flow-control, pending event, or pending clock */ brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq)); - bus->fcqueued++; + bus->sdcnt.fcqueued++; /* Priority based enq */ spin_lock_bh(&bus->txqlock); @@ -2845,13 +2844,13 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) /* On failure, abort the command and terminate the frame */ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ret); - bus->tx_sderrs++; + bus->sdcnt.tx_sderrs++; brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); - bus->f1regdata++; + bus->sdcnt.f1regdata++; for (i = 0; i < 3; i++) { u8 hi, lo; @@ -2859,7 +2858,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) SBSDIO_FUNC1_WFRAMEBCHI, NULL); lo = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL); - bus->f1regdata += 2; + bus->sdcnt.f1regdata += 2; if (hi == 0 && lo == 0) break; } @@ -2976,13 +2975,324 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) up(&bus->sdsem); if (ret) - bus->tx_ctlerrs++; + bus->sdcnt.tx_ctlerrs++; else - bus->tx_ctlpkts++; + bus->sdcnt.tx_ctlpkts++; return ret ? -EIO : 0; } +#ifdef DEBUG +static inline bool brcmf_sdio_valid_shared_address(u32 addr) +{ + return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)); +} + +static int brcmf_sdio_readshared(struct brcmf_sdio *bus, + struct sdpcm_shared *sh) +{ + u32 addr; + int rv; + u32 shaddr = 0; + struct sdpcm_shared_le sh_le; + __le32 addr_le; + + shaddr = bus->ramsize - 4; + + /* + * Read last word in socram to determine + * address of sdpcm_shared structure + */ + rv = brcmf_sdbrcm_membytes(bus, false, shaddr, + (u8 *)&addr_le, 4); + if (rv < 0) + return rv; + + addr = le32_to_cpu(addr_le); + + brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); + + /* + * Check if addr is valid. + * NVRAM length at the end of memory should have been overwritten. + */ + if (!brcmf_sdio_valid_shared_address(addr)) { + brcmf_dbg(ERROR, "invalid sdpcm_shared address 0x%08X\n", + addr); + return -EINVAL; + } + + /* Read hndrte_shared structure */ + rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le, + sizeof(struct sdpcm_shared_le)); + if (rv < 0) + return rv; + + /* Endianness */ + sh->flags = le32_to_cpu(sh_le.flags); + sh->trap_addr = le32_to_cpu(sh_le.trap_addr); + sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr); + sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr); + sh->assert_line = le32_to_cpu(sh_le.assert_line); + sh->console_addr = le32_to_cpu(sh_le.console_addr); + sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr); + + if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { + brcmf_dbg(ERROR, + "sdpcm_shared version mismatch: dhd %d dongle %d\n", + SDPCM_SHARED_VERSION, + sh->flags & SDPCM_SHARED_VERSION_MASK); + return -EPROTO; + } + + return 0; +} + +static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, + struct sdpcm_shared *sh, char __user *data, + size_t count) +{ + u32 addr, console_ptr, console_size, console_index; + char *conbuf = NULL; + __le32 sh_val; + int rv; + loff_t pos = 0; + int nbytes = 0; + + /* obtain console information from device memory */ + addr = sh->console_addr + offsetof(struct rte_console, log_le); + rv = brcmf_sdbrcm_membytes(bus, false, addr, + (u8 *)&sh_val, sizeof(u32)); + if (rv < 0) + return rv; + console_ptr = le32_to_cpu(sh_val); + + addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size); + rv = brcmf_sdbrcm_membytes(bus, false, addr, + (u8 *)&sh_val, sizeof(u32)); + if (rv < 0) + return rv; + console_size = le32_to_cpu(sh_val); + + addr = sh->console_addr + offsetof(struct rte_console, log_le.idx); + rv = brcmf_sdbrcm_membytes(bus, false, addr, + (u8 *)&sh_val, sizeof(u32)); + if (rv < 0) + return rv; + console_index = le32_to_cpu(sh_val); + + /* allocate buffer for console data */ + if (console_size <= CONSOLE_BUFFER_MAX) + conbuf = vzalloc(console_size+1); + + if (!conbuf) + return -ENOMEM; + + /* obtain the console data from device */ + conbuf[console_size] = '\0'; + rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf, + console_size); + if (rv < 0) + goto done; + + rv = simple_read_from_buffer(data, count, &pos, + conbuf + console_index, + console_size - console_index); + if (rv < 0) + goto done; + + nbytes = rv; + if (console_index > 0) { + pos = 0; + rv = simple_read_from_buffer(data+nbytes, count, &pos, + conbuf, console_index - 1); + if (rv < 0) + goto done; + rv += nbytes; + } +done: + vfree(conbuf); + return rv; +} + +static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, + char __user *data, size_t count) +{ + int error, res; + char buf[350]; + struct brcmf_trap_info tr; + int nbytes; + loff_t pos = 0; + + if ((sh->flags & SDPCM_SHARED_TRAP) == 0) + return 0; + + error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, + sizeof(struct brcmf_trap_info)); + if (error < 0) + return error; + + nbytes = brcmf_sdio_dump_console(bus, sh, data, count); + if (nbytes < 0) + return nbytes; + + res = scnprintf(buf, sizeof(buf), + "dongle trap info: type 0x%x @ epc 0x%08x\n" + " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" + " lr 0x%08x pc 0x%08x offset 0x%x\n" + " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" + " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", + le32_to_cpu(tr.type), le32_to_cpu(tr.epc), + le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), + le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), + le32_to_cpu(tr.pc), sh->trap_addr, + le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), + le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), + le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), + le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); + + error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res); + if (error < 0) + return error; + + nbytes += error; + return nbytes; +} + +static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, + struct sdpcm_shared *sh, char __user *data, + size_t count) +{ + int error = 0; + char buf[200]; + char file[80] = "?"; + char expr[80] = "<???>"; + int res; + loff_t pos = 0; + + if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { + brcmf_dbg(INFO, "firmware not built with -assert\n"); + return 0; + } else if ((sh->flags & SDPCM_SHARED_ASSERT) == 0) { + brcmf_dbg(INFO, "no assert in dongle\n"); + return 0; + } + + if (sh->assert_file_addr != 0) { + error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr, + (u8 *)file, 80); + if (error < 0) + return error; + } + if (sh->assert_exp_addr != 0) { + error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr, + (u8 *)expr, 80); + if (error < 0) + return error; + } + + res = scnprintf(buf, sizeof(buf), + "dongle assert: %s:%d: assert(%s)\n", + file, sh->assert_line, expr); + return simple_read_from_buffer(data, count, &pos, buf, res); +} + +static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) +{ + int error; + struct sdpcm_shared sh; + + down(&bus->sdsem); + error = brcmf_sdio_readshared(bus, &sh); + up(&bus->sdsem); + + if (error < 0) + return error; + + if ((sh.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) + brcmf_dbg(INFO, "firmware not built with -assert\n"); + else if (sh.flags & SDPCM_SHARED_ASSERT) + brcmf_dbg(ERROR, "assertion in dongle\n"); + + if (sh.flags & SDPCM_SHARED_TRAP) + brcmf_dbg(ERROR, "firmware trap in dongle\n"); + + return 0; +} + +static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data, + size_t count, loff_t *ppos) +{ + int error = 0; + struct sdpcm_shared sh; + int nbytes = 0; + loff_t pos = *ppos; + + if (pos != 0) + return 0; + + down(&bus->sdsem); + error = brcmf_sdio_readshared(bus, &sh); + if (error < 0) + goto done; + + error = brcmf_sdio_assert_info(bus, &sh, data, count); + if (error < 0) + goto done; + + nbytes = error; + error = brcmf_sdio_trap_info(bus, &sh, data, count); + if (error < 0) + goto done; + + error += nbytes; + *ppos += error; +done: + up(&bus->sdsem); + return error; +} + +static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data, + size_t count, loff_t *ppos) +{ + struct brcmf_sdio *bus = f->private_data; + int res; + + res = brcmf_sdbrcm_died_dump(bus, data, count, ppos); + if (res > 0) + *ppos += res; + return (ssize_t)res; +} + +static const struct file_operations brcmf_sdio_forensic_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = brcmf_sdio_forensic_read +}; + +static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) +{ + struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr; + struct dentry *dentry = brcmf_debugfs_get_devdir(drvr); + + if (IS_ERR_OR_NULL(dentry)) + return; + + debugfs_create_file("forensics", S_IRUGO, dentry, bus, + &brcmf_sdio_forensic_ops); + brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); +} +#else +static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) +{ + return 0; +} + +static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) +{ +} +#endif /* DEBUG */ + static int brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) { @@ -3009,60 +3319,27 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) rxlen, msglen); } else if (timeleft == 0) { brcmf_dbg(ERROR, "resumed on timeout\n"); + brcmf_sdbrcm_checkdied(bus); } else if (pending) { brcmf_dbg(CTL, "cancelled\n"); return -ERESTARTSYS; } else { brcmf_dbg(CTL, "resumed for unknown reason?\n"); + brcmf_sdbrcm_checkdied(bus); } if (rxlen) - bus->rx_ctlpkts++; + bus->sdcnt.rx_ctlpkts++; else - bus->rx_ctlerrs++; + bus->sdcnt.rx_ctlerrs++; return rxlen ? (int)rxlen : -ETIMEDOUT; } -static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len) -{ - int bcmerror = 0; - - brcmf_dbg(TRACE, "Enter\n"); - - /* Basic sanity checks */ - if (bus->sdiodev->bus_if->drvr_up) { - bcmerror = -EISCONN; - goto err; - } - if (!len) { - bcmerror = -EOVERFLOW; - goto err; - } - - /* Free the old ones and replace with passed variables */ - kfree(bus->vars); - - bus->vars = kmalloc(len, GFP_ATOMIC); - bus->varsz = bus->vars ? len : 0; - if (bus->vars == NULL) { - bcmerror = -ENOMEM; - goto err; - } - - /* Copy the passed variables, which should include the - terminating double-null */ - memcpy(bus->vars, arg, bus->varsz); -err: - return bcmerror; -} - static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) { int bcmerror = 0; - u32 varsize; u32 varaddr; - u8 *vbuffer; u32 varsizew; __le32 varsizew_le; #ifdef DEBUG @@ -3071,56 +3348,44 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) /* Even if there are no vars are to be written, we still need to set the ramsize. */ - varsize = bus->varsz ? roundup(bus->varsz, 4) : 0; - varaddr = (bus->ramsize - 4) - varsize; + varaddr = (bus->ramsize - 4) - bus->varsz; if (bus->vars) { - vbuffer = kzalloc(varsize, GFP_ATOMIC); - if (!vbuffer) - return -ENOMEM; - - memcpy(vbuffer, bus->vars, bus->varsz); - /* Write the vars list */ - bcmerror = - brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize); + bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr, + bus->vars, bus->varsz); #ifdef DEBUG /* Verify NVRAM bytes */ - brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); - nvram_ularray = kmalloc(varsize, GFP_ATOMIC); - if (!nvram_ularray) { - kfree(vbuffer); + brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", + bus->varsz); + nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC); + if (!nvram_ularray) return -ENOMEM; - } /* Upload image to verify downloaded contents. */ - memset(nvram_ularray, 0xaa, varsize); + memset(nvram_ularray, 0xaa, bus->varsz); /* Read the vars list to temp buffer for comparison */ - bcmerror = - brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray, - varsize); + bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr, + nvram_ularray, bus->varsz); if (bcmerror) { brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n", - bcmerror, varsize, varaddr); + bcmerror, bus->varsz, varaddr); } /* Compare the org NVRAM with the one read from RAM */ - if (memcmp(vbuffer, nvram_ularray, varsize)) + if (memcmp(bus->vars, nvram_ularray, bus->varsz)) brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n"); else brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); kfree(nvram_ularray); #endif /* DEBUG */ - - kfree(vbuffer); } /* adjust to the user specified RAM */ brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", - varaddr, varsize); - varsize = ((bus->ramsize - 4) - varaddr); + varaddr, bus->varsz); /* * Determine the length token: @@ -3131,13 +3396,13 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) varsizew = 0; varsizew_le = cpu_to_le32(0); } else { - varsizew = varsize / 4; + varsizew = bus->varsz / 4; varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); varsizew_le = cpu_to_le32(varsizew); } brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", - varsize, varsizew); + bus->varsz, varsizew); /* Write the length token to the last word */ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), @@ -3261,13 +3526,21 @@ err: * by two NULs. */ -static uint brcmf_process_nvram_vars(char *varbuf, uint len) +static int brcmf_process_nvram_vars(struct brcmf_sdio *bus) { + char *varbuf; char *dp; bool findNewline; int column; - uint buf_len, n; + int ret = 0; + uint buf_len, n, len; + len = bus->firmware->size; + varbuf = vmalloc(len); + if (!varbuf) + return -ENOMEM; + + memcpy(varbuf, bus->firmware->data, len); dp = varbuf; findNewline = false; @@ -3296,56 +3569,44 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len) column++; } buf_len = dp - varbuf; - while (dp < varbuf + n) *dp++ = 0; - return buf_len; + kfree(bus->vars); + /* roundup needed for download to device */ + bus->varsz = roundup(buf_len + 1, 4); + bus->vars = kmalloc(bus->varsz, GFP_KERNEL); + if (bus->vars == NULL) { + bus->varsz = 0; + ret = -ENOMEM; + goto err; + } + + /* copy the processed variables and add null termination */ + memcpy(bus->vars, varbuf, buf_len); + bus->vars[buf_len] = 0; +err: + vfree(varbuf); + return ret; } static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) { - uint len; - char *memblock = NULL; - char *bufp; int ret; + if (bus->sdiodev->bus_if->drvr_up) + return -EISCONN; + ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, &bus->sdiodev->func[2]->dev); if (ret) { brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); return ret; } - bus->fw_ptr = 0; - - memblock = kmalloc(MEMBLOCK, GFP_ATOMIC); - if (memblock == NULL) { - ret = -ENOMEM; - goto err; - } - - len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus); - - if (len > 0 && len < MEMBLOCK) { - bufp = (char *)memblock; - bufp[len] = 0; - len = brcmf_process_nvram_vars(bufp, len); - bufp += len; - *bufp++ = 0; - if (len) - ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1); - if (ret) - brcmf_dbg(ERROR, "error downloading vars: %d\n", ret); - } else { - brcmf_dbg(ERROR, "error reading nvram file: %d\n", len); - ret = -EIO; - } -err: - kfree(memblock); + ret = brcmf_process_nvram_vars(bus); release_firmware(bus->firmware); - bus->fw_ptr = 0; return ret; } @@ -3419,7 +3680,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) return 0; /* Start the watchdog timer */ - bus->tickcnt = 0; + bus->sdcnt.tickcnt = 0; brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); down(&bus->sdsem); @@ -3512,7 +3773,7 @@ void brcmf_sdbrcm_isr(void *arg) return; } /* Count the interrupt call */ - bus->intrcount++; + bus->sdcnt.intrcount++; bus->ipend = true; /* Shouldn't get this interrupt if we're sleeping? */ @@ -3554,7 +3815,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) bus->polltick = 0; /* Check device if no interrupts */ - if (!bus->intr || (bus->intrcount == bus->lastintrs)) { + if (!bus->intr || + (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { if (!bus->dpc_sched) { u8 devpend; @@ -3569,7 +3831,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) /* If there is something, make like the ISR and schedule the DPC */ if (intstatus) { - bus->pollcnt++; + bus->sdcnt.pollcnt++; bus->ipend = true; bus->dpc_sched = true; @@ -3581,7 +3843,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) } /* Update interrupt tracking */ - bus->lastintrs = bus->intrcount; + bus->sdcnt.lastintrs = bus->sdcnt.intrcount; } #ifdef DEBUG /* Poll for console output periodically */ @@ -3623,6 +3885,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) return true; if (chipid == BCM4330_CHIP_ID) return true; + if (chipid == BCM4334_CHIP_ID) + return true; return false; } @@ -3793,7 +4057,7 @@ brcmf_sdbrcm_watchdog_thread(void *data) if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { brcmf_sdbrcm_bus_watchdog(bus); /* Count the tick for reference */ - bus->tickcnt++; + bus->sdcnt.tickcnt++; } else break; } @@ -3856,6 +4120,10 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) { int ret; struct brcmf_sdio *bus; + struct brcmf_bus_dcmd *dlst; + u32 dngl_txglom; + u32 dngl_txglomalign; + u8 idx; brcmf_dbg(TRACE, "Enter\n"); @@ -3938,8 +4206,29 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) goto fail; } + brcmf_sdio_debugfs_create(bus); brcmf_dbg(INFO, "completed!!\n"); + /* sdio bus core specific dcmd */ + idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); + dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL); + if (dlst) { + if (bus->ci->c_inf[idx].rev < 12) { + /* for sdio core rev < 12, disable txgloming */ + dngl_txglom = 0; + dlst->name = "bus:txglom"; + dlst->param = (char *)&dngl_txglom; + dlst->param_len = sizeof(u32); + } else { + /* otherwise, set txglomalign */ + dngl_txglomalign = bus->sdiodev->bus_if->align; + dlst->name = "bus:txglomalign"; + dlst->param = (char *)&dngl_txglomalign; + dlst->param_len = sizeof(u32); + } + list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list); + } + /* if firmware path present try to download and bring up bus */ ret = brcmf_bus_start(bus->sdiodev->dev); if (ret != 0) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index f8e1f1c84d08..58155e23d220 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c @@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, ci->c_inf[3].cib = 0x03004211; ci->ramsize = 0x48000; break; + case BCM4334_CHIP_ID: + ci->c_inf[0].wrapbase = 0x18100000; + ci->c_inf[0].cib = 0x29004211; + ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; + ci->c_inf[1].base = 0x18002000; + ci->c_inf[1].wrapbase = 0x18102000; + ci->c_inf[1].cib = 0x0d004211; + ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; + ci->c_inf[2].base = 0x18004000; + ci->c_inf[2].wrapbase = 0x18104000; + ci->c_inf[2].cib = 0x13080401; + ci->c_inf[3].id = BCMA_CORE_ARM_CM3; + ci->c_inf[3].base = 0x18003000; + ci->c_inf[3].wrapbase = 0x18103000; + ci->c_inf[3].cib = 0x07004211; + ci->ramsize = 0x80000; + break; default: brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); return -ENODEV; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index d13ae9c299f2..28c5fbb4af26 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -691,9 +691,10 @@ scan_out: } static s32 -brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, +brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { + struct net_device *ndev = request->wdev->netdev; s32 err = 0; WL_TRACE("Enter\n"); @@ -919,9 +920,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); if (params->bssid) - WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n", - params->bssid[0], params->bssid[1], params->bssid[2], - params->bssid[3], params->bssid[4], params->bssid[5]); + WL_CONN("BSSID: %pM\n", params->bssid); else WL_CONN("No BSSID specified\n"); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index 6d8b7213643a..8c9345dd37d2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c @@ -318,10 +318,6 @@ #define IS_SIM(chippkg) \ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) -#define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) - -#define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) - #ifdef DEBUG #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #else @@ -473,9 +469,6 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; } - /* figure out buscore */ - sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0); - return true; } @@ -483,11 +476,7 @@ static struct si_info *ai_doattach(struct si_info *sii, struct bcma_bus *pbus) { struct si_pub *sih = &sii->pub; - u32 w, savewin; struct bcma_device *cc; - struct ssb_sprom *sprom = &pbus->sprom; - - savewin = 0; sii->icbus = pbus; sii->pcibus = pbus->host_pci; @@ -510,47 +499,7 @@ static struct si_info *ai_doattach(struct si_info *sii, /* PMU specific initializations */ if (ai_get_cccaps(sih) & CC_CAP_PMU) { - si_pmu_init(sih); (void)si_pmu_measure_alpclk(sih); - si_pmu_res_init(sih); - } - - /* setup the GPIO based LED powersave register */ - w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | - (sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT); - if (w == 0) - w = DEFAULT_GPIOTIMERVAL; - ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), - ~0, w); - - if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { - /* - * enable 12 mA drive strenth for 43224 and - * set chipControl register bit 15 - */ - if (ai_get_chiprev(sih) == 0) { - SI_MSG("Applying 43224A0 WARs\n"); - ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol), - CCTRL43224_GPIO_TOGGLE, - CCTRL43224_GPIO_TOGGLE); - si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, - CCTRL_43224A0_12MA_LED_DRIVE); - } - if (ai_get_chiprev(sih) >= 1) { - SI_MSG("Applying 43224B0+ WARs\n"); - si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, - CCTRL_43224B0_12MA_LED_DRIVE); - } - } - - if (ai_get_chip_id(sih) == BCM4313_CHIP_ID) { - /* - * enable 12 mA drive strenth for 4313 and - * set chipControl register bit 1 - */ - SI_MSG("Applying 4313 WARs\n"); - si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, - CCTRL_4313_12MA_LED_DRIVE); } return sii; @@ -589,7 +538,7 @@ void ai_detach(struct si_pub *sih) struct si_pub *si_local = NULL; memcpy(&si_local, &sih, sizeof(struct si_pub **)); - sii = (struct si_info *)sih; + sii = container_of(sih, struct si_info, pub); if (sii == NULL) return; @@ -597,27 +546,6 @@ void ai_detach(struct si_pub *sih) kfree(sii); } -/* return index of coreid or BADIDX if not found */ -struct bcma_device *ai_findcore(struct si_pub *sih, u16 coreid, u16 coreunit) -{ - struct bcma_device *core; - struct si_info *sii; - uint found; - - sii = (struct si_info *)sih; - - found = 0; - - list_for_each_entry(core, &sii->icbus->cores, list) - if (core->id.id == coreid) { - if (found == coreunit) - return core; - found++; - } - - return NULL; -} - /* * read/modify chipcommon core register. */ @@ -627,13 +555,12 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) u32 w; struct si_info *sii; - sii = (struct si_info *)sih; + sii = container_of(sih, struct si_info, pub); cc = sii->icbus->drv_cc.core; /* mask and set */ - if (mask || val) { + if (mask || val) bcma_maskset32(cc, regoff, ~mask, val); - } /* readback */ w = bcma_read32(cc, regoff); @@ -694,12 +621,13 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc) /* initialize power control delay registers */ void ai_clkctl_init(struct si_pub *sih) { + struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *cc; if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) return; - cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); + cc = sii->icbus->drv_cc.core; if (cc == NULL) return; @@ -721,7 +649,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) uint slowminfreq; u16 fpdelay; - sii = (struct si_info *)sih; + sii = container_of(sih, struct si_info, pub); if (ai_get_cccaps(sih) & CC_CAP_PMU) { fpdelay = si_pmu_fast_pwrup_delay(sih); return fpdelay; @@ -731,7 +659,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) return 0; fpdelay = 0; - cc = ai_findcore(sih, CC_CORE_ID, 0); + cc = sii->icbus->drv_cc.core; if (cc) { slowminfreq = ai_slowclk_freq(sih, false, cc); fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2) @@ -753,12 +681,9 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) struct si_info *sii; struct bcma_device *cc; - sii = (struct si_info *)sih; - - if (PCI_FORCEHT(sih)) - return mode == BCMA_CLKMODE_FAST; + sii = container_of(sih, struct si_info, pub); - cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); + cc = sii->icbus->drv_cc.core; bcma_core_set_clockmode(cc, mode); return mode == BCMA_CLKMODE_FAST; } @@ -766,16 +691,10 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) void ai_pci_up(struct si_pub *sih) { struct si_info *sii; - struct bcma_device *cc; - sii = (struct si_info *)sih; + sii = container_of(sih, struct si_info, pub); - if (PCI_FORCEHT(sih)) { - cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); - bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST); - } - - if (PCIE(sih)) + if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); } @@ -783,26 +702,20 @@ void ai_pci_up(struct si_pub *sih) void ai_pci_down(struct si_pub *sih) { struct si_info *sii; - struct bcma_device *cc; - sii = (struct si_info *)sih; + sii = container_of(sih, struct si_info, pub); - /* release FORCEHT since chip is going to "down" state */ - if (PCI_FORCEHT(sih)) { - cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); - bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC); - } - - if (PCIE(sih)) + if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); } /* Enable BT-COEX & Ex-PA for 4313 */ void ai_epa_4313war(struct si_pub *sih) { + struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *cc; - cc = ai_findcore(sih, CC_CORE_ID, 0); + cc = sii->icbus->drv_cc.core; /* EPA Fix */ bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK); @@ -814,7 +727,7 @@ bool ai_deviceremoved(struct si_pub *sih) u32 w; struct si_info *sii; - sii = (struct si_info *)sih; + sii = container_of(sih, struct si_info, pub); if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI) return false; @@ -825,15 +738,3 @@ bool ai_deviceremoved(struct si_pub *sih) return false; } - -uint ai_get_buscoretype(struct si_pub *sih) -{ - struct si_info *sii = (struct si_info *)sih; - return sii->buscore->id.id; -} - -uint ai_get_buscorerev(struct si_pub *sih) -{ - struct si_info *sii = (struct si_info *)sih; - return sii->buscore->id.rev; -} diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index d9f04a683bdb..89562c1fbf49 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h @@ -88,16 +88,6 @@ #define CLKD_OTP 0x000f0000 #define CLKD_OTP_SHIFT 16 -/* Package IDs */ -#define BCM4717_PKG_ID 9 /* 4717 package id */ -#define BCM4718_PKG_ID 10 /* 4718 package id */ -#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ - -/* these are router chips */ -#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ -#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ -#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ - /* dynamic clock control defines */ #define LPOMINFREQ 25000 /* low power oscillator min */ #define LPOMAXFREQ 43000 /* low power oscillator max */ @@ -168,7 +158,6 @@ struct si_info { struct si_pub pub; /* back plane public state (must be first) */ struct bcma_bus *icbus; /* handle to soc interconnect bus */ struct pci_dev *pcibus; /* handle to pci bus */ - struct bcma_device *buscore; u32 chipst; /* chip status */ }; @@ -183,8 +172,6 @@ struct si_info { /* AMBA Interconnect exported externs */ -extern struct bcma_device *ai_findcore(struct si_pub *sih, - u16 coreid, u16 coreunit); extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); /* === exported functions === */ @@ -193,7 +180,7 @@ extern void ai_detach(struct si_pub *sih); extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); extern void ai_clkctl_init(struct si_pub *sih); extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); -extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); +extern bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode); extern bool ai_deviceremoved(struct si_pub *sih); extern void ai_pci_down(struct si_pub *sih); @@ -202,9 +189,6 @@ extern void ai_pci_up(struct si_pub *sih); /* Enable Ex-PA for 4313 */ extern void ai_epa_4313war(struct si_pub *sih); -extern uint ai_get_buscoretype(struct si_pub *sih); -extern uint ai_get_buscorerev(struct si_pub *sih); - static inline u32 ai_get_cccaps(struct si_pub *sih) { return sih->cccaps; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 95b5902bc4b3..be5bcfb9153b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c @@ -663,9 +663,6 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, /* patch the first MPDU */ if (count == 1) { u8 plcp0, plcp3, is40, sgi; - struct ieee80211_sta *sta; - - sta = tx_info->control.sta; if (rr) { plcp0 = plcp[0]; @@ -735,10 +732,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, * a candidate for aggregation */ p = pktq_ppeek(&qi->q, prec); - /* tx_info must be checked with current p */ - tx_info = IEEE80211_SKB_CB(p); - if (p) { + tx_info = IEEE80211_SKB_CB(p); if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && ((u8) (p->priority) == tid)) { plen = p->len + AMPDU_MAX_MPDU_OVERHEAD; @@ -759,6 +754,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, p = NULL; continue; } + /* next packet fit for aggregation so dequeue */ p = brcmu_pktq_pdeq(&qi->q, prec); } else { p = NULL; @@ -1196,8 +1192,8 @@ static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a) bool rc; rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false; - rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL || - tx_info->control.sta == ampdu_pars->sta); + rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL || + tx_info->rate_driver_data[0] == ampdu_pars->sta); rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid); return rc; } @@ -1211,8 +1207,8 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a) struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi; if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && - (tx_info->control.sta == sta || sta == NULL)) - tx_info->control.sta = NULL; + (tx_info->rate_driver_data[0] == sta || sta == NULL)) + tx_info->rate_driver_data[0] = NULL; } /* diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index eb77ac3cfb6b..9a4c63f927cb 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -15,7 +15,9 @@ */ #include <linux/types.h> +#include <net/cfg80211.h> #include <net/mac80211.h> +#include <net/regulatory.h> #include <defs.h> #include "pub.h" @@ -23,73 +25,17 @@ #include "main.h" #include "stf.h" #include "channel.h" +#include "mac80211_if.h" /* QDB() macro takes a dB value and converts to a quarter dB value */ #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) -#define LOCALE_CHAN_01_11 (1<<0) -#define LOCALE_CHAN_12_13 (1<<1) -#define LOCALE_CHAN_14 (1<<2) -#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */ -#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */ -#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */ -#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */ -#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */ -#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */ -#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */ -#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */ -#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */ -#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */ -#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */ -#define LOCALE_CHAN_52_140_ALL (1<<14) -#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */ - -#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \ - LOCALE_SET_5G_LOW2 | \ - LOCALE_SET_5G_LOW3) -#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) -#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) -#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \ - LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) -#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) -#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 - -#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \ - LOCALE_CHAN_12_13 | \ - LOCALE_CHAN_14) - -#define LOCALE_RADAR_SET_NONE 0 -#define LOCALE_RADAR_SET_1 1 - -#define LOCALE_RESTRICTED_NONE 0 -#define LOCALE_RESTRICTED_SET_2G_SHORT 1 -#define LOCALE_RESTRICTED_CHAN_165 2 -#define LOCALE_CHAN_ALL_5G 3 -#define LOCALE_RESTRICTED_JAPAN_LEGACY 4 -#define LOCALE_RESTRICTED_11D_2G 5 -#define LOCALE_RESTRICTED_11D_5G 6 -#define LOCALE_RESTRICTED_LOW_HI 7 -#define LOCALE_RESTRICTED_12_13_14 8 - -#define LOCALE_2G_IDX_i 0 -#define LOCALE_5G_IDX_11 0 #define LOCALE_MIMO_IDX_bn 0 #define LOCALE_MIMO_IDX_11n 0 -/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */ -#define BRCMS_MAXPWR_TBL_SIZE 6 /* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ #define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 -/* power level in group of 2.4GHz band channels: - * maxpwr[0] - CCK channels [1] - * maxpwr[1] - CCK channels [2-10] - * maxpwr[2] - CCK channels [11-14] - * maxpwr[3] - OFDM channels [1] - * maxpwr[4] - OFDM channels [2-10] - * maxpwr[5] - OFDM channels [11-14] - */ - /* maxpwr mapping to 5GHz band channels: * maxpwr[0] - channels [34-48] * maxpwr[1] - channels [52-60] @@ -101,16 +47,8 @@ #define LC(id) LOCALE_MIMO_IDX_ ## id -#define LC_2G(id) LOCALE_2G_IDX_ ## id - -#define LC_5G(id) LOCALE_5G_IDX_ ## id - -#define LOCALES(band2, band5, mimo2, mimo5) \ - {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} - -/* macro to get 2.4 GHz channel group index for tx power */ -#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) -#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) +#define LOCALES(mimo2, mimo5) \ + {LC(mimo2), LC(mimo5)} /* macro to get 5 GHz channel group index for tx power */ #define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ @@ -118,18 +56,37 @@ (((c) < 100) ? 2 : \ (((c) < 149) ? 3 : 4)))) -#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU) - -struct brcms_cm_band { - /* struct locale_info flags */ - u8 locale_flags; - /* List of valid channels in the country */ - struct brcms_chanvec valid_channels; - /* List of restricted use channels */ - const struct brcms_chanvec *restricted_channels; - /* List of radar sensitive channels */ - const struct brcms_chanvec *radar_channels; - u8 PAD[8]; +#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) +#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) +#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_DFS | \ + NL80211_RRF_NO_IBSS) +#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_DFS | \ + NL80211_RRF_NO_IBSS) +#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +static const struct ieee80211_regdomain brcms_regdom_x2 = { + .n_reg_rules = 7, + .alpha2 = "X2", + .reg_rules = { + BRCM_2GHZ_2412_2462, + BRCM_2GHZ_2467_2472, + BRCM_5GHZ_5180_5240, + BRCM_5GHZ_5260_5320, + BRCM_5GHZ_5500_5700, + BRCM_5GHZ_5745_5825, + } }; /* locale per-channel tx power limits for MIMO frames @@ -141,337 +98,23 @@ struct locale_mimo_info { s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; /* tx 40 MHz power limits, qdBm units */ s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; - u8 flags; }; /* Country names and abbreviations with locale defined from ISO 3166 */ struct country_info { - const u8 locale_2G; /* 2.4G band locale */ - const u8 locale_5G; /* 5G band locale */ const u8 locale_mimo_2G; /* 2.4G mimo info */ const u8 locale_mimo_5G; /* 5G mimo info */ }; +struct brcms_regd { + struct country_info country; + const struct ieee80211_regdomain *regdomain; +}; + struct brcms_cm_info { struct brcms_pub *pub; struct brcms_c_info *wlc; - char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ - uint srom_regrev; /* Regulatory Rev for the SROM ccode */ - const struct country_info *country; /* current country def */ - char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */ - uint regrev; /* current Regulatory Revision */ - char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */ - /* per-band state (one per phy/radio) */ - struct brcms_cm_band bandstate[MAXBANDS]; - /* quiet channels currently for radar sensitivity or 11h support */ - /* channels on which we cannot transmit */ - struct brcms_chanvec quiet_channels; -}; - -/* locale channel and power info. */ -struct locale_info { - u32 valid_channels; - /* List of radar sensitive channels */ - u8 radar_channels; - /* List of channels used only if APs are detected */ - u8 restricted_channels; - /* Max tx pwr in qdBm for each sub-band */ - s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE]; - /* Country IE advertised max tx pwr in dBm per sub-band */ - s8 pub_maxpwr[BAND_5G_PWR_LVLS]; - u8 flags; -}; - -/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */ - -/* - * Some common channel sets - */ - -/* No channels */ -static const struct brcms_chanvec chanvec_none = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* All 2.4 GHz HW channels */ -static const struct brcms_chanvec chanvec_all_2G = { - {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* All 5 GHz HW channels */ -static const struct brcms_chanvec chanvec_all_5G = { - {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11, - 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11, - 0x11, 0x11, 0x11, 0x01} -}; - -/* - * Radar channel sets - */ - -/* Channels 52 - 64, 100 - 140 */ -static const struct brcms_chanvec radar_set1 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ - 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ - 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ - 0x00, 0x00, 0x00, 0x00} -}; - -/* - * Restricted channel sets - */ - -/* Channels 34, 38, 42, 46 */ -static const struct brcms_chanvec restricted_set_japan_legacy = { - {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* Channels 12, 13 */ -static const struct brcms_chanvec restricted_set_2g_short = { - {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* Channel 165 */ -static const struct brcms_chanvec restricted_chan_165 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* Channels 36 - 48 & 149 - 165 */ -static const struct brcms_chanvec restricted_low_hi = { - {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* Channels 12 - 14 */ -static const struct brcms_chanvec restricted_set_12_13_14 = { - {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -/* global memory to provide working buffer for expanded locale */ - -static const struct brcms_chanvec *g_table_radar_set[] = { - &chanvec_none, - &radar_set1 -}; - -static const struct brcms_chanvec *g_table_restricted_chan[] = { - &chanvec_none, /* restricted_set_none */ - &restricted_set_2g_short, - &restricted_chan_165, - &chanvec_all_5G, - &restricted_set_japan_legacy, - &chanvec_all_2G, /* restricted_set_11d_2G */ - &chanvec_all_5G, /* restricted_set_11d_5G */ - &restricted_low_hi, - &restricted_set_12_13_14 -}; - -static const struct brcms_chanvec locale_2g_01_11 = { - {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_2g_12_13 = { - {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_2g_14 = { - {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_LOW_JP1 = { - {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_LOW_JP2 = { - {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_LOW1 = { - {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_LOW2 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_LOW3 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_MID1 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_MID2 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_MID3 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_HIGH1 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_HIGH2 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_HIGH3 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_52_140_ALL = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; - -static const struct brcms_chanvec locale_5g_HIGH4 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, - 0x11, 0x11, 0x11, 0x11} -}; - -static const struct brcms_chanvec *g_table_locale_base[] = { - &locale_2g_01_11, - &locale_2g_12_13, - &locale_2g_14, - &locale_5g_LOW_JP1, - &locale_5g_LOW_JP2, - &locale_5g_LOW1, - &locale_5g_LOW2, - &locale_5g_LOW3, - &locale_5g_MID1, - &locale_5g_MID2, - &locale_5g_MID3, - &locale_5g_HIGH1, - &locale_5g_HIGH2, - &locale_5g_HIGH3, - &locale_5g_52_140_ALL, - &locale_5g_HIGH4 -}; - -static void brcms_c_locale_add_channels(struct brcms_chanvec *target, - const struct brcms_chanvec *channels) -{ - u8 i; - for (i = 0; i < sizeof(struct brcms_chanvec); i++) - target->vec[i] |= channels->vec[i]; -} - -static void brcms_c_locale_get_channels(const struct locale_info *locale, - struct brcms_chanvec *channels) -{ - u8 i; - - memset(channels, 0, sizeof(struct brcms_chanvec)); - - for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) { - if (locale->valid_channels & (1 << i)) - brcms_c_locale_add_channels(channels, - g_table_locale_base[i]); - } -} - -/* - * Locale Definitions - 2.4 GHz - */ -static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */ - LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13, - LOCALE_RADAR_SET_NONE, - LOCALE_RESTRICTED_SET_2G_SHORT, - {QDB(19), QDB(19), QDB(19), - QDB(19), QDB(19), QDB(19)}, - {20, 20, 20, 0}, - BRCMS_EIRP -}; - -/* - * Locale Definitions - 5 GHz - */ -static const struct locale_info locale_11 = { - /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */ - LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165, - LOCALE_RADAR_SET_1, - LOCALE_RESTRICTED_NONE, - {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)}, - {23, 23, 23, 30, 30}, - BRCMS_EIRP | BRCMS_DFS_EU -}; - -static const struct locale_info *g_locale_2g_table[] = { - &locale_i -}; - -static const struct locale_info *g_locale_5g_table[] = { - &locale_11 + const struct brcms_regd *world_regd; }; /* @@ -484,7 +127,6 @@ static const struct locale_mimo_info locale_bn = { {0, 0, QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), 0, 0}, - 0 }; static const struct locale_mimo_info *g_mimo_2g_table[] = { @@ -497,114 +139,20 @@ static const struct locale_mimo_info *g_mimo_2g_table[] = { static const struct locale_mimo_info locale_11n = { { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, - 0 }; static const struct locale_mimo_info *g_mimo_5g_table[] = { &locale_11n }; -static const struct { - char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */ - struct country_info country; -} cntry_locales[] = { +static const struct brcms_regd cntry_locales[] = { + /* Worldwide RoW 2, must always be at index 0 */ { - "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */ -}; - -#ifdef SUPPORT_40MHZ -/* 20MHz channel info for 40MHz pairing support */ -struct chan20_info { - u8 sb; - u8 adj_sbs; + .country = LOCALES(bn, 11n), + .regdomain = &brcms_regdom_x2, + }, }; -/* indicates adjacent channels that are allowed for a 40 Mhz channel and - * those that permitted by the HT - */ -struct chan20_info chan20_info[] = { - /* 11b/11g */ -/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 11 */ {12, (CH_LOWER_SB)}, -/* 12 */ {13, (CH_LOWER_SB)}, -/* 13 */ {14, (CH_LOWER_SB)}, - -/* 11a japan high */ -/* 14 */ {34, (CH_UPPER_SB)}, -/* 15 */ {38, (CH_LOWER_SB)}, -/* 16 */ {42, (CH_LOWER_SB)}, -/* 17 */ {46, (CH_LOWER_SB)}, - -/* 11a usa low */ -/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)}, - -/* 11a Europe */ -/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 36 */ {140, (CH_LOWER_SB)}, - -/* 11a usa high, ref5 only */ -/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */ -/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)}, -/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)}, -/* 41 */ {165, (CH_LOWER_SB)}, - -/* 11a japan */ -/* 42 */ {184, (CH_UPPER_SB)}, -/* 43 */ {188, (CH_LOWER_SB)}, -/* 44 */ {192, (CH_UPPER_SB)}, -/* 45 */ {196, (CH_LOWER_SB)}, -/* 46 */ {200, (CH_UPPER_SB)}, -/* 47 */ {204, (CH_LOWER_SB)}, -/* 48 */ {208, (CH_UPPER_SB)}, -/* 49 */ {212, (CH_LOWER_SB)}, -/* 50 */ {216, (CH_LOWER_SB)} -}; -#endif /* SUPPORT_40MHZ */ - -static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx) -{ - if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) - return NULL; /* error condition */ - - return g_locale_2g_table[locale_idx]; -} - -static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx) -{ - if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) - return NULL; /* error condition */ - - return g_locale_5g_table[locale_idx]; -} - static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) { if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) @@ -621,13 +169,6 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx) return g_mimo_5g_table[locale_idx]; } -static int -brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode, - char *mapped_ccode, uint *mapped_regrev) -{ - return false; -} - /* * Indicates whether the country provided is valid to pass * to cfg80211 or not. @@ -662,155 +203,24 @@ static bool brcms_c_country_valid(const char *ccode) return true; } -/* Lookup a country info structure from a null terminated country - * abbreviation and regrev directly with no translation. - */ -static const struct country_info * -brcms_c_country_lookup_direct(const char *ccode, uint regrev) +static const struct brcms_regd *brcms_world_regd(const char *regdom, int len) { - uint size, i; - - /* Should just return 0 for single locale driver. */ - /* Keep it this way in case we add more locales. (for now anyway) */ - - /* - * all other country def arrays are for regrev == 0, so if - * regrev is non-zero, fail - */ - if (regrev > 0) - return NULL; - - /* find matched table entry from country code */ - size = ARRAY_SIZE(cntry_locales); - for (i = 0; i < size; i++) { - if (strcmp(ccode, cntry_locales[i].abbrev) == 0) - return &cntry_locales[i].country; - } - return NULL; -} - -static const struct country_info * -brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode, - char *mapped_ccode, uint *mapped_regrev) -{ - struct brcms_c_info *wlc = wlc_cm->wlc; - const struct country_info *country; - uint srom_regrev = wlc_cm->srom_regrev; - const char *srom_ccode = wlc_cm->srom_ccode; - int mapped; - - /* check for currently supported ccode size */ - if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) { - wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for " - "match\n", wlc->pub->unit, __func__, ccode); - return NULL; - } - - /* default mapping is the given ccode and regrev 0 */ - strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); - *mapped_regrev = 0; - - /* If the desired country code matches the srom country code, - * then the mapped country is the srom regulatory rev. - * Otherwise look for an aggregate mapping. - */ - if (!strcmp(srom_ccode, ccode)) { - *mapped_regrev = srom_regrev; - mapped = 0; - wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__); - } else { - mapped = - brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode, - mapped_regrev); - } - - /* find the matching built-in country definition */ - country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); - - /* if there is not an exact rev match, default to rev zero */ - if (country == NULL && *mapped_regrev != 0) { - *mapped_regrev = 0; - country = - brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); - } - - return country; -} - -/* Lookup a country info structure from a null terminated country code - * The lookup is case sensitive. - */ -static const struct country_info * -brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode) -{ - const struct country_info *country; - char mapped_ccode[BRCM_CNTRY_BUF_SZ]; - uint mapped_regrev; - - /* - * map the country code to a built-in country code, regrev, and - * country_info struct - */ - country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode, - &mapped_regrev); - - return country; -} - -/* - * reset the quiet channels vector to the union - * of the restricted and radar channel sets - */ -static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) -{ - struct brcms_c_info *wlc = wlc_cm->wlc; - uint i, j; - struct brcms_band *band; - const struct brcms_chanvec *chanvec; - - memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec)); - - band = wlc->band; - for (i = 0; i < wlc->pub->_nbands; - i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { - - /* initialize quiet channels for restricted channels */ - chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels; - for (j = 0; j < sizeof(struct brcms_chanvec); j++) - wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j]; + const struct brcms_regd *regd = NULL; + int i; + for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) { + if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) { + regd = &cntry_locales[i]; + break; + } } -} - -/* Is the channel valid for the current locale and current band? */ -static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val) -{ - struct brcms_c_info *wlc = wlc_cm->wlc; - return ((val < MAXCHANNEL) && - isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec, - val)); + return regd; } -/* Is the channel valid for the current locale and specified band? */ -static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm, - uint bandunit, uint val) -{ - return ((val < MAXCHANNEL) - && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val)); -} - -/* Is the channel valid for the current locale? (but don't consider channels not - * available due to bandlocking) - */ -static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val) +static const struct brcms_regd *brcms_default_world_regd(void) { - struct brcms_c_info *wlc = wlc_cm->wlc; - - return brcms_c_valid_channel20(wlc->cmi, val) || - (!wlc->bandlocked - && brcms_c_valid_channel20_in_band(wlc->cmi, - OTHERBANDUNIT(wlc), val)); + return &cntry_locales[0]; } /* JP, J1 - J10 are Japan ccodes */ @@ -820,12 +230,6 @@ static bool brcms_c_japan_ccode(const char *ccode) (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9'))); } -/* Returns true if currently set country is Japan or variant */ -static bool brcms_c_japan(struct brcms_c_info *wlc) -{ - return brcms_c_japan_ccode(wlc->cmi->country_abbrev); -} - static void brcms_c_channel_min_txpower_limits_with_local_constraint( struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, @@ -901,140 +305,16 @@ brcms_c_channel_min_txpower_limits_with_local_constraint( } -/* Update the radio state (enable/disable) and tx power targets - * based on a new set of channel/regulatory information - */ -static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) -{ - struct brcms_c_info *wlc = wlc_cm->wlc; - uint chan; - struct txpwr_limits txpwr; - - /* search for the existence of any valid channel */ - for (chan = 0; chan < MAXCHANNEL; chan++) { - if (brcms_c_valid_channel20_db(wlc->cmi, chan)) - break; - } - if (chan == MAXCHANNEL) - chan = INVCHANNEL; - - /* - * based on the channel search above, set or - * clear WL_RADIO_COUNTRY_DISABLE. - */ - if (chan == INVCHANNEL) { - /* - * country/locale with no valid channels, set - * the radio disable bit - */ - mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); - wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " - "nbands %d bandlocked %d\n", wlc->pub->unit, - __func__, wlc_cm->country_abbrev, wlc->pub->_nbands, - wlc->bandlocked); - } else if (mboolisset(wlc->pub->radio_disabled, - WL_RADIO_COUNTRY_DISABLE)) { - /* - * country/locale with valid channel, clear - * the radio disable bit - */ - mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); - } - - /* - * Now that the country abbreviation is set, if the radio supports 2G, - * then set channel 14 restrictions based on the new locale. - */ - if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) - wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, - brcms_c_japan(wlc) ? true : - false); - - if (wlc->pub->up && chan != INVCHANNEL) { - brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); - brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, - &txpwr, BRCMS_TXPWR_MAX); - wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec); - } -} - -static int -brcms_c_channels_init(struct brcms_cm_info *wlc_cm, - const struct country_info *country) -{ - struct brcms_c_info *wlc = wlc_cm->wlc; - uint i, j; - struct brcms_band *band; - const struct locale_info *li; - struct brcms_chanvec sup_chan; - const struct locale_mimo_info *li_mimo; - - band = wlc->band; - for (i = 0; i < wlc->pub->_nbands; - i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { - - li = (band->bandtype == BRCM_BAND_5G) ? - brcms_c_get_locale_5g(country->locale_5G) : - brcms_c_get_locale_2g(country->locale_2G); - wlc_cm->bandstate[band->bandunit].locale_flags = li->flags; - li_mimo = (band->bandtype == BRCM_BAND_5G) ? - brcms_c_get_mimo_5g(country->locale_mimo_5G) : - brcms_c_get_mimo_2g(country->locale_mimo_2G); - - /* merge the mimo non-mimo locale flags */ - wlc_cm->bandstate[band->bandunit].locale_flags |= - li_mimo->flags; - - wlc_cm->bandstate[band->bandunit].restricted_channels = - g_table_restricted_chan[li->restricted_channels]; - wlc_cm->bandstate[band->bandunit].radar_channels = - g_table_radar_set[li->radar_channels]; - - /* - * set the channel availability, masking out the channels - * that may not be supported on this phy. - */ - wlc_phy_chanspec_band_validch(band->pi, band->bandtype, - &sup_chan); - brcms_c_locale_get_channels(li, - &wlc_cm->bandstate[band->bandunit]. - valid_channels); - for (j = 0; j < sizeof(struct brcms_chanvec); j++) - wlc_cm->bandstate[band->bandunit].valid_channels. - vec[j] &= sup_chan.vec[j]; - } - - brcms_c_quiet_channels_reset(wlc_cm); - brcms_c_channels_commit(wlc_cm); - - return 0; -} - /* * set the driver's current country and regulatory information * using a country code as the source. Look up built in country * information found with the country code. */ static void -brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, - const char *country_abbrev, - const char *ccode, uint regrev, - const struct country_info *country) +brcms_c_set_country(struct brcms_cm_info *wlc_cm, + const struct brcms_regd *regd) { - const struct locale_info *locale; struct brcms_c_info *wlc = wlc_cm->wlc; - char prev_country_abbrev[BRCM_CNTRY_BUF_SZ]; - - /* save current country state */ - wlc_cm->country = country; - - memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ); - strncpy(prev_country_abbrev, wlc_cm->country_abbrev, - BRCM_CNTRY_BUF_SZ - 1); - - strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); - strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); - wlc_cm->regrev = regrev; if ((wlc->pub->_n_enab & SUPPORT_11N) != wlc->protection->nmode_user) @@ -1042,75 +322,19 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); - /* set or restore gmode as required by regulatory */ - locale = brcms_c_get_locale_2g(country->locale_2G); - if (locale && (locale->flags & BRCMS_NO_OFDM)) - brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); - else - brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); - brcms_c_channels_init(wlc_cm, country); + brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); return; } -static int -brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, - const char *country_abbrev, - const char *ccode, int regrev) -{ - const struct country_info *country; - char mapped_ccode[BRCM_CNTRY_BUF_SZ]; - uint mapped_regrev; - - /* if regrev is -1, lookup the mapped country code, - * otherwise use the ccode and regrev directly - */ - if (regrev == -1) { - /* - * map the country code to a built-in country - * code, regrev, and country_info - */ - country = - brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode, - &mapped_regrev); - } else { - /* find the matching built-in country definition */ - country = brcms_c_country_lookup_direct(ccode, regrev); - strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); - mapped_regrev = regrev; - } - - if (country == NULL) - return -EINVAL; - - /* set the driver state for the country */ - brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode, - mapped_regrev, country); - - return 0; -} - -/* - * set the driver's current country and regulatory information using - * a country code as the source. Lookup built in country information - * found with the country code. - */ -static int -brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode) -{ - char country_abbrev[BRCM_CNTRY_BUF_SZ]; - strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ); - return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1); -} - struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) { struct brcms_cm_info *wlc_cm; - char country_abbrev[BRCM_CNTRY_BUF_SZ]; - const struct country_info *country; struct brcms_pub *pub = wlc->pub; struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; + const char *ccode = sprom->alpha2; + int ccode_len = sizeof(sprom->alpha2); BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); @@ -1122,24 +346,27 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) wlc->cmi = wlc_cm; /* store the country code for passing up as a regulatory hint */ - if (sprom->alpha2 && brcms_c_country_valid(sprom->alpha2)) - strncpy(wlc->pub->srom_ccode, sprom->alpha2, sizeof(sprom->alpha2)); + wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len); + if (brcms_c_country_valid(ccode)) + strncpy(wlc->pub->srom_ccode, ccode, ccode_len); /* - * internal country information which must match - * regulatory constraints in firmware + * If no custom world domain is found in the SROM, use the + * default "X2" domain. */ - memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ); - strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1); - country = brcms_c_country_lookup(wlc, country_abbrev); + if (!wlc_cm->world_regd) { + wlc_cm->world_regd = brcms_default_world_regd(); + ccode = wlc_cm->world_regd->regdomain->alpha2; + ccode_len = BRCM_CNTRY_BUF_SZ - 1; + } /* save default country for exiting 11d regulatory mode */ - strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); + strncpy(wlc->country_default, ccode, ccode_len); /* initialize autocountry_default to driver default */ - strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1); + strncpy(wlc->autocountry_default, ccode, ccode_len); - brcms_c_set_countrycode(wlc_cm, country_abbrev); + brcms_c_set_country(wlc_cm, wlc_cm->world_regd); return wlc_cm; } @@ -1149,31 +376,15 @@ void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm) kfree(wlc_cm); } -u8 -brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, - uint bandunit) -{ - return wlc_cm->bandstate[bandunit].locale_flags; -} - -static bool -brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) -{ - return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) && - CHSPEC_IS40(chspec) ? - (isset(wlc_cm->quiet_channels.vec, - lower_20_sb(CHSPEC_CHANNEL(chspec))) || - isset(wlc_cm->quiet_channels.vec, - upper_20_sb(CHSPEC_CHANNEL(chspec)))) : - isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); -} - void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, u8 local_constraint_qdbm) { struct brcms_c_info *wlc = wlc_cm->wlc; + struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; + const struct ieee80211_reg_rule *reg_rule; struct txpwr_limits txpwr; + int ret; brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); @@ -1181,8 +392,15 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, wlc_cm, &txpwr, local_constraint_qdbm ); + /* set or restore gmode as required by regulatory */ + ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, ®_rule); + if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM)) + brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); + else + brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); + brcms_b_set_chanspec(wlc->hw, chanspec, - (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0), + !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN), &txpwr); } @@ -1191,15 +409,14 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, struct txpwr_limits *txpwr) { struct brcms_c_info *wlc = wlc_cm->wlc; + struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; uint i; uint chan; int maxpwr; int delta; const struct country_info *country; struct brcms_band *band; - const struct locale_info *li; int conducted_max = BRCMS_TXPWR_MAX; - int conducted_ofdm_max = BRCMS_TXPWR_MAX; const struct locale_mimo_info *li_mimo; int maxpwr20, maxpwr40; int maxpwr_idx; @@ -1207,67 +424,35 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, memset(txpwr, 0, sizeof(struct txpwr_limits)); - if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) { - country = brcms_c_country_lookup(wlc, wlc->autocountry_default); - if (country == NULL) - return; - } else { - country = wlc_cm->country; - } + if (WARN_ON(!ch)) + return; + + country = &wlc_cm->world_regd->country; chan = CHSPEC_CHANNEL(chanspec); band = wlc->bandstate[chspec_bandunit(chanspec)]; - li = (band->bandtype == BRCM_BAND_5G) ? - brcms_c_get_locale_5g(country->locale_5G) : - brcms_c_get_locale_2g(country->locale_2G); - li_mimo = (band->bandtype == BRCM_BAND_5G) ? brcms_c_get_mimo_5g(country->locale_mimo_5G) : brcms_c_get_mimo_2g(country->locale_mimo_2G); - if (li->flags & BRCMS_EIRP) { - delta = band->antgain; - } else { - delta = 0; - if (band->antgain > QDB(6)) - delta = band->antgain - QDB(6); /* Excess over 6 dB */ - } + delta = band->antgain; - if (li == &locale_i) { + if (band->bandtype == BRCM_BAND_2G) conducted_max = QDB(22); - conducted_ofdm_max = QDB(22); - } + + maxpwr = QDB(ch->max_power) - delta; + maxpwr = max(maxpwr, 0); + maxpwr = min(maxpwr, conducted_max); /* CCK txpwr limits for 2.4G band */ if (band->bandtype == BRCM_BAND_2G) { - maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)]; - - maxpwr = maxpwr - delta; - maxpwr = max(maxpwr, 0); - maxpwr = min(maxpwr, conducted_max); - for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) txpwr->cck[i] = (u8) maxpwr; } - /* OFDM txpwr limits for 2.4G or 5G bands */ - if (band->bandtype == BRCM_BAND_2G) - maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; - else - maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; - - maxpwr = maxpwr - delta; - maxpwr = max(maxpwr, 0); - maxpwr = min(maxpwr, conducted_ofdm_max); - - /* Keep OFDM lmit below CCK limit */ - if (band->bandtype == BRCM_BAND_2G) - maxpwr = min_t(int, maxpwr, txpwr->cck[0]); - - for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) + for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { txpwr->ofdm[i] = (u8) maxpwr; - for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { /* * OFDM 40 MHz SISO has the same power as the corresponding * MCS0-7 rate unless overriden by the locale specific code. @@ -1282,14 +467,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, txpwr->ofdm_40_cdd[i] = 0; } - /* MIMO/HT specific limits */ - if (li_mimo->flags & BRCMS_EIRP) { - delta = band->antgain; - } else { - delta = 0; - if (band->antgain > QDB(6)) - delta = band->antgain - QDB(6); /* Excess over 6 dB */ - } + delta = 0; + if (band->antgain > QDB(6)) + delta = band->antgain - QDB(6); /* Excess over 6 dB */ if (band->bandtype == BRCM_BAND_2G) maxpwr_idx = (chan - 1); @@ -1431,8 +611,7 @@ static bool brcms_c_chspec_malformed(u16 chanspec) * and they are also a legal HT combination */ static bool -brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, - bool dualband) +brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec) { struct brcms_c_info *wlc = wlc_cm->wlc; u8 channel = CHSPEC_CHANNEL(chspec); @@ -1448,59 +627,163 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, chspec_bandunit(chspec)) return false; - /* Check a 20Mhz channel */ - if (CHSPEC_IS20(chspec)) { - if (dualband) - return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi, - channel); - else - return brcms_c_valid_channel20(wlc_cm->wlc->cmi, - channel); + return true; +} + +bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) +{ + return brcms_c_valid_chanspec_ext(wlc_cm, chspec); +} + +static bool brcms_is_radar_freq(u16 center_freq) +{ + return center_freq >= 5260 && center_freq <= 5700; +} + +static void brcms_reg_apply_radar_flags(struct wiphy *wiphy) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + int i; + + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + if (!sband) + return; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + if (!brcms_is_radar_freq(ch->center_freq)) + continue; + + /* + * All channels in this range should be passive and have + * DFS enabled. + */ + if (!(ch->flags & IEEE80211_CHAN_DISABLED)) + ch->flags |= IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; } -#ifdef SUPPORT_40MHZ - /* - * We know we are now checking a 40MHZ channel, so we should - * only be here for NPHYS - */ - if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { - u8 upper_sideband = 0, idx; - u8 num_ch20_entries = - sizeof(chan20_info) / sizeof(struct chan20_info); - - if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec))) - return false; - - if (dualband) { - if (!brcms_c_valid_channel20_db(wlc->cmi, - lower_20_sb(channel)) || - !brcms_c_valid_channel20_db(wlc->cmi, - upper_20_sb(channel))) - return false; - } else { - if (!brcms_c_valid_channel20(wlc->cmi, - lower_20_sb(channel)) || - !brcms_c_valid_channel20(wlc->cmi, - upper_20_sb(channel))) - return false; +} + +static void +brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + const struct ieee80211_reg_rule *rule; + int band, i, ret; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + if (ch->flags & + (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR)) + continue; + + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { + ret = freq_reg_info(wiphy, ch->center_freq, + 0, &rule); + if (ret) + continue; + + if (!(rule->flags & NL80211_RRF_NO_IBSS)) + ch->flags &= ~IEEE80211_CHAN_NO_IBSS; + if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN)) + ch->flags &= + ~IEEE80211_CHAN_PASSIVE_SCAN; + } else if (ch->beacon_found) { + ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN); + } } + } +} - /* find the lower sideband info in the sideband array */ - for (idx = 0; idx < num_ch20_entries; idx++) { - if (chan20_info[idx].sb == lower_20_sb(channel)) - upper_sideband = chan20_info[idx].adj_sbs; +static int brcms_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct brcms_info *wl = hw->priv; + struct brcms_c_info *wlc = wl->wlc; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + int band, i; + bool ch_found = false; + + brcms_reg_apply_radar_flags(wiphy); + + if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) + brcms_reg_apply_beaconing_flags(wiphy, request->initiator); + + /* Disable radio if all channels disallowed by regulatory */ + for (band = 0; !ch_found && band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + + for (i = 0; !ch_found && i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + if (!(ch->flags & IEEE80211_CHAN_DISABLED)) + ch_found = true; } - /* check that the lower sideband allows an upper sideband */ - if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == - (CH_UPPER_SB | CH_EWA_VALID)) - return true; - return false; } -#endif /* 40 MHZ */ - return false; + if (ch_found) { + mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); + } else { + mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); + wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n", + wlc->pub->unit, __func__, request->alpha2); + } + + if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) + wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, + brcms_c_japan_ccode(request->alpha2)); + + return 0; } -bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) +void brcms_c_regd_init(struct brcms_c_info *wlc) { - return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true); + struct wiphy *wiphy = wlc->wiphy; + const struct brcms_regd *regd = wlc->cmi->world_regd; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct brcms_chanvec sup_chan; + struct brcms_band *band; + int band_idx, i; + + /* Disable any channels not supported by the phy */ + for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) { + band = wlc->bandstate[band_idx]; + + wlc_phy_chanspec_band_validch(band->pi, band->bandtype, + &sup_chan); + + if (band_idx == BAND_2G_INDEX) + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (!isset(sup_chan.vec, ch->hw_value)) + ch->flags |= IEEE80211_CHAN_DISABLED; + } + } + + wlc->wiphy->reg_notifier = brcms_reg_notifier; + wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | + WIPHY_FLAG_STRICT_REGULATORY; + wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain); + brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER); } diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h index 808cb4fbfbe7..006483a0abe6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h @@ -37,9 +37,6 @@ brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); -extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, - uint bandunit); - extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec); @@ -49,5 +46,6 @@ extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, u8 local_constraint_qdbm); +extern void brcms_c_regd_init(struct brcms_c_info *wlc); #endif /* _WLC_CHANNEL_H */ diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 11054ae9d4f6..5e53305bd9a9 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -573,6 +573,7 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, struct dma_info *di; u8 rev = core->id.rev; uint size; + struct si_info *sii = container_of(sih, struct si_info, pub); /* allocate private info structure */ di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC); @@ -633,16 +634,20 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, */ di->ddoffsetlow = 0; di->dataoffsetlow = 0; - /* add offset for pcie with DMA64 bus */ - di->ddoffsetlow = 0; - di->ddoffsethigh = SI_PCIE_DMA_H32; + /* for pci bus, add offset */ + if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) { + /* add offset for pcie with DMA64 bus */ + di->ddoffsetlow = 0; + di->ddoffsethigh = SI_PCIE_DMA_H32; + } di->dataoffsetlow = di->ddoffsetlow; di->dataoffsethigh = di->ddoffsethigh; + /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ - if ((core->id.id == SDIOD_CORE_ID) + if ((core->id.id == BCMA_CORE_SDIO_DEV) && ((rev > 0) && (rev <= 2))) di->addrext = false; - else if ((core->id.id == I2S_CORE_ID) && + else if ((core->id.id == BCMA_CORE_I2S) && ((rev == 0) || (rev == 1))) di->addrext = false; else @@ -1433,7 +1438,7 @@ void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) struct ieee80211_tx_info *tx_info; while (i != end) { - skb = (struct sk_buff *)di->txp[i]; + skb = di->txp[i]; if (skb != NULL) { tx_info = (struct ieee80211_tx_info *)skb->cb; (callback_fnc)(tx_info, arg_a); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 50f92a0b7c41..9e79d47e077f 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -267,6 +267,7 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct brcms_info *wl = hw->priv; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); spin_lock_bh(&wl->lock); if (!wl->pub->up) { @@ -275,6 +276,7 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) goto done; } brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); + tx_info->rate_driver_data[0] = tx_info->control.sta; done: spin_unlock_bh(&wl->lock); } @@ -319,8 +321,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw) return; spin_lock_bh(&wl->lock); - status = brcms_c_chipmatch(wl->wlc->hw->vendorid, - wl->wlc->hw->deviceid); + status = brcms_c_chipmatch(wl->wlc->hw->d11core); spin_unlock_bh(&wl->lock); if (!status) { wiphy_err(wl->wiphy, @@ -721,14 +722,6 @@ static const struct ieee80211_ops brcms_ops = { .flush = brcms_ops_flush, }; -/* - * is called in brcms_bcma_probe() context, therefore no locking required. - */ -static int brcms_set_hint(struct brcms_info *wl, char *abbrev) -{ - return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev); -} - void brcms_dpc(unsigned long data) { struct brcms_info *wl; @@ -1058,6 +1051,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) goto fail; } + brcms_c_regd_init(wl->wlc); + memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); if (WARN_ON(!is_valid_ether_addr(perm))) goto fail; @@ -1068,9 +1063,9 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" "%d\n", __func__, err); - if (wl->pub->srom_ccode[0] && brcms_set_hint(wl, wl->pub->srom_ccode)) - wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", - __func__, err); + if (wl->pub->srom_ccode[0] && + regulatory_hint(wl->wiphy, wl->pub->srom_ccode)) + wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__); n_adapters_found++; return wl; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 19db4052c44c..03ca65324845 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -18,6 +18,7 @@ #include <linux/pci_ids.h> #include <linux/if_ether.h> +#include <net/cfg80211.h> #include <net/mac80211.h> #include <brcm_hw_ids.h> #include <aiutils.h> @@ -268,7 +269,7 @@ struct brcms_c_bit_desc { */ /* Starting corerev for the fifo size table */ -#define XMTFIFOTBL_STARTREV 20 +#define XMTFIFOTBL_STARTREV 17 struct d11init { __le16 addr; @@ -332,6 +333,12 @@ const u8 wlc_prio2prec_map[] = { }; static const u16 xmtfifo_sz[][NFIFO] = { + /* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */ + {20, 192, 192, 21, 17, 5}, + /* corerev 18: */ + {0, 0, 0, 0, 0, 0}, + /* corerev 19: */ + {0, 0, 0, 0, 0, 0}, /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ {20, 192, 192, 21, 17, 5}, /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ @@ -342,6 +349,14 @@ static const u16 xmtfifo_sz[][NFIFO] = { {20, 192, 192, 21, 17, 5}, /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ {9, 58, 22, 14, 14, 5}, + /* corerev 25: */ + {0, 0, 0, 0, 0, 0}, + /* corerev 26: */ + {0, 0, 0, 0, 0, 0}, + /* corerev 27: */ + {0, 0, 0, 0, 0, 0}, + /* corerev 28: 2304, 14848, 5632, 3584, 3584, 1280 */ + {9, 58, 22, 14, 14, 5}, }; #ifdef DEBUG @@ -878,7 +893,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) tx_info = IEEE80211_SKB_CB(p); h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); - if (tx_info->control.sta) + if (tx_info->rate_driver_data[0]) scb = &wlc->pri_scb; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -1941,7 +1956,8 @@ static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) * accesses phyreg throughput mac. This can be skipped since * only mac reg is accessed below */ - flags |= SICF_PCLKE; + if (D11REV_GE(wlc_hw->corerev, 18)) + flags |= SICF_PCLKE; /* * TODO: test suspend/resume @@ -2022,7 +2038,8 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) * phyreg throughput mac, AND phy_reset is skipped at early stage when * band->pi is invalid. need to enable PHY CLK */ - flags |= SICF_PCLKE; + if (D11REV_GE(wlc_hw->corerev, 18)) + flags |= SICF_PCLKE; /* * reset the core @@ -2125,8 +2142,8 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) { struct bcma_device *core = wlc_hw->d11core; - if ((ai_get_chip_id(wlc_hw->sih) == BCM43224_CHIP_ID) || - (ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) { + if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43224) || + (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) { if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082); bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8); @@ -2790,7 +2807,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) tmp = 0; if (on) { - if ((ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { + if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) { bcma_set32(core, D11REGOFFS(clk_ctl_st), CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | @@ -3139,20 +3156,6 @@ void brcms_c_reset(struct brcms_c_info *wlc) brcms_b_reset(wlc->hw); } -/* Return the channel the driver should initialize during brcms_c_init. - * the channel may have to be changed from the currently configured channel - * if other configurations are in conflict (bandlocked, 11n mode disabled, - * invalid channel for current country, etc.) - */ -static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc) -{ - u16 chanspec = - 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | - WL_CHANSPEC_BAND_2G; - - return chanspec; -} - void brcms_c_init_scb(struct scb *scb) { int i; @@ -4231,9 +4234,8 @@ static void brcms_c_radio_timer(void *arg) } /* common low-level watchdog code */ -static void brcms_b_watchdog(void *arg) +static void brcms_b_watchdog(struct brcms_c_info *wlc) { - struct brcms_c_info *wlc = (struct brcms_c_info *) arg; struct brcms_hardware *wlc_hw = wlc->hw; BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); @@ -4254,10 +4256,8 @@ static void brcms_b_watchdog(void *arg) } /* common watchdog code */ -static void brcms_c_watchdog(void *arg) +static void brcms_c_watchdog(struct brcms_c_info *wlc) { - struct brcms_c_info *wlc = (struct brcms_c_info *) arg; - BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); if (!wlc->pub->up) @@ -4297,7 +4297,9 @@ static void brcms_c_watchdog(void *arg) static void brcms_c_watchdog_by_timer(void *arg) { - brcms_c_watchdog(arg); + struct brcms_c_info *wlc = (struct brcms_c_info *) arg; + + brcms_c_watchdog(wlc); } static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit) @@ -4467,11 +4469,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, } /* verify again the device is supported */ - if (core->bus->hosttype == BCMA_HOSTTYPE_PCI && - !brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " - "vendor/device (0x%x/0x%x)\n", - unit, pcidev->vendor, pcidev->device); + if (!brcms_c_chipmatch(core)) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported device\n", + unit); err = 12; goto fail; } @@ -4541,7 +4541,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, else wlc_hw->_nbands = 1; - if ((ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) + if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) wlc_hw->_nbands = 1; /* BMAC_NOTE: remove init of pub values when brcms_c_attach() @@ -4608,8 +4608,12 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, wlc_hw->machwcap_backup = wlc_hw->machwcap; /* init tx fifo size */ + WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 || + (wlc_hw->corerev - XMTFIFOTBL_STARTREV) > + ARRAY_SIZE(xmtfifo_sz)); wlc_hw->xmtfifo_sz = xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; + WARN_ON(!wlc_hw->xmtfifo_sz[0]); /* Get a phy for this band */ wlc_hw->band->pi = @@ -5049,7 +5053,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) wlc_hw->wlc->pub->hw_up = true; if ((wlc_hw->boardflags & BFL_FEM) - && (ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { + && (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) { if (! (wlc_hw->boardrev >= 0x1250 && (wlc_hw->boardflags & BFL_FEM_BT))) @@ -5129,6 +5133,8 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) /* make interface operational */ int brcms_c_up(struct brcms_c_info *wlc) { + struct ieee80211_channel *ch; + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); /* HW is turned off so don't try to access it */ @@ -5141,7 +5147,7 @@ int brcms_c_up(struct brcms_c_info *wlc) } if ((wlc->pub->boardflags & BFL_FEM) - && (ai_get_chip_id(wlc->hw->sih) == BCM4313_CHIP_ID)) { + && (ai_get_chip_id(wlc->hw->sih) == BCMA_CHIP_ID_BCM4313)) { if (wlc->pub->boardrev >= 0x1250 && (wlc->pub->boardflags & BFL_FEM_BT)) brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, @@ -5195,8 +5201,9 @@ int brcms_c_up(struct brcms_c_info *wlc) wlc->pub->up = true; if (wlc->bandinit_pending) { + ch = wlc->pub->ieee_hw->conf.channel; brcms_c_suspend_mac_and_wait(wlc); - brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec); + brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value)); wlc->bandinit_pending = false; brcms_c_enable_mac(wlc); } @@ -5397,11 +5404,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) else return -EINVAL; - /* Legacy or bust when no OFDM is supported by regulatory */ - if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) & - BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B)) - return -EINVAL; - /* update configuration value */ if (config) brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); @@ -5782,8 +5784,12 @@ void brcms_c_print_txstatus(struct tx_status *txs) (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); } -bool brcms_c_chipmatch(u16 vendor, u16 device) +static bool brcms_c_chipmatch_pci(struct bcma_device *core) { + struct pci_dev *pcidev = core->bus->host_pci; + u16 vendor = pcidev->vendor; + u16 device = pcidev->device; + if (vendor != PCI_VENDOR_ID_BROADCOM) { pr_err("unknown vendor id %04x\n", vendor); return false; @@ -5802,6 +5808,30 @@ bool brcms_c_chipmatch(u16 vendor, u16 device) return false; } +static bool brcms_c_chipmatch_soc(struct bcma_device *core) +{ + struct bcma_chipinfo *chipinfo = &core->bus->chipinfo; + + if (chipinfo->id == BCMA_CHIP_ID_BCM4716) + return true; + + pr_err("unknown chip id %04x\n", chipinfo->id); + return false; +} + +bool brcms_c_chipmatch(struct bcma_device *core) +{ + switch (core->bus->hosttype) { + case BCMA_HOSTTYPE_PCI: + return brcms_c_chipmatch_pci(core); + case BCMA_HOSTTYPE_SOC: + return brcms_c_chipmatch_soc(core); + default: + pr_err("unknown host type: %i\n", core->bus->hosttype); + return false; + } +} + #if defined(DEBUG) void brcms_c_print_txdesc(struct d11txh *txh) { @@ -8201,19 +8231,12 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) { struct bcma_device *core = wlc->hw->d11core; + struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; u16 chanspec; BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); - /* - * This will happen if a big-hammer was executed. In - * that case, we want to go back to the channel that - * we were on and not new channel - */ - if (wlc->pub->associated) - chanspec = wlc->home_chanspec; - else - chanspec = brcms_c_init_chanspec(wlc); + chanspec = ch20mhz_chspec(ch->hw_value); brcms_b_init(wlc->hw, chanspec); @@ -8318,7 +8341,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, struct brcms_pub *pub; /* allocate struct brcms_c_info state and its substructures */ - wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, 0); + wlc = brcms_c_attach_malloc(unit, &err, 0); if (wlc == NULL) goto fail; wlc->wiphy = wl->wiphy; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c index 264f8c4c703d..91937c5025ce 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c @@ -198,6 +198,8 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr) void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) { + struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); + if ((D11REV_GE(pi->sh->corerev, 24)) || (D11REV_IS(pi->sh->corerev, 22) && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { @@ -209,7 +211,8 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); } - if (++pi->phy_wreg >= pi->phy_wreg_limit) { + if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && + (++pi->phy_wreg >= pi->phy_wreg_limit)) { (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); pi->phy_wreg = 0; } @@ -292,10 +295,13 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val); if (addr == 0x72) - (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); + (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); #else + struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); + bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); - if (++pi->phy_wreg >= pi->phy_wreg_limit) { + if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && + (++pi->phy_wreg >= pi->phy_wreg_limit)) { pi->phy_wreg = 0; (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); } @@ -837,7 +843,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, pi->tbl_data_hi = tblDataHi; pi->tbl_data_lo = tblDataLo; - if (pi->sh->chip == BCM43224_CHIP_ID && + if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 && pi->sh->chiprev == 1) { pi->tbl_addr = tblAddr; pi->tbl_save_id = tbl_id; @@ -847,7 +853,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) { - if ((pi->sh->chip == BCM43224_CHIP_ID) && + if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && (pi->sh->chiprev == 1) && (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { read_phy_reg(pi, pi->tbl_data_lo); @@ -881,7 +887,7 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, for (idx = 0; idx < ptbl_info->tbl_len; idx++) { - if ((pi->sh->chip == BCM43224_CHIP_ID) && + if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && (pi->sh->chiprev == 1) && (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { read_phy_reg(pi, tblDataLo); @@ -918,7 +924,7 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, for (idx = 0; idx < ptbl_info->tbl_len; idx++) { - if ((pi->sh->chip == BCM43224_CHIP_ID) && + if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && (pi->sh->chiprev == 1)) { (void)read_phy_reg(pi, tblDataLo); @@ -2894,7 +2900,7 @@ const u8 *wlc_phy_get_ofdm_rate_lookup(void) void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) { - if ((pi->sh->chip == BCM4313_CHIP_ID) && + if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) && (pi->sh->boardflags & BFL_FEM)) { if (mode) { u16 txant = 0; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 13b261517cce..65db9b7458dc 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c @@ -14358,7 +14358,7 @@ void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs) wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); - if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) + if (pi->sh && (pi->sh->_rifs_phy != rifs)) pi->sh->_rifs_phy = rifs; } @@ -17893,6 +17893,8 @@ static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi) nphy_tpc_txgain_ipa_2g_2057rev7; } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; + if (pi->sh->chip == BCMA_CHIP_ID_BCM47162) + tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; } else { @@ -19254,8 +19256,14 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) case 38: case 102: case 118: - nphy_adj_tone_id_buf[0] = 0; - nphy_adj_noise_var_buf[0] = 0x0; + if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) && + (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) { + nphy_adj_tone_id_buf[0] = 32; + nphy_adj_noise_var_buf[0] = 0x21f; + } else { + nphy_adj_tone_id_buf[0] = 0; + nphy_adj_noise_var_buf[0] = 0x0; + } break; case 134: nphy_adj_tone_id_buf[0] = 32; @@ -19309,8 +19317,8 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && - ((pi->sh->chippkg == BCM4717_PKG_ID) || - (pi->sh->chippkg == BCM4718_PKG_ID))) { + ((pi->sh->chippkg == BCMA_PKG_ID_BCM4717) || + (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) { if ((pi->sh->boardflags & BFL_EXTLNA) && (CHSPEC_IS2G(pi->radio_chanspec))) ai_cc_reg(pi->sh->sih, @@ -19318,6 +19326,10 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) 0x40, 0x40); } + if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357)) + si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA, + CCTRL5357_EXTPA); + if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && CHSPEC_IS40(pi->radio_chanspec)) { @@ -20695,12 +20707,22 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, 0x1f); - write_radio_reg(pi, - RADIO_2056_SYN_PLL_LOOPFILTER4 | - RADIO_2056_SYN, 0xb); - write_radio_reg(pi, - RADIO_2056_SYN_PLL_CP2 | - RADIO_2056_SYN, 0x14); + if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || + (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) { + write_radio_reg(pi, + RADIO_2056_SYN_PLL_LOOPFILTER4 | + RADIO_2056_SYN, 0x14); + write_radio_reg(pi, + RADIO_2056_SYN_PLL_CP2 | + RADIO_2056_SYN, 0x00); + } else { + write_radio_reg(pi, + RADIO_2056_SYN_PLL_LOOPFILTER4 | + RADIO_2056_SYN, 0xb); + write_radio_reg(pi, + RADIO_2056_SYN_PLL_CP2 | + RADIO_2056_SYN, 0x14); + } } } @@ -20747,24 +20769,30 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PADG_IDAC, 0xcc); - bias = 0x25; - cascbias = 0x20; + if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || + (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) { + bias = 0x40; + cascbias = 0x45; + pag_boost_tune = 0x5; + pgag_boost_tune = 0x33; + padg_boost_tune = 0x77; + mixg_boost_tune = 0x55; + } else { + bias = 0x25; + cascbias = 0x20; - if ((pi->sh->chip == - BCM43224_CHIP_ID) - || (pi->sh->chip == - BCM43225_CHIP_ID)) { - if (pi->sh->chippkg == - BCM43224_FAB_SMIC) { + if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 || + pi->sh->chip == BCMA_CHIP_ID_BCM43225) && + pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) { bias = 0x2a; cascbias = 0x38; } - } - pag_boost_tune = 0x4; - pgag_boost_tune = 0x03; - padg_boost_tune = 0x77; - mixg_boost_tune = 0x65; + pag_boost_tune = 0x4; + pgag_boost_tune = 0x03; + padg_boost_tune = 0x77; + mixg_boost_tune = 0x65; + } WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, INTPAG_IMAIN_STAT, bias); @@ -20863,11 +20891,10 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, cascbias = 0x30; - if ((pi->sh->chip == BCM43224_CHIP_ID) || - (pi->sh->chip == BCM43225_CHIP_ID)) { - if (pi->sh->chippkg == BCM43224_FAB_SMIC) - cascbias = 0x35; - } + if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 || + pi->sh->chip == BCMA_CHIP_ID_BCM43225) && + pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) + cascbias = 0x35; pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; @@ -21106,6 +21133,7 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, const struct nphy_sfo_cfg *ci) { u16 val; + struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; if (CHSPEC_IS5G(chanspec) && !val) { @@ -21178,22 +21206,32 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (val == 54) spuravoid = 1; - } else { - if (pi->nphy_aband_spurwar_en && - ((val == 38) || (val == 102) - || (val == 118))) + } else if (pi->nphy_aband_spurwar_en && + ((val == 38) || (val == 102) || (val == 118))) { + if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) + && (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) { + spuravoid = 0; + } else { spuravoid = 1; + } } if (pi->phy_spuravoid == SPURAVOID_FORCEON) spuravoid = 1; - wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); - si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid); - wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); + if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || + (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { + bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, + spuravoid); + } else { + wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); + bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, + spuravoid); + wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); + } - if ((pi->sh->chip == BCM43224_CHIP_ID) || - (pi->sh->chip == BCM43225_CHIP_ID)) { + if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) || + (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { if (spuravoid == 1) { bcma_write16(pi->d11core, D11REGOFFS(tsf_clk_frac_l), @@ -21209,7 +21247,9 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, } } - wlapi_bmac_core_phypll_reset(pi->sh->physhim); + if (!((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || + (pi->sh->chip == BCMA_CHIP_ID_BCM47162))) + wlapi_bmac_core_phypll_reset(pi->sh->physhim); mod_phy_reg(pi, 0x01, (0x1 << 15), ((spuravoid > 0) ? (0x1 << 15) : 0)); @@ -22171,9 +22211,15 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, &auxADC_rssi_ctrlH_save); - radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) - + 82 * (auxADC_Vl) - 28861 + - 128) / 256; + if (pi->sh->chip == BCMA_CHIP_ID_BCM5357) { + radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1]) + + 88 * (auxADC_Vl) - 27111 + + 128) / 256; + } else { + radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) + + 82 * (auxADC_Vl) - 28861 + + 128) / 256; + } offset = (s16) pi->phy_tempsense_offset; @@ -24923,14 +24969,16 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, if (txgains->useindex) { phy_a4 = 15 - ((txgains->index) >> 3); if (CHSPEC_IS2G(pi->radio_chanspec)) { - if (NREV_GE(pi->pubpi.phy_rev, 6)) + if (NREV_GE(pi->pubpi.phy_rev, 6) && + pi->sh->chip == BCMA_CHIP_ID_BCM47162) { + phy_a5 = 0x10f7 | (phy_a4 << 8); + } else if (NREV_GE(pi->pubpi.phy_rev, 6)) { phy_a5 = 0x00f7 | (phy_a4 << 8); - - else - if (NREV_IS(pi->pubpi.phy_rev, 5)) + } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { phy_a5 = 0x10f7 | (phy_a4 << 8); - else + } else { phy_a5 = 0x50f7 | (phy_a4 << 8); + } } else { phy_a5 = 0x70f7 | (phy_a4 << 8); } diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c index 4931d29d077b..7e9df566c733 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c @@ -74,16 +74,6 @@ * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary * number to differentiate different PLLs controlled by the same PMU rev. */ -/* pllcontrol registers: - * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, - * p1div, p2div, _bypass_sdmod - */ -#define PMU1_PLL0_PLLCTL0 0 -#define PMU1_PLL0_PLLCTL1 1 -#define PMU1_PLL0_PLLCTL2 2 -#define PMU1_PLL0_PLLCTL3 3 -#define PMU1_PLL0_PLLCTL4 4 -#define PMU1_PLL0_PLLCTL5 5 /* pmu XtalFreqRatio */ #define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF @@ -108,118 +98,14 @@ #define RES4313_HT_AVAIL_RSRC 14 #define RES4313_MACPHY_CLK_AVAIL_RSRC 15 -/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */ -static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) -{ - u32 min_mask = 0, max_mask = 0; - uint rsrcs; - - /* # resources */ - rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT; - - /* determine min/max rsrc masks */ - switch (ai_get_chip_id(sih)) { - case BCM43224_CHIP_ID: - case BCM43225_CHIP_ID: - /* ??? */ - break; - - case BCM4313_CHIP_ID: - min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) | - PMURES_BIT(RES4313_XTAL_PU_RSRC) | - PMURES_BIT(RES4313_ALP_AVAIL_RSRC) | - PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC); - max_mask = 0xffff; - break; - default: - break; - } - - *pmin = min_mask; - *pmax = max_mask; -} - -void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid) -{ - u32 tmp = 0; - struct bcma_device *core; - - /* switch to chipc */ - core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); - - switch (ai_get_chip_id(sih)) { - case BCM43224_CHIP_ID: - case BCM43225_CHIP_ID: - if (spuravoid == 1) { - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL0); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x11500010); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL1); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x000C0C06); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL2); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x0F600a08); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL3); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x00000000); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL4); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x2001E920); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL5); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x88888815); - } else { - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL0); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x11100010); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL1); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x000c0c06); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL2); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x03000a08); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL3); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x00000000); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL4); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x200005c0); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), - PMU1_PLL0_PLLCTL5); - bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), - 0x88888815); - } - tmp = 1 << 10; - break; - - default: - /* bail out */ - return; - } - - bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp); -} - u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) { uint delay = PMU_MAX_TRANSITION_DLY; switch (ai_get_chip_id(sih)) { - case BCM43224_CHIP_ID: - case BCM43225_CHIP_ID: - case BCM4313_CHIP_ID: + case BCMA_CHIP_ID_BCM43224: + case BCMA_CHIP_ID_BCM43225: + case BCMA_CHIP_ID_BCM4313: delay = 3700; break; default: @@ -270,9 +156,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih) return clock; switch (ai_get_chip_id(sih)) { - case BCM43224_CHIP_ID: - case BCM43225_CHIP_ID: - case BCM4313_CHIP_ID: + case BCMA_CHIP_ID_BCM43224: + case BCMA_CHIP_ID_BCM43225: + case BCMA_CHIP_ID_BCM4313: /* always 20Mhz */ clock = 20000 * 1000; break; @@ -283,51 +169,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih) return clock; } -/* initialize PMU */ -void si_pmu_init(struct si_pub *sih) -{ - struct bcma_device *core; - - /* select chipc */ - core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); - - if (ai_get_pmurev(sih) == 1) - bcma_mask32(core, CHIPCREGOFFS(pmucontrol), - ~PCTL_NOILP_ON_WAIT); - else if (ai_get_pmurev(sih) >= 2) - bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT); -} - -/* initialize PMU resources */ -void si_pmu_res_init(struct si_pub *sih) -{ - struct bcma_device *core; - u32 min_mask = 0, max_mask = 0; - - /* select to chipc */ - core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); - - /* Determine min/max rsrc masks */ - si_pmu_res_masks(sih, &min_mask, &max_mask); - - /* It is required to program max_mask first and then min_mask */ - - /* Program max resource mask */ - - if (max_mask) - bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask); - - /* Program min resource mask */ - - if (min_mask) - bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask); - - /* Add some delay; allow resources to come up and settle. */ - mdelay(2); -} - u32 si_pmu_measure_alpclk(struct si_pub *sih) { + struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *core; u32 alp_khz; @@ -335,7 +179,7 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih) return 0; /* Remember original core before switch to chipc */ - core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); + core = sii->icbus->drv_cc.core; if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) { u32 ilp_ctr, alp_hz; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h index 3e39c5e0f9ff..f7cff873578b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h @@ -26,10 +26,7 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); extern u32 si_pmu_alp_clock(struct si_pub *sih); extern void si_pmu_pllupd(struct si_pub *sih); -extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid); extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); -extern void si_pmu_init(struct si_pub *sih); -extern void si_pmu_res_init(struct si_pub *sih); extern u32 si_pmu_measure_alpclk(struct si_pub *sih); #endif /* _BRCM_PMU_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index aa5d67f8d874..5855f4fd16dc 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h @@ -311,7 +311,7 @@ extern uint brcms_c_detach(struct brcms_c_info *wlc); extern int brcms_c_up(struct brcms_c_info *wlc); extern uint brcms_c_down(struct brcms_c_info *wlc); -extern bool brcms_c_chipmatch(u16 vendor, u16 device); +extern bool brcms_c_chipmatch(struct bcma_device *core); extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx); extern void brcms_c_reset(struct brcms_c_info *wlc); diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index b45ab34cdfdc..3e6405e06ac0 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c @@ -43,6 +43,8 @@ EXPORT_SYMBOL(brcmu_pkt_buf_get_skb); /* Free the driver packet. Free the tag if present */ void brcmu_pkt_buf_free_skb(struct sk_buff *skb) { + if (!skb) + return; WARN_ON(skb->next); if (skb->destructor) /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 333193f20e1c..bcc79b4e3267 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h @@ -37,5 +37,6 @@ #define BCM4329_CHIP_ID 0x4329 #define BCM4330_CHIP_ID 0x4330 #define BCM4331_CHIP_ID 0x4331 +#define BCM4334_CHIP_ID 0x4334 #endif /* _BRCM_HW_IDS_H_ */ diff --git a/drivers/net/wireless/brcm80211/include/soc.h b/drivers/net/wireless/brcm80211/include/soc.h index 4e9b7e4827ea..123cfa854a0d 100644 --- a/drivers/net/wireless/brcm80211/include/soc.h +++ b/drivers/net/wireless/brcm80211/include/soc.h @@ -19,68 +19,6 @@ #define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ -/* core codes */ -#define NODEV_CORE_ID 0x700 /* Invalid coreid */ -#define CC_CORE_ID 0x800 /* chipcommon core */ -#define ILINE20_CORE_ID 0x801 /* iline20 core */ -#define SRAM_CORE_ID 0x802 /* sram core */ -#define SDRAM_CORE_ID 0x803 /* sdram core */ -#define PCI_CORE_ID 0x804 /* pci core */ -#define MIPS_CORE_ID 0x805 /* mips core */ -#define ENET_CORE_ID 0x806 /* enet mac core */ -#define CODEC_CORE_ID 0x807 /* v90 codec core */ -#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ -#define ADSL_CORE_ID 0x809 /* ADSL core */ -#define ILINE100_CORE_ID 0x80a /* iline100 core */ -#define IPSEC_CORE_ID 0x80b /* ipsec core */ -#define UTOPIA_CORE_ID 0x80c /* utopia core */ -#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ -#define SOCRAM_CORE_ID 0x80e /* internal memory core */ -#define MEMC_CORE_ID 0x80f /* memc sdram core */ -#define OFDM_CORE_ID 0x810 /* OFDM phy core */ -#define EXTIF_CORE_ID 0x811 /* external interface core */ -#define D11_CORE_ID 0x812 /* 802.11 MAC core */ -#define APHY_CORE_ID 0x813 /* 802.11a phy core */ -#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ -#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ -#define MIPS33_CORE_ID 0x816 /* mips3302 core */ -#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ -#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ -#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ -#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ -#define SDIOH_CORE_ID 0x81b /* sdio host core */ -#define ROBO_CORE_ID 0x81c /* roboswitch core */ -#define ATA100_CORE_ID 0x81d /* parallel ATA core */ -#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ -#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ -#define PCIE_CORE_ID 0x820 /* pci express core */ -#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ -#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ -#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ -#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ -#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ -#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ -#define PMU_CORE_ID 0x827 /* PMU core */ -#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ -#define SDIOD_CORE_ID 0x829 /* SDIO device core */ -#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ -#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ -#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ -#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ -#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ -#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ -#define SC_CORE_ID 0x831 /* shared common core */ -#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ -#define SPIH_CORE_ID 0x833 /* SPI host core */ -#define I2S_CORE_ID 0x834 /* I2S core */ -#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ -#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ -#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ -#define DEF_AI_COMP 0xfff /* Default component, in ai chips it - * maps all unused address ranges - */ - /* Common core control flags */ #define SICF_BIST_EN 0x8000 #define SICF_PME_EN 0x4000 |