mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-30 15:48:52 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
57
drivers/net/wireless/brcm80211/brcmfmac/Makefile
Normal file
57
drivers/net/wireless/brcm80211/brcmfmac/Makefile
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#
|
||||
# Makefile fragment for Broadcom 802.11n Networking Device Driver
|
||||
#
|
||||
# Copyright (c) 2010 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.
|
||||
|
||||
ccflags-y += \
|
||||
-Idrivers/net/wireless/brcm80211/brcmfmac \
|
||||
-Idrivers/net/wireless/brcm80211/include
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
||||
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
|
||||
brcmfmac-objs += \
|
||||
wl_cfg80211.o \
|
||||
chip.o \
|
||||
fwil.o \
|
||||
fweh.o \
|
||||
fwsignal.o \
|
||||
p2p.o \
|
||||
proto.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o \
|
||||
firmware.o \
|
||||
feature.o \
|
||||
btcoex.o \
|
||||
vendor.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
|
||||
bcdc.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \
|
||||
commonring.o \
|
||||
flowring.o \
|
||||
msgbuf.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
|
||||
dhd_sdio.o \
|
||||
bcmsdh.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
|
||||
usb.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \
|
||||
pcie.o
|
||||
brcmfmac-$(CONFIG_BRCMDBG) += \
|
||||
dhd_dbg.o
|
||||
brcmfmac-$(CONFIG_BRCM_TRACING) += \
|
||||
tracepoint.o
|
||||
brcmfmac-$(CONFIG_OF) += \
|
||||
of.o
|
||||
395
drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
Normal file
395
drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Communicates with the dongle by using dcmd codes.
|
||||
* For certain dcmd codes, the dongle interprets string data from the host.
|
||||
******************************************************************************/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "fwsignal.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "tracepoint.h"
|
||||
#include "proto.h"
|
||||
#include "bcdc.h"
|
||||
|
||||
struct brcmf_proto_bcdc_dcmd {
|
||||
__le32 cmd; /* dongle command value */
|
||||
__le32 len; /* lower 16: output buflen;
|
||||
* upper 16: input buflen (excludes header) */
|
||||
__le32 flags; /* flag defns given below */
|
||||
__le32 status; /* status code returned from the device */
|
||||
};
|
||||
|
||||
/* BCDC flag definitions */
|
||||
#define BCDC_DCMD_ERROR 0x01 /* 1=cmd failed */
|
||||
#define BCDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */
|
||||
#define BCDC_DCMD_IF_MASK 0xF000 /* I/F index */
|
||||
#define BCDC_DCMD_IF_SHIFT 12
|
||||
#define BCDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */
|
||||
#define BCDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */
|
||||
#define BCDC_DCMD_ID(flags) \
|
||||
(((flags) & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT)
|
||||
|
||||
/*
|
||||
* BCDC header - Broadcom specific extension of CDC.
|
||||
* Used on data packets to convey priority across USB.
|
||||
*/
|
||||
#define BCDC_HEADER_LEN 4
|
||||
#define BCDC_PROTO_VER 2 /* Protocol version */
|
||||
#define BCDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
|
||||
#define BCDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
|
||||
#define BCDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */
|
||||
#define BCDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
|
||||
#define BCDC_PRIORITY_MASK 0x7
|
||||
#define BCDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */
|
||||
#define BCDC_FLAG2_IF_SHIFT 0
|
||||
|
||||
#define BCDC_GET_IF_IDX(hdr) \
|
||||
((int)((((hdr)->flags2) & BCDC_FLAG2_IF_MASK) >> BCDC_FLAG2_IF_SHIFT))
|
||||
#define BCDC_SET_IF_IDX(hdr, idx) \
|
||||
((hdr)->flags2 = (((hdr)->flags2 & ~BCDC_FLAG2_IF_MASK) | \
|
||||
((idx) << BCDC_FLAG2_IF_SHIFT)))
|
||||
|
||||
/**
|
||||
* struct brcmf_proto_bcdc_header - BCDC header format
|
||||
*
|
||||
* @flags: flags contain protocol and checksum info.
|
||||
* @priority: 802.1d priority and USB flow control info (bit 4:7).
|
||||
* @flags2: additional flags containing dongle interface index.
|
||||
* @data_offset: start of packet data. header is following by firmware signals.
|
||||
*/
|
||||
struct brcmf_proto_bcdc_header {
|
||||
u8 flags;
|
||||
u8 priority;
|
||||
u8 flags2;
|
||||
u8 data_offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* maximum length of firmware signal data between
|
||||
* the BCDC header and packet data in the tx path.
|
||||
*/
|
||||
#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12
|
||||
|
||||
#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
|
||||
#define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE
|
||||
* (amount of header tha might be added)
|
||||
* plus any space that might be needed
|
||||
* for bus alignment padding.
|
||||
*/
|
||||
struct brcmf_bcdc {
|
||||
u16 reqid;
|
||||
u8 bus_header[BUS_HEADER_LEN];
|
||||
struct brcmf_proto_bcdc_dcmd msg;
|
||||
unsigned char buf[BRCMF_DCMD_MAXLEN];
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
|
||||
uint len, bool set)
|
||||
{
|
||||
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
|
||||
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
|
||||
u32 flags;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter\n");
|
||||
|
||||
memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
|
||||
|
||||
msg->cmd = cpu_to_le32(cmd);
|
||||
msg->len = cpu_to_le32(len);
|
||||
flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
|
||||
if (set)
|
||||
flags |= BCDC_DCMD_SET;
|
||||
flags = (flags & ~BCDC_DCMD_IF_MASK) |
|
||||
(ifidx << BCDC_DCMD_IF_SHIFT);
|
||||
msg->flags = cpu_to_le32(flags);
|
||||
|
||||
if (buf)
|
||||
memcpy(bcdc->buf, buf, len);
|
||||
|
||||
len += sizeof(*msg);
|
||||
if (len > BRCMF_TX_IOCTL_MAX_MSG_SIZE)
|
||||
len = BRCMF_TX_IOCTL_MAX_MSG_SIZE;
|
||||
|
||||
/* Send request */
|
||||
return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len);
|
||||
}
|
||||
|
||||
static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
|
||||
{
|
||||
int ret;
|
||||
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter\n");
|
||||
len += sizeof(struct brcmf_proto_bcdc_dcmd);
|
||||
do {
|
||||
ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg,
|
||||
len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
} while (BCDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len)
|
||||
{
|
||||
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
|
||||
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
|
||||
void *info;
|
||||
int ret = 0, retries = 0;
|
||||
u32 id, flags;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
|
||||
|
||||
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
|
||||
if (ret < 0) {
|
||||
brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
|
||||
ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
retry:
|
||||
/* wait for interrupt and get first fragment */
|
||||
ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
flags = le32_to_cpu(msg->flags);
|
||||
id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
|
||||
|
||||
if ((id < bcdc->reqid) && (++retries < RETRIES))
|
||||
goto retry;
|
||||
if (id != bcdc->reqid) {
|
||||
brcmf_err("%s: unexpected request id %d (expected %d)\n",
|
||||
brcmf_ifname(drvr, ifidx), id, bcdc->reqid);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check info buffer */
|
||||
info = (void *)&msg[1];
|
||||
|
||||
/* Copy info buffer */
|
||||
if (buf) {
|
||||
if (ret < (int)len)
|
||||
len = ret;
|
||||
memcpy(buf, info, len);
|
||||
}
|
||||
|
||||
/* Check the ERROR flag */
|
||||
if (flags & BCDC_DCMD_ERROR)
|
||||
ret = le32_to_cpu(msg->status);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len)
|
||||
{
|
||||
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
|
||||
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
|
||||
int ret = 0;
|
||||
u32 flags, id;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
|
||||
|
||||
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
flags = le32_to_cpu(msg->flags);
|
||||
id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
|
||||
|
||||
if (id != bcdc->reqid) {
|
||||
brcmf_err("%s: unexpected request id %d (expected %d)\n",
|
||||
brcmf_ifname(drvr, ifidx), id, bcdc->reqid);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check the ERROR flag */
|
||||
if (flags & BCDC_DCMD_ERROR)
|
||||
ret = le32_to_cpu(msg->status);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
|
||||
struct sk_buff *pktbuf)
|
||||
{
|
||||
struct brcmf_proto_bcdc_header *h;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter\n");
|
||||
|
||||
/* Push BDC header used to convey priority for buses that don't */
|
||||
skb_push(pktbuf, BCDC_HEADER_LEN);
|
||||
|
||||
h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
|
||||
|
||||
h->flags = (BCDC_PROTO_VER << BCDC_FLAG_VER_SHIFT);
|
||||
if (pktbuf->ip_summed == CHECKSUM_PARTIAL)
|
||||
h->flags |= BCDC_FLAG_SUM_NEEDED;
|
||||
|
||||
h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK);
|
||||
h->flags2 = 0;
|
||||
h->data_offset = offset;
|
||||
BCDC_SET_IF_IDX(h, ifidx);
|
||||
trace_brcmf_bcdchdr(pktbuf->data);
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
|
||||
struct sk_buff *pktbuf)
|
||||
{
|
||||
struct brcmf_proto_bcdc_header *h;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter\n");
|
||||
|
||||
/* Pop BCDC header used to convey priority for buses that don't */
|
||||
if (pktbuf->len <= BCDC_HEADER_LEN) {
|
||||
brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
|
||||
pktbuf->len, BCDC_HEADER_LEN);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
trace_brcmf_bcdchdr(pktbuf->data);
|
||||
h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
|
||||
|
||||
*ifidx = BCDC_GET_IF_IDX(h);
|
||||
if (*ifidx >= BRCMF_MAX_IFS) {
|
||||
brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
|
||||
return -EBADE;
|
||||
}
|
||||
/* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
* events this is easy because it contains the bssidx which maps
|
||||
* 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
* bssidx 1 is used for p2p0 and no data can be received or
|
||||
* transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
*/
|
||||
if (*ifidx)
|
||||
(*ifidx)++;
|
||||
|
||||
if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
|
||||
BCDC_PROTO_VER) {
|
||||
brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
|
||||
brcmf_ifname(drvr, *ifidx), h->flags);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
if (h->flags & BCDC_FLAG_SUM_GOOD) {
|
||||
brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
|
||||
brcmf_ifname(drvr, *ifidx), h->flags);
|
||||
pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
pktbuf->priority = h->priority & BCDC_PRIORITY_MASK;
|
||||
|
||||
skb_pull(pktbuf, BCDC_HEADER_LEN);
|
||||
if (do_fws)
|
||||
brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
|
||||
else
|
||||
skb_pull(pktbuf, h->data_offset << 2);
|
||||
|
||||
if (pktbuf->len == 0)
|
||||
return -ENODATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
|
||||
struct sk_buff *pktbuf)
|
||||
{
|
||||
brcmf_proto_bcdc_hdrpush(drvr, ifidx, offset, pktbuf);
|
||||
return brcmf_bus_txdata(drvr->bus_if, pktbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_proto_bcdc_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
|
||||
enum proto_addr_mode addr_mode)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_proto_bcdc_delete_peer(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 peer[ETH_ALEN])
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 peer[ETH_ALEN])
|
||||
{
|
||||
}
|
||||
|
||||
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_bcdc *bcdc;
|
||||
|
||||
bcdc = kzalloc(sizeof(*bcdc), GFP_ATOMIC);
|
||||
if (!bcdc)
|
||||
goto fail;
|
||||
|
||||
/* ensure that the msg buf directly follows the cdc msg struct */
|
||||
if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) {
|
||||
brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
|
||||
drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
|
||||
drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
|
||||
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
|
||||
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
|
||||
drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
|
||||
drvr->proto->pd = bcdc;
|
||||
|
||||
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
|
||||
drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
|
||||
sizeof(struct brcmf_proto_bcdc_dcmd);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kfree(bcdc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
kfree(drvr->proto->pd);
|
||||
drvr->proto->pd = NULL;
|
||||
}
|
||||
27
drivers/net/wireless/brcm80211/brcmfmac/bcdc.h
Normal file
27
drivers/net/wireless/brcm80211/brcmfmac/bcdc.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_BCDC_H
|
||||
#define BRCMFMAC_BCDC_H
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_PROTO_BCDC
|
||||
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
|
||||
#else
|
||||
static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
|
||||
static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {}
|
||||
#endif
|
||||
|
||||
#endif /* BRCMFMAC_BCDC_H */
|
||||
1239
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
Normal file
1239
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
Normal file
File diff suppressed because it is too large
Load diff
497
drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
Normal file
497
drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include <defs.h>
|
||||
#include <dhd.h>
|
||||
#include <dhd_dbg.h>
|
||||
#include "fwil.h"
|
||||
#include "fwil_types.h"
|
||||
#include "btcoex.h"
|
||||
#include "p2p.h"
|
||||
#include "wl_cfg80211.h"
|
||||
|
||||
/* T1 start SCO/eSCO priority suppression */
|
||||
#define BRCMF_BTCOEX_OPPR_WIN_TIME 2000
|
||||
|
||||
/* BT registers values during DHCP */
|
||||
#define BRCMF_BT_DHCP_REG50 0x8022
|
||||
#define BRCMF_BT_DHCP_REG51 0
|
||||
#define BRCMF_BT_DHCP_REG64 0
|
||||
#define BRCMF_BT_DHCP_REG65 0
|
||||
#define BRCMF_BT_DHCP_REG71 0
|
||||
#define BRCMF_BT_DHCP_REG66 0x2710
|
||||
#define BRCMF_BT_DHCP_REG41 0x33
|
||||
#define BRCMF_BT_DHCP_REG68 0x190
|
||||
|
||||
/* number of samples for SCO detection */
|
||||
#define BRCMF_BT_SCO_SAMPLES 12
|
||||
|
||||
/**
|
||||
* enum brcmf_btcoex_state - BT coex DHCP state machine states
|
||||
* @BRCMF_BT_DHCP_IDLE: DCHP is idle
|
||||
* @BRCMF_BT_DHCP_START: DHCP started, wait before
|
||||
* boosting wifi priority
|
||||
* @BRCMF_BT_DHCP_OPPR_WIN: graceful DHCP opportunity ended,
|
||||
* boost wifi priority
|
||||
* @BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: wifi priority boost end,
|
||||
* restore defaults
|
||||
*/
|
||||
enum brcmf_btcoex_state {
|
||||
BRCMF_BT_DHCP_IDLE,
|
||||
BRCMF_BT_DHCP_START,
|
||||
BRCMF_BT_DHCP_OPPR_WIN,
|
||||
BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_btcoex_info - BT coex related information
|
||||
* @vif: interface for which request was done.
|
||||
* @timer: timer for DHCP state machine
|
||||
* @timeout: configured timeout.
|
||||
* @timer_on: DHCP timer active
|
||||
* @dhcp_done: DHCP finished before T1/T2 timer expiration
|
||||
* @bt_state: DHCP state machine state
|
||||
* @work: DHCP state machine work
|
||||
* @cfg: driver private data for cfg80211 interface
|
||||
* @reg66: saved value of btc_params 66
|
||||
* @reg41: saved value of btc_params 41
|
||||
* @reg68: saved value of btc_params 68
|
||||
* @saved_regs_part1: flag indicating regs 66,41,68
|
||||
* have been saved
|
||||
* @reg51: saved value of btc_params 51
|
||||
* @reg64: saved value of btc_params 64
|
||||
* @reg65: saved value of btc_params 65
|
||||
* @reg71: saved value of btc_params 71
|
||||
* @saved_regs_part1: flag indicating regs 50,51,64,65,71
|
||||
* have been saved
|
||||
*/
|
||||
struct brcmf_btcoex_info {
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct timer_list timer;
|
||||
u16 timeout;
|
||||
bool timer_on;
|
||||
bool dhcp_done;
|
||||
enum brcmf_btcoex_state bt_state;
|
||||
struct work_struct work;
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
u32 reg66;
|
||||
u32 reg41;
|
||||
u32 reg68;
|
||||
bool saved_regs_part1;
|
||||
u32 reg50;
|
||||
u32 reg51;
|
||||
u32 reg64;
|
||||
u32 reg65;
|
||||
u32 reg71;
|
||||
bool saved_regs_part2;
|
||||
};
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_params_write() - write btc_params firmware variable
|
||||
* @ifp: interface
|
||||
* @addr: btc_params register number
|
||||
* @data: data to write
|
||||
*/
|
||||
static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data)
|
||||
{
|
||||
struct {
|
||||
__le32 addr;
|
||||
__le32 data;
|
||||
} reg_write;
|
||||
|
||||
reg_write.addr = cpu_to_le32(addr);
|
||||
reg_write.data = cpu_to_le32(data);
|
||||
return brcmf_fil_iovar_data_set(ifp, "btc_params",
|
||||
®_write, sizeof(reg_write));
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_params_read() - read btc_params firmware variable
|
||||
* @ifp: interface
|
||||
* @addr: btc_params register number
|
||||
* @data: read data
|
||||
*/
|
||||
static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data)
|
||||
{
|
||||
*data = addr;
|
||||
|
||||
return brcmf_fil_iovar_int_get(ifp, "btc_params", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_boost_wifi() - control BT SCO/eSCO parameters
|
||||
* @btci: BT coex info
|
||||
* @trump_sco:
|
||||
* true - set SCO/eSCO parameters for compatibility
|
||||
* during DHCP window
|
||||
* false - restore saved parameter values
|
||||
*
|
||||
* Enhanced BT COEX settings for eSCO compatibility during DHCP window
|
||||
*/
|
||||
static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
|
||||
bool trump_sco)
|
||||
{
|
||||
struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
|
||||
|
||||
if (trump_sco && !btci->saved_regs_part2) {
|
||||
/* this should reduce eSCO agressive
|
||||
* retransmit w/o breaking it
|
||||
*/
|
||||
|
||||
/* save current */
|
||||
brcmf_dbg(INFO, "new SCO/eSCO coex algo {save & override}\n");
|
||||
brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
|
||||
brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
|
||||
brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
|
||||
brcmf_btcoex_params_read(ifp, 65, &btci->reg65);
|
||||
brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
|
||||
|
||||
btci->saved_regs_part2 = true;
|
||||
brcmf_dbg(INFO,
|
||||
"saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
btci->reg50, btci->reg51, btci->reg64,
|
||||
btci->reg65, btci->reg71);
|
||||
|
||||
/* pacify the eSco */
|
||||
brcmf_btcoex_params_write(ifp, 50, BRCMF_BT_DHCP_REG50);
|
||||
brcmf_btcoex_params_write(ifp, 51, BRCMF_BT_DHCP_REG51);
|
||||
brcmf_btcoex_params_write(ifp, 64, BRCMF_BT_DHCP_REG64);
|
||||
brcmf_btcoex_params_write(ifp, 65, BRCMF_BT_DHCP_REG65);
|
||||
brcmf_btcoex_params_write(ifp, 71, BRCMF_BT_DHCP_REG71);
|
||||
|
||||
} else if (btci->saved_regs_part2) {
|
||||
/* restore previously saved bt params */
|
||||
brcmf_dbg(INFO, "Do new SCO/eSCO coex algo {restore}\n");
|
||||
brcmf_btcoex_params_write(ifp, 50, btci->reg50);
|
||||
brcmf_btcoex_params_write(ifp, 51, btci->reg51);
|
||||
brcmf_btcoex_params_write(ifp, 64, btci->reg64);
|
||||
brcmf_btcoex_params_write(ifp, 65, btci->reg65);
|
||||
brcmf_btcoex_params_write(ifp, 71, btci->reg71);
|
||||
|
||||
brcmf_dbg(INFO,
|
||||
"restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
btci->reg50, btci->reg51, btci->reg64,
|
||||
btci->reg65, btci->reg71);
|
||||
|
||||
btci->saved_regs_part2 = false;
|
||||
} else {
|
||||
brcmf_dbg(INFO, "attempted to restore not saved BTCOEX params\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active
|
||||
* @ifp: interface
|
||||
*
|
||||
* return: true if SCO/eSCO session is active
|
||||
*/
|
||||
static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp)
|
||||
{
|
||||
int ioc_res = 0;
|
||||
bool res = false;
|
||||
int sco_id_cnt = 0;
|
||||
u32 param27;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) {
|
||||
ioc_res = brcmf_btcoex_params_read(ifp, 27, ¶m27);
|
||||
|
||||
if (ioc_res < 0) {
|
||||
brcmf_err("ioc read btc params error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "sample[%d], btc_params 27:%x\n", i, param27);
|
||||
|
||||
if ((param27 & 0x6) == 2) { /* count both sco & esco */
|
||||
sco_id_cnt++;
|
||||
}
|
||||
|
||||
if (sco_id_cnt > 2) {
|
||||
brcmf_dbg(INFO,
|
||||
"sco/esco detected, pkt id_cnt:%d samples:%d\n",
|
||||
sco_id_cnt, i);
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
brcmf_dbg(TRACE, "exit: result=%d\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* btcmf_btcoex_save_part1() - save first step parameters.
|
||||
*/
|
||||
static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
struct brcmf_if *ifp = btci->vif->ifp;
|
||||
|
||||
if (!btci->saved_regs_part1) {
|
||||
/* Retrieve and save original reg value */
|
||||
brcmf_btcoex_params_read(ifp, 66, &btci->reg66);
|
||||
brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
|
||||
brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
|
||||
btci->saved_regs_part1 = true;
|
||||
brcmf_dbg(INFO,
|
||||
"saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
|
||||
btci->reg66, btci->reg41,
|
||||
btci->reg68);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_restore_part1() - restore first step parameters.
|
||||
*/
|
||||
static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
if (btci->saved_regs_part1) {
|
||||
btci->saved_regs_part1 = false;
|
||||
ifp = btci->vif->ifp;
|
||||
brcmf_btcoex_params_write(ifp, 66, btci->reg66);
|
||||
brcmf_btcoex_params_write(ifp, 41, btci->reg41);
|
||||
brcmf_btcoex_params_write(ifp, 68, btci->reg68);
|
||||
brcmf_dbg(INFO,
|
||||
"restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
|
||||
btci->reg66, btci->reg41,
|
||||
btci->reg68);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_timerfunc() - BT coex timer callback
|
||||
*/
|
||||
static void brcmf_btcoex_timerfunc(ulong data)
|
||||
{
|
||||
struct brcmf_btcoex_info *bt_local = (struct brcmf_btcoex_info *)data;
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
bt_local->timer_on = false;
|
||||
schedule_work(&bt_local->work);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_handler() - BT coex state machine work handler
|
||||
* @work: work
|
||||
*/
|
||||
static void brcmf_btcoex_handler(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_btcoex_info *btci;
|
||||
btci = container_of(work, struct brcmf_btcoex_info, work);
|
||||
if (btci->timer_on) {
|
||||
btci->timer_on = false;
|
||||
del_timer_sync(&btci->timer);
|
||||
}
|
||||
|
||||
switch (btci->bt_state) {
|
||||
case BRCMF_BT_DHCP_START:
|
||||
/* DHCP started provide OPPORTUNITY window
|
||||
to get DHCP address
|
||||
*/
|
||||
brcmf_dbg(INFO, "DHCP started\n");
|
||||
btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
|
||||
if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
|
||||
mod_timer(&btci->timer, btci->timer.expires);
|
||||
} else {
|
||||
btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME;
|
||||
mod_timer(&btci->timer,
|
||||
jiffies +
|
||||
msecs_to_jiffies(BRCMF_BTCOEX_OPPR_WIN_TIME));
|
||||
}
|
||||
btci->timer_on = true;
|
||||
break;
|
||||
|
||||
case BRCMF_BT_DHCP_OPPR_WIN:
|
||||
if (btci->dhcp_done) {
|
||||
brcmf_dbg(INFO, "DHCP done before T1 expiration\n");
|
||||
goto idle;
|
||||
}
|
||||
|
||||
/* DHCP is not over yet, start lowering BT priority */
|
||||
brcmf_dbg(INFO, "DHCP T1:%d expired\n",
|
||||
BRCMF_BTCOEX_OPPR_WIN_TIME);
|
||||
brcmf_btcoex_boost_wifi(btci, true);
|
||||
|
||||
btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT;
|
||||
mod_timer(&btci->timer,
|
||||
jiffies + msecs_to_jiffies(btci->timeout));
|
||||
btci->timer_on = true;
|
||||
break;
|
||||
|
||||
case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
|
||||
if (btci->dhcp_done)
|
||||
brcmf_dbg(INFO, "DHCP done before T2 expiration\n");
|
||||
else
|
||||
brcmf_dbg(INFO, "DHCP T2:%d expired\n",
|
||||
BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
|
||||
|
||||
goto idle;
|
||||
|
||||
default:
|
||||
brcmf_err("invalid state=%d !!!\n", btci->bt_state);
|
||||
goto idle;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
idle:
|
||||
btci->bt_state = BRCMF_BT_DHCP_IDLE;
|
||||
btci->timer_on = false;
|
||||
brcmf_btcoex_boost_wifi(btci, false);
|
||||
cfg80211_crit_proto_stopped(&btci->vif->wdev, GFP_KERNEL);
|
||||
brcmf_btcoex_restore_part1(btci);
|
||||
btci->vif = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_attach() - initialize BT coex data
|
||||
* @cfg: driver private cfg80211 data
|
||||
*
|
||||
* return: 0 on success
|
||||
*/
|
||||
int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_btcoex_info *btci = NULL;
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
btci = kmalloc(sizeof(struct brcmf_btcoex_info), GFP_KERNEL);
|
||||
if (!btci)
|
||||
return -ENOMEM;
|
||||
|
||||
btci->bt_state = BRCMF_BT_DHCP_IDLE;
|
||||
|
||||
/* Set up timer for BT */
|
||||
btci->timer_on = false;
|
||||
btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME;
|
||||
init_timer(&btci->timer);
|
||||
btci->timer.data = (ulong)btci;
|
||||
btci->timer.function = brcmf_btcoex_timerfunc;
|
||||
btci->cfg = cfg;
|
||||
btci->saved_regs_part1 = false;
|
||||
btci->saved_regs_part2 = false;
|
||||
|
||||
INIT_WORK(&btci->work, brcmf_btcoex_handler);
|
||||
|
||||
cfg->btcoex = btci;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_detach - clean BT coex data
|
||||
* @cfg: driver private cfg80211 data
|
||||
*/
|
||||
void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
if (!cfg->btcoex)
|
||||
return;
|
||||
|
||||
if (cfg->btcoex->timer_on) {
|
||||
cfg->btcoex->timer_on = false;
|
||||
del_timer_sync(&cfg->btcoex->timer);
|
||||
}
|
||||
|
||||
cancel_work_sync(&cfg->btcoex->work);
|
||||
|
||||
brcmf_btcoex_boost_wifi(cfg->btcoex, false);
|
||||
brcmf_btcoex_restore_part1(cfg->btcoex);
|
||||
|
||||
kfree(cfg->btcoex);
|
||||
cfg->btcoex = NULL;
|
||||
}
|
||||
|
||||
static void brcmf_btcoex_dhcp_start(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
struct brcmf_if *ifp = btci->vif->ifp;
|
||||
|
||||
btcmf_btcoex_save_part1(btci);
|
||||
/* set new regs values */
|
||||
brcmf_btcoex_params_write(ifp, 66, BRCMF_BT_DHCP_REG66);
|
||||
brcmf_btcoex_params_write(ifp, 41, BRCMF_BT_DHCP_REG41);
|
||||
brcmf_btcoex_params_write(ifp, 68, BRCMF_BT_DHCP_REG68);
|
||||
btci->dhcp_done = false;
|
||||
btci->bt_state = BRCMF_BT_DHCP_START;
|
||||
schedule_work(&btci->work);
|
||||
brcmf_dbg(TRACE, "enable BT DHCP Timer\n");
|
||||
}
|
||||
|
||||
static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
/* Stop any bt timer because DHCP session is done */
|
||||
btci->dhcp_done = true;
|
||||
if (btci->timer_on) {
|
||||
brcmf_dbg(INFO, "disable BT DHCP Timer\n");
|
||||
btci->timer_on = false;
|
||||
del_timer_sync(&btci->timer);
|
||||
|
||||
/* schedule worker if transition to IDLE is needed */
|
||||
if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
|
||||
brcmf_dbg(INFO, "bt_state:%d\n",
|
||||
btci->bt_state);
|
||||
schedule_work(&btci->work);
|
||||
}
|
||||
} else {
|
||||
/* Restore original values */
|
||||
brcmf_btcoex_restore_part1(btci);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_set_mode - set BT coex mode
|
||||
* @cfg: driver private cfg80211 data
|
||||
* @mode: Wifi-Bluetooth coexistence mode
|
||||
*
|
||||
* return: 0 on success
|
||||
*/
|
||||
int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
|
||||
enum brcmf_btcoex_mode mode, u16 duration)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
|
||||
struct brcmf_btcoex_info *btci = cfg->btcoex;
|
||||
struct brcmf_if *ifp = cfg->pub->iflist[0];
|
||||
|
||||
switch (mode) {
|
||||
case BRCMF_BTCOEX_DISABLED:
|
||||
brcmf_dbg(INFO, "DHCP session starts\n");
|
||||
if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
|
||||
return -EBUSY;
|
||||
/* Start BT timer only for SCO connection */
|
||||
if (brcmf_btcoex_is_sco_active(ifp)) {
|
||||
btci->timeout = duration;
|
||||
btci->vif = vif;
|
||||
brcmf_btcoex_dhcp_start(btci);
|
||||
}
|
||||
break;
|
||||
|
||||
case BRCMF_BTCOEX_ENABLED:
|
||||
brcmf_dbg(INFO, "DHCP session ends\n");
|
||||
if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
|
||||
vif == btci->vif) {
|
||||
brcmf_btcoex_dhcp_end(btci);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
brcmf_dbg(INFO, "Unknown mode, ignored\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
29
drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
Normal file
29
drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#ifndef WL_BTCOEX_H_
|
||||
#define WL_BTCOEX_H_
|
||||
|
||||
enum brcmf_btcoex_mode {
|
||||
BRCMF_BTCOEX_DISABLED,
|
||||
BRCMF_BTCOEX_ENABLED
|
||||
};
|
||||
|
||||
int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg);
|
||||
int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
|
||||
enum brcmf_btcoex_mode mode, u16 duration);
|
||||
|
||||
#endif /* WL_BTCOEX_H_ */
|
||||
1043
drivers/net/wireless/brcm80211/brcmfmac/chip.c
Normal file
1043
drivers/net/wireless/brcm80211/brcmfmac/chip.c
Normal file
File diff suppressed because it is too large
Load diff
91
drivers/net/wireless/brcm80211/brcmfmac/chip.h
Normal file
91
drivers/net/wireless/brcm80211/brcmfmac/chip.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifndef BRCMF_CHIP_H
|
||||
#define BRCMF_CHIP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define CORE_CC_REG(base, field) \
|
||||
(base + offsetof(struct chipcregs, field))
|
||||
|
||||
/**
|
||||
* struct brcmf_chip - chip level information.
|
||||
*
|
||||
* @chip: chip identifier.
|
||||
* @chiprev: chip revision.
|
||||
* @cc_caps: chipcommon core capabilities.
|
||||
* @pmucaps: PMU capabilities.
|
||||
* @pmurev: PMU revision.
|
||||
* @rambase: RAM base address (only applicable for ARM CR4 chips).
|
||||
* @ramsize: amount of RAM on chip.
|
||||
* @name: string representation of the chip identifier.
|
||||
*/
|
||||
struct brcmf_chip {
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
u32 cc_caps;
|
||||
u32 pmucaps;
|
||||
u32 pmurev;
|
||||
u32 rambase;
|
||||
u32 ramsize;
|
||||
char name[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_core - core related information.
|
||||
*
|
||||
* @id: core identifier.
|
||||
* @rev: core revision.
|
||||
* @base: base address of core register space.
|
||||
*/
|
||||
struct brcmf_core {
|
||||
u16 id;
|
||||
u16 rev;
|
||||
u32 base;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_buscore_ops - buscore specific callbacks.
|
||||
*
|
||||
* @read32: read 32-bit value over bus.
|
||||
* @write32: write 32-bit value over bus.
|
||||
* @prepare: prepare bus for core configuration.
|
||||
* @setup: bus-specific core setup.
|
||||
* @exit_dl: exit download state.
|
||||
* The callback should use the provided @rstvec when non-zero.
|
||||
*/
|
||||
struct brcmf_buscore_ops {
|
||||
u32 (*read32)(void *ctx, u32 addr);
|
||||
void (*write32)(void *ctx, u32 addr, u32 value);
|
||||
int (*prepare)(void *ctx);
|
||||
int (*setup)(void *ctx, struct brcmf_chip *chip);
|
||||
void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
|
||||
};
|
||||
|
||||
struct brcmf_chip *brcmf_chip_attach(void *ctx,
|
||||
const struct brcmf_buscore_ops *ops);
|
||||
void brcmf_chip_detach(struct brcmf_chip *chip);
|
||||
struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
|
||||
struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
|
||||
bool brcmf_chip_iscoreup(struct brcmf_core *core);
|
||||
void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
|
||||
void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
|
||||
u32 postreset);
|
||||
void brcmf_chip_enter_download(struct brcmf_chip *ci);
|
||||
bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec);
|
||||
bool brcmf_chip_sr_capable(struct brcmf_chip *pub);
|
||||
|
||||
#endif /* BRCMF_AXIDMP_H */
|
||||
273
drivers/net/wireless/brcm80211/brcmfmac/commonring.c
Normal file
273
drivers/net/wireless/brcm80211/brcmfmac/commonring.c
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
/* Copyright (c) 2014 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/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
||||
#include "dhd.h"
|
||||
#include "commonring.h"
|
||||
|
||||
|
||||
/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
* be put in util. Note, this is not real flushing. It is virtual non
|
||||
* cached memory. Only write buffers should have to be drained. Though
|
||||
* this may be different depending on platform......
|
||||
* SEE ALSO msgbuf.c
|
||||
*/
|
||||
#define brcmf_dma_flush(addr, len)
|
||||
#define brcmf_dma_invalidate_cache(addr, len)
|
||||
|
||||
|
||||
void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
|
||||
int (*cr_ring_bell)(void *ctx),
|
||||
int (*cr_update_rptr)(void *ctx),
|
||||
int (*cr_update_wptr)(void *ctx),
|
||||
int (*cr_write_rptr)(void *ctx),
|
||||
int (*cr_write_wptr)(void *ctx), void *ctx)
|
||||
{
|
||||
commonring->cr_ring_bell = cr_ring_bell;
|
||||
commonring->cr_update_rptr = cr_update_rptr;
|
||||
commonring->cr_update_wptr = cr_update_wptr;
|
||||
commonring->cr_write_rptr = cr_write_rptr;
|
||||
commonring->cr_write_wptr = cr_write_wptr;
|
||||
commonring->cr_ctx = ctx;
|
||||
}
|
||||
|
||||
|
||||
void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
|
||||
u16 item_len, void *buf_addr)
|
||||
{
|
||||
commonring->depth = depth;
|
||||
commonring->item_len = item_len;
|
||||
commonring->buf_addr = buf_addr;
|
||||
if (!commonring->inited) {
|
||||
spin_lock_init(&commonring->lock);
|
||||
commonring->inited = true;
|
||||
}
|
||||
commonring->r_ptr = 0;
|
||||
if (commonring->cr_write_rptr)
|
||||
commonring->cr_write_rptr(commonring->cr_ctx);
|
||||
commonring->w_ptr = 0;
|
||||
if (commonring->cr_write_wptr)
|
||||
commonring->cr_write_wptr(commonring->cr_ctx);
|
||||
commonring->f_ptr = 0;
|
||||
}
|
||||
|
||||
|
||||
void brcmf_commonring_lock(struct brcmf_commonring *commonring)
|
||||
__acquires(&commonring->lock)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&commonring->lock, flags);
|
||||
commonring->flags = flags;
|
||||
}
|
||||
|
||||
|
||||
void brcmf_commonring_unlock(struct brcmf_commonring *commonring)
|
||||
__releases(&commonring->lock)
|
||||
{
|
||||
spin_unlock_irqrestore(&commonring->lock, commonring->flags);
|
||||
}
|
||||
|
||||
|
||||
bool brcmf_commonring_write_available(struct brcmf_commonring *commonring)
|
||||
{
|
||||
u16 available;
|
||||
bool retry = true;
|
||||
|
||||
again:
|
||||
if (commonring->r_ptr <= commonring->w_ptr)
|
||||
available = commonring->depth - commonring->w_ptr +
|
||||
commonring->r_ptr;
|
||||
else
|
||||
available = commonring->r_ptr - commonring->w_ptr;
|
||||
|
||||
if (available > 1) {
|
||||
if (!commonring->was_full)
|
||||
return true;
|
||||
if (available > commonring->depth / 8) {
|
||||
commonring->was_full = false;
|
||||
return true;
|
||||
}
|
||||
if (retry) {
|
||||
if (commonring->cr_update_rptr)
|
||||
commonring->cr_update_rptr(commonring->cr_ctx);
|
||||
retry = false;
|
||||
goto again;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (retry) {
|
||||
if (commonring->cr_update_rptr)
|
||||
commonring->cr_update_rptr(commonring->cr_ctx);
|
||||
retry = false;
|
||||
goto again;
|
||||
}
|
||||
|
||||
commonring->was_full = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring)
|
||||
{
|
||||
void *ret_ptr;
|
||||
u16 available;
|
||||
bool retry = true;
|
||||
|
||||
again:
|
||||
if (commonring->r_ptr <= commonring->w_ptr)
|
||||
available = commonring->depth - commonring->w_ptr +
|
||||
commonring->r_ptr;
|
||||
else
|
||||
available = commonring->r_ptr - commonring->w_ptr;
|
||||
|
||||
if (available > 1) {
|
||||
ret_ptr = commonring->buf_addr +
|
||||
(commonring->w_ptr * commonring->item_len);
|
||||
commonring->w_ptr++;
|
||||
if (commonring->w_ptr == commonring->depth)
|
||||
commonring->w_ptr = 0;
|
||||
return ret_ptr;
|
||||
}
|
||||
|
||||
if (retry) {
|
||||
if (commonring->cr_update_rptr)
|
||||
commonring->cr_update_rptr(commonring->cr_ctx);
|
||||
retry = false;
|
||||
goto again;
|
||||
}
|
||||
|
||||
commonring->was_full = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
|
||||
u16 n_items, u16 *alloced)
|
||||
{
|
||||
void *ret_ptr;
|
||||
u16 available;
|
||||
bool retry = true;
|
||||
|
||||
again:
|
||||
if (commonring->r_ptr <= commonring->w_ptr)
|
||||
available = commonring->depth - commonring->w_ptr +
|
||||
commonring->r_ptr;
|
||||
else
|
||||
available = commonring->r_ptr - commonring->w_ptr;
|
||||
|
||||
if (available > 1) {
|
||||
ret_ptr = commonring->buf_addr +
|
||||
(commonring->w_ptr * commonring->item_len);
|
||||
*alloced = min_t(u16, n_items, available - 1);
|
||||
if (*alloced + commonring->w_ptr > commonring->depth)
|
||||
*alloced = commonring->depth - commonring->w_ptr;
|
||||
commonring->w_ptr += *alloced;
|
||||
if (commonring->w_ptr == commonring->depth)
|
||||
commonring->w_ptr = 0;
|
||||
return ret_ptr;
|
||||
}
|
||||
|
||||
if (retry) {
|
||||
if (commonring->cr_update_rptr)
|
||||
commonring->cr_update_rptr(commonring->cr_ctx);
|
||||
retry = false;
|
||||
goto again;
|
||||
}
|
||||
|
||||
commonring->was_full = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
|
||||
{
|
||||
void *address;
|
||||
|
||||
address = commonring->buf_addr;
|
||||
address += (commonring->f_ptr * commonring->item_len);
|
||||
if (commonring->f_ptr > commonring->w_ptr) {
|
||||
brcmf_dma_flush(address,
|
||||
(commonring->depth - commonring->f_ptr) *
|
||||
commonring->item_len);
|
||||
address = commonring->buf_addr;
|
||||
commonring->f_ptr = 0;
|
||||
}
|
||||
brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
|
||||
commonring->item_len);
|
||||
|
||||
commonring->f_ptr = commonring->w_ptr;
|
||||
|
||||
if (commonring->cr_write_wptr)
|
||||
commonring->cr_write_wptr(commonring->cr_ctx);
|
||||
if (commonring->cr_ring_bell)
|
||||
return commonring->cr_ring_bell(commonring->cr_ctx);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
|
||||
u16 n_items)
|
||||
{
|
||||
if (commonring->w_ptr == 0)
|
||||
commonring->w_ptr = commonring->depth - n_items;
|
||||
else
|
||||
commonring->w_ptr -= n_items;
|
||||
}
|
||||
|
||||
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items)
|
||||
{
|
||||
void *ret_addr;
|
||||
|
||||
if (commonring->cr_update_wptr)
|
||||
commonring->cr_update_wptr(commonring->cr_ctx);
|
||||
|
||||
*n_items = (commonring->w_ptr >= commonring->r_ptr) ?
|
||||
(commonring->w_ptr - commonring->r_ptr) :
|
||||
(commonring->depth - commonring->r_ptr);
|
||||
|
||||
if (*n_items == 0)
|
||||
return NULL;
|
||||
|
||||
ret_addr = commonring->buf_addr +
|
||||
(commonring->r_ptr * commonring->item_len);
|
||||
|
||||
commonring->r_ptr += *n_items;
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
|
||||
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
|
||||
{
|
||||
if (commonring->cr_write_rptr)
|
||||
return commonring->cr_write_rptr(commonring->cr_ctx);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
69
drivers/net/wireless/brcm80211/brcmfmac/commonring.h
Normal file
69
drivers/net/wireless/brcm80211/brcmfmac/commonring.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_COMMONRING_H
|
||||
#define BRCMFMAC_COMMONRING_H
|
||||
|
||||
|
||||
struct brcmf_commonring {
|
||||
u16 r_ptr;
|
||||
u16 w_ptr;
|
||||
u16 f_ptr;
|
||||
u16 depth;
|
||||
u16 item_len;
|
||||
|
||||
void *buf_addr;
|
||||
|
||||
int (*cr_ring_bell)(void *ctx);
|
||||
int (*cr_update_rptr)(void *ctx);
|
||||
int (*cr_update_wptr)(void *ctx);
|
||||
int (*cr_write_rptr)(void *ctx);
|
||||
int (*cr_write_wptr)(void *ctx);
|
||||
|
||||
void *cr_ctx;
|
||||
|
||||
spinlock_t lock;
|
||||
unsigned long flags;
|
||||
bool inited;
|
||||
bool was_full;
|
||||
};
|
||||
|
||||
|
||||
void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
|
||||
int (*cr_ring_bell)(void *ctx),
|
||||
int (*cr_update_rptr)(void *ctx),
|
||||
int (*cr_update_wptr)(void *ctx),
|
||||
int (*cr_write_rptr)(void *ctx),
|
||||
int (*cr_write_wptr)(void *ctx), void *ctx);
|
||||
void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
|
||||
u16 item_len, void *buf_addr);
|
||||
void brcmf_commonring_lock(struct brcmf_commonring *commonring);
|
||||
void brcmf_commonring_unlock(struct brcmf_commonring *commonring);
|
||||
bool brcmf_commonring_write_available(struct brcmf_commonring *commonring);
|
||||
void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring);
|
||||
void *
|
||||
brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
|
||||
u16 n_items, u16 *alloced);
|
||||
int brcmf_commonring_write_complete(struct brcmf_commonring *commonring);
|
||||
void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
|
||||
u16 n_items);
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items);
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
|
||||
|
||||
#define brcmf_commonring_n_items(commonring) (commonring->depth)
|
||||
#define brcmf_commonring_len_item(commonring) (commonring->item_len)
|
||||
|
||||
|
||||
#endif /* BRCMFMAC_COMMONRING_H */
|
||||
189
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
Normal file
189
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
/****************
|
||||
* Common types *
|
||||
*/
|
||||
|
||||
#ifndef _BRCMF_H_
|
||||
#define _BRCMF_H_
|
||||
|
||||
#include "fweh.h"
|
||||
|
||||
#define TOE_TX_CSUM_OL 0x00000001
|
||||
#define TOE_RX_CSUM_OL 0x00000002
|
||||
|
||||
/* For supporting multiple interfaces */
|
||||
#define BRCMF_MAX_IFS 16
|
||||
|
||||
#define DOT11_MAX_DEFAULT_KEYS 4
|
||||
|
||||
/* Small, medium and maximum buffer size for dcmd
|
||||
*/
|
||||
#define BRCMF_DCMD_SMLEN 256
|
||||
#define BRCMF_DCMD_MEDLEN 1536
|
||||
#define BRCMF_DCMD_MAXLEN 8192
|
||||
|
||||
/* IOCTL from host to device are limited in lenght. A device can only handle
|
||||
* ethernet frame size. This limitation is to be applied by protocol layer.
|
||||
*/
|
||||
#define BRCMF_TX_IOCTL_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
|
||||
|
||||
#define BRCMF_AMPDU_RX_REORDER_MAXFLOWS 256
|
||||
|
||||
/* Length of firmware version string stored for
|
||||
* ethtool driver info which uses 32 bytes as well.
|
||||
*/
|
||||
#define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32
|
||||
|
||||
/**
|
||||
* struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info
|
||||
*
|
||||
* @pktslots: dynamic allocated array for ordering AMPDU packets.
|
||||
* @flow_id: AMPDU flow identifier.
|
||||
* @cur_idx: last AMPDU index from firmware.
|
||||
* @exp_idx: expected next AMPDU index.
|
||||
* @max_idx: maximum amount of packets per AMPDU.
|
||||
* @pend_pkts: number of packets currently in @pktslots.
|
||||
*/
|
||||
struct brcmf_ampdu_rx_reorder {
|
||||
struct sk_buff **pktslots;
|
||||
u8 flow_id;
|
||||
u8 cur_idx;
|
||||
u8 exp_idx;
|
||||
u8 max_idx;
|
||||
u8 pend_pkts;
|
||||
};
|
||||
|
||||
/* Forward decls for struct brcmf_pub (see below) */
|
||||
struct brcmf_proto; /* device communication protocol info */
|
||||
struct brcmf_cfg80211_dev; /* cfg80211 device info */
|
||||
struct brcmf_fws_info; /* firmware signalling info */
|
||||
|
||||
/* Common structure for module and instance linkage */
|
||||
struct brcmf_pub {
|
||||
/* Linkage ponters */
|
||||
struct brcmf_bus *bus_if;
|
||||
struct brcmf_proto *proto;
|
||||
struct brcmf_cfg80211_info *config;
|
||||
|
||||
/* Internal brcmf items */
|
||||
uint hdrlen; /* Total BRCMF header length (proto + bus) */
|
||||
uint rxsz; /* Rx buffer size bus module should use */
|
||||
u8 wme_dp; /* wme discard priority */
|
||||
|
||||
/* Dongle media info */
|
||||
char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN];
|
||||
u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
|
||||
|
||||
/* Multicast data packets sent to dongle */
|
||||
unsigned long tx_multicast;
|
||||
|
||||
struct brcmf_if *iflist[BRCMF_MAX_IFS];
|
||||
|
||||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
struct brcmf_fweh_info fweh;
|
||||
|
||||
struct brcmf_fws_info *fws;
|
||||
|
||||
struct brcmf_ampdu_rx_reorder
|
||||
*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
|
||||
|
||||
u32 feat_flags;
|
||||
u32 chip_quirks;
|
||||
|
||||
#ifdef DEBUG
|
||||
struct dentry *dbgfs_dir;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* forward declarations */
|
||||
struct brcmf_cfg80211_vif;
|
||||
struct brcmf_fws_mac_descriptor;
|
||||
|
||||
/**
|
||||
* enum brcmf_netif_stop_reason - reason for stopping netif queue.
|
||||
*
|
||||
* @BRCMF_NETIF_STOP_REASON_FWS_FC:
|
||||
* netif stopped due to firmware signalling flow control.
|
||||
* @BRCMF_NETIF_STOP_REASON_FLOW:
|
||||
* netif stopped due to flowring full.
|
||||
*/
|
||||
enum brcmf_netif_stop_reason {
|
||||
BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
|
||||
BRCMF_NETIF_STOP_REASON_FLOW = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_if - interface control information.
|
||||
*
|
||||
* @drvr: points to device related information.
|
||||
* @vif: points to cfg80211 specific interface information.
|
||||
* @ndev: associated network device.
|
||||
* @stats: interface specific network statistics.
|
||||
* @setmacaddr_work: worker object for setting mac address.
|
||||
* @multicast_work: worker object for multicast provisioning.
|
||||
* @fws_desc: interface specific firmware-signalling descriptor.
|
||||
* @ifidx: interface index in device firmware.
|
||||
* @bssidx: index of bss associated with this interface.
|
||||
* @mac_addr: assigned mac address.
|
||||
* @netif_stop: bitmap indicates reason why netif queues are stopped.
|
||||
* @netif_stop_lock: spinlock for update netif_stop from multiple sources.
|
||||
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
|
||||
* @pend_8021x_wait: used for signalling change in count.
|
||||
*/
|
||||
struct brcmf_if {
|
||||
struct brcmf_pub *drvr;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct net_device *ndev;
|
||||
struct net_device_stats stats;
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
struct brcmf_fws_mac_descriptor *fws_desc;
|
||||
int ifidx;
|
||||
s32 bssidx;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 netif_stop;
|
||||
spinlock_t netif_stop_lock;
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
};
|
||||
|
||||
struct brcmf_skb_reorder_data {
|
||||
u8 *reorder;
|
||||
};
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
|
||||
|
||||
/* Return pointer to interface name */
|
||||
char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
|
||||
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
char *name, u8 *mac_addr);
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
|
||||
void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
||||
enum brcmf_netif_stop_reason reason, bool state);
|
||||
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
|
||||
bool success);
|
||||
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
|
||||
/* Sets dongle media info (drv_version, mac address). */
|
||||
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
|
||||
|
||||
#endif /* _BRCMF_H_ */
|
||||
244
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
Normal file
244
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef _BRCMF_BUS_H_
|
||||
#define _BRCMF_BUS_H_
|
||||
|
||||
#include "dhd_dbg.h"
|
||||
|
||||
/* IDs of the 6 default common rings of msgbuf protocol */
|
||||
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
|
||||
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1
|
||||
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2
|
||||
#define BRCMF_D2H_MSGRING_TX_COMPLETE 3
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE 4
|
||||
|
||||
#define BRCMF_NROF_H2D_COMMON_MSGRINGS 2
|
||||
#define BRCMF_NROF_D2H_COMMON_MSGRINGS 3
|
||||
#define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \
|
||||
BRCMF_NROF_D2H_COMMON_MSGRINGS)
|
||||
|
||||
/* The level of bus communication with the dongle */
|
||||
enum brcmf_bus_state {
|
||||
BRCMF_BUS_UNKNOWN, /* Not determined yet */
|
||||
BRCMF_BUS_NOMEDIUM, /* No medium access to dongle */
|
||||
BRCMF_BUS_DOWN, /* Not ready for frame transfers */
|
||||
BRCMF_BUS_LOAD, /* Download access only (CPU reset) */
|
||||
BRCMF_BUS_DATA /* Ready for frame transfers */
|
||||
};
|
||||
|
||||
/* The level of bus communication with the dongle */
|
||||
enum brcmf_bus_protocol_type {
|
||||
BRCMF_PROTO_BCDC,
|
||||
BRCMF_PROTO_MSGBUF
|
||||
};
|
||||
|
||||
struct brcmf_bus_dcmd {
|
||||
char *name;
|
||||
char *param;
|
||||
int param_len;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_bus_ops - bus callback operations.
|
||||
*
|
||||
* @preinit: execute bus/device specific dongle init commands (optional).
|
||||
* @init: prepare for communication with dongle.
|
||||
* @stop: clear pending frames, disable data flow.
|
||||
* @txdata: send a data frame to the dongle. When the data
|
||||
* has been transferred, the common driver must be
|
||||
* notified using brcmf_txcomplete(). The common
|
||||
* driver calls this function with interrupts
|
||||
* disabled.
|
||||
* @txctl: transmit a control request message to dongle.
|
||||
* @rxctl: receive a control response message from dongle.
|
||||
* @gettxq: obtain a reference of bus transmit queue (optional).
|
||||
* @wowl_config: specify if dongle is configured for wowl when going to suspend
|
||||
*
|
||||
* This structure provides an abstract interface towards the
|
||||
* bus specific driver. For control messages to common driver
|
||||
* will assure there is only one active transaction. Unless
|
||||
* indicated otherwise these callbacks are mandatory.
|
||||
*/
|
||||
struct brcmf_bus_ops {
|
||||
int (*preinit)(struct device *dev);
|
||||
void (*stop)(struct device *dev);
|
||||
int (*txdata)(struct device *dev, struct sk_buff *skb);
|
||||
int (*txctl)(struct device *dev, unsigned char *msg, uint len);
|
||||
int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
|
||||
struct pktq * (*gettxq)(struct device *dev);
|
||||
void (*wowl_config)(struct device *dev, bool enabled);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct brcmf_bus_msgbuf - bus ringbuf if in case of msgbuf.
|
||||
*
|
||||
* @commonrings: commonrings which are always there.
|
||||
* @flowrings: commonrings which are dynamically created and destroyed for data.
|
||||
* @rx_dataoffset: if set then all rx data has this this offset.
|
||||
* @max_rxbufpost: maximum number of buffers to post for rx.
|
||||
* @nrof_flowrings: number of flowrings.
|
||||
*/
|
||||
struct brcmf_bus_msgbuf {
|
||||
struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
|
||||
struct brcmf_commonring **flowrings;
|
||||
u32 rx_dataoffset;
|
||||
u32 max_rxbufpost;
|
||||
u32 nrof_flowrings;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct brcmf_bus - interface structure between common and bus layer
|
||||
*
|
||||
* @bus_priv: pointer to private bus device.
|
||||
* @proto_type: protocol type, bcdc or msgbuf
|
||||
* @dev: device pointer of bus device.
|
||||
* @drvr: public driver information.
|
||||
* @state: operational state of the bus interface.
|
||||
* @maxctl: maximum size for rxctl request message.
|
||||
* @tx_realloc: number of tx packets realloced for headroom.
|
||||
* @dstats: dongle-based statistical data.
|
||||
* @dcmd_list: bus/device specific dongle initialization commands.
|
||||
* @chip: device identifier of the dongle chip.
|
||||
* @wowl_supported: is wowl supported by bus driver.
|
||||
* @chiprev: revision of the dongle chip.
|
||||
*/
|
||||
struct brcmf_bus {
|
||||
union {
|
||||
struct brcmf_sdio_dev *sdio;
|
||||
struct brcmf_usbdev *usb;
|
||||
struct brcmf_pciedev *pcie;
|
||||
} bus_priv;
|
||||
enum brcmf_bus_protocol_type proto_type;
|
||||
struct device *dev;
|
||||
struct brcmf_pub *drvr;
|
||||
enum brcmf_bus_state state;
|
||||
uint maxctl;
|
||||
unsigned long tx_realloc;
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
bool always_use_fws_queue;
|
||||
bool wowl_supported;
|
||||
|
||||
struct brcmf_bus_ops *ops;
|
||||
struct brcmf_bus_msgbuf *msgbuf;
|
||||
};
|
||||
|
||||
/*
|
||||
* callback wrappers
|
||||
*/
|
||||
static inline int brcmf_bus_preinit(struct brcmf_bus *bus)
|
||||
{
|
||||
if (!bus->ops->preinit)
|
||||
return 0;
|
||||
return bus->ops->preinit(bus->dev);
|
||||
}
|
||||
|
||||
static inline void brcmf_bus_stop(struct brcmf_bus *bus)
|
||||
{
|
||||
bus->ops->stop(bus->dev);
|
||||
}
|
||||
|
||||
static inline int brcmf_bus_txdata(struct brcmf_bus *bus, struct sk_buff *skb)
|
||||
{
|
||||
return bus->ops->txdata(bus->dev, skb);
|
||||
}
|
||||
|
||||
static inline
|
||||
int brcmf_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
|
||||
{
|
||||
return bus->ops->txctl(bus->dev, msg, len);
|
||||
}
|
||||
|
||||
static inline
|
||||
int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
|
||||
{
|
||||
return bus->ops->rxctl(bus->dev, msg, len);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
|
||||
{
|
||||
if (!bus->ops->gettxq)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
return bus->ops->gettxq(bus->dev);
|
||||
}
|
||||
|
||||
static inline
|
||||
void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled)
|
||||
{
|
||||
if (bus->ops->wowl_config)
|
||||
bus->ops->wowl_config(bus->dev, enabled);
|
||||
}
|
||||
|
||||
static inline bool brcmf_bus_ready(struct brcmf_bus *bus)
|
||||
{
|
||||
return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA;
|
||||
}
|
||||
|
||||
static inline void brcmf_bus_change_state(struct brcmf_bus *bus,
|
||||
enum brcmf_bus_state new_state)
|
||||
{
|
||||
/* NOMEDIUM is permanent */
|
||||
if (bus->state == BRCMF_BUS_NOMEDIUM)
|
||||
return;
|
||||
|
||||
brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state);
|
||||
bus->state = new_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* interface functions from common layer
|
||||
*/
|
||||
|
||||
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt,
|
||||
int prec);
|
||||
|
||||
/* Receive frame for delivery to OS. Callee disposes of rxp. */
|
||||
void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
|
||||
|
||||
/* Indication from bus module regarding presence/insertion of dongle. */
|
||||
int brcmf_attach(struct device *dev);
|
||||
/* Indication from bus module regarding removal/absence of dongle */
|
||||
void brcmf_detach(struct device *dev);
|
||||
/* Indication from bus module that dongle should be reset */
|
||||
void brcmf_dev_reset(struct device *dev);
|
||||
/* Indication from bus module to change flow-control state */
|
||||
void brcmf_txflowblock(struct device *dev, bool state);
|
||||
|
||||
/* Notify the bus has transferred the tx packet to firmware */
|
||||
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
|
||||
|
||||
int brcmf_bus_start(struct device *dev);
|
||||
s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data,
|
||||
u32 len);
|
||||
void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||
void brcmf_sdio_exit(void);
|
||||
void brcmf_sdio_init(void);
|
||||
void brcmf_sdio_register(void);
|
||||
#endif
|
||||
#ifdef CONFIG_BRCMFMAC_USB
|
||||
void brcmf_usb_exit(void);
|
||||
void brcmf_usb_register(void);
|
||||
#endif
|
||||
|
||||
#endif /* _BRCMF_BUS_H_ */
|
||||
400
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
Normal file
400
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fwil.h"
|
||||
#include "fwil_types.h"
|
||||
#include "tracepoint.h"
|
||||
|
||||
#define PKTFILTER_BUF_SIZE 128
|
||||
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
|
||||
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
|
||||
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
||||
#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
|
||||
|
||||
/* boost value for RSSI_DELTA in preferred join selection */
|
||||
#define BRCMF_JOIN_PREF_RSSI_BOOST 8
|
||||
|
||||
|
||||
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
||||
struct sk_buff *pkt, int prec)
|
||||
{
|
||||
struct sk_buff *p;
|
||||
int eprec = -1; /* precedence to evict from */
|
||||
bool discard_oldest;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
/* Fast case, precedence queue is not full and we are also not
|
||||
* exceeding total queue length
|
||||
*/
|
||||
if (!pktq_pfull(q, prec) && !pktq_full(q)) {
|
||||
brcmu_pktq_penq(q, prec, pkt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Determine precedence from which to evict packet, if any */
|
||||
if (pktq_pfull(q, prec))
|
||||
eprec = prec;
|
||||
else if (pktq_full(q)) {
|
||||
p = brcmu_pktq_peek_tail(q, &eprec);
|
||||
if (eprec > prec)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Evict if needed */
|
||||
if (eprec >= 0) {
|
||||
/* Detect queueing to unconfigured precedence */
|
||||
discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec);
|
||||
if (eprec == prec && !discard_oldest)
|
||||
return false; /* refuse newer (incoming) packet */
|
||||
/* Evict packet according to discard policy */
|
||||
p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
|
||||
brcmu_pktq_pdeq_tail(q, eprec);
|
||||
if (p == NULL)
|
||||
brcmf_err("brcmu_pktq_penq() failed, oldest %d\n",
|
||||
discard_oldest);
|
||||
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
}
|
||||
|
||||
/* Enqueue */
|
||||
p = brcmu_pktq_penq(q, prec, pkt);
|
||||
if (p == NULL)
|
||||
brcmf_err("brcmu_pktq_penq() failed\n");
|
||||
|
||||
return p != NULL;
|
||||
}
|
||||
|
||||
/* Convert user's input in hex pattern to byte-size mask */
|
||||
static int brcmf_c_pattern_atoh(char *src, char *dst)
|
||||
{
|
||||
int i;
|
||||
if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
|
||||
brcmf_err("Mask invalid format. Needs to start with 0x\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
src = src + 2; /* Skip past 0x */
|
||||
if (strlen(src) % 2 != 0) {
|
||||
brcmf_err("Mask invalid format. Length must be even.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; *src != '\0'; i++) {
|
||||
unsigned long res;
|
||||
char num[3];
|
||||
strncpy(num, src, 2);
|
||||
num[2] = '\0';
|
||||
if (kstrtoul(num, 16, &res))
|
||||
return -EINVAL;
|
||||
dst[i] = (u8)res;
|
||||
src += 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
|
||||
int master_mode)
|
||||
{
|
||||
unsigned long res;
|
||||
char *argv;
|
||||
char *arg_save = NULL, *arg_org = NULL;
|
||||
s32 err;
|
||||
struct brcmf_pkt_filter_enable_le enable_parm;
|
||||
|
||||
arg_save = kstrdup(arg, GFP_ATOMIC);
|
||||
if (!arg_save)
|
||||
goto fail;
|
||||
|
||||
arg_org = arg_save;
|
||||
|
||||
argv = strsep(&arg_save, " ");
|
||||
|
||||
if (argv == NULL) {
|
||||
brcmf_err("No args provided\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Parse packet filter id. */
|
||||
enable_parm.id = 0;
|
||||
if (!kstrtoul(argv, 0, &res))
|
||||
enable_parm.id = cpu_to_le32((u32)res);
|
||||
|
||||
/* Enable/disable the specified filter. */
|
||||
enable_parm.enable = cpu_to_le32(enable);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
|
||||
sizeof(enable_parm));
|
||||
if (err)
|
||||
brcmf_err("Set pkt_filter_enable error (%d)\n", err);
|
||||
|
||||
/* Control the master mode */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
|
||||
if (err)
|
||||
brcmf_err("Set pkt_filter_mode error (%d)\n", err);
|
||||
|
||||
fail:
|
||||
kfree(arg_org);
|
||||
}
|
||||
|
||||
static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
|
||||
{
|
||||
struct brcmf_pkt_filter_le *pkt_filter;
|
||||
unsigned long res;
|
||||
int buf_len;
|
||||
s32 err;
|
||||
u32 mask_size;
|
||||
u32 pattern_size;
|
||||
char *argv[8], *buf = NULL;
|
||||
int i = 0;
|
||||
char *arg_save = NULL, *arg_org = NULL;
|
||||
|
||||
arg_save = kstrdup(arg, GFP_ATOMIC);
|
||||
if (!arg_save)
|
||||
goto fail;
|
||||
|
||||
arg_org = arg_save;
|
||||
|
||||
buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
|
||||
if (!buf)
|
||||
goto fail;
|
||||
|
||||
argv[i] = strsep(&arg_save, " ");
|
||||
while (argv[i]) {
|
||||
i++;
|
||||
if (i >= 8) {
|
||||
brcmf_err("Too many parameters\n");
|
||||
goto fail;
|
||||
}
|
||||
argv[i] = strsep(&arg_save, " ");
|
||||
}
|
||||
|
||||
if (i != 6) {
|
||||
brcmf_err("Not enough args provided %d\n", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pkt_filter = (struct brcmf_pkt_filter_le *)buf;
|
||||
|
||||
/* Parse packet filter id. */
|
||||
pkt_filter->id = 0;
|
||||
if (!kstrtoul(argv[0], 0, &res))
|
||||
pkt_filter->id = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse filter polarity. */
|
||||
pkt_filter->negate_match = 0;
|
||||
if (!kstrtoul(argv[1], 0, &res))
|
||||
pkt_filter->negate_match = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse filter type. */
|
||||
pkt_filter->type = 0;
|
||||
if (!kstrtoul(argv[2], 0, &res))
|
||||
pkt_filter->type = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse pattern filter offset. */
|
||||
pkt_filter->u.pattern.offset = 0;
|
||||
if (!kstrtoul(argv[3], 0, &res))
|
||||
pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse pattern filter mask. */
|
||||
mask_size = brcmf_c_pattern_atoh(argv[4],
|
||||
(char *)pkt_filter->u.pattern.mask_and_pattern);
|
||||
|
||||
/* Parse pattern filter pattern. */
|
||||
pattern_size = brcmf_c_pattern_atoh(argv[5],
|
||||
(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
|
||||
|
||||
if (mask_size != pattern_size) {
|
||||
brcmf_err("Mask and pattern not the same size\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
|
||||
buf_len = offsetof(struct brcmf_pkt_filter_le,
|
||||
u.pattern.mask_and_pattern);
|
||||
buf_len += mask_size + pattern_size;
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
|
||||
buf_len);
|
||||
if (err)
|
||||
brcmf_err("Set pkt_filter_add error (%d)\n", err);
|
||||
|
||||
fail:
|
||||
kfree(arg_org);
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||
{
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
u8 buf[BRCMF_DCMD_SMLEN];
|
||||
struct brcmf_join_pref_params join_pref_params[2];
|
||||
char *ptr;
|
||||
s32 err;
|
||||
|
||||
/* retreive mac address */
|
||||
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
sizeof(ifp->mac_addr));
|
||||
if (err < 0) {
|
||||
brcmf_err("Retreiving cur_etheraddr failed, %d\n",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
|
||||
|
||||
/* query for 'ver' to get version info from firmware */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strcpy(buf, "ver");
|
||||
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
|
||||
if (err < 0) {
|
||||
brcmf_err("Retreiving version information failed, %d\n",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
ptr = (char *)buf;
|
||||
strsep(&ptr, "\n");
|
||||
|
||||
/* Print fw version info */
|
||||
brcmf_err("Firmware version = %s\n", buf);
|
||||
|
||||
/* locate firmware version number for ethtool */
|
||||
ptr = strrchr(buf, ' ') + 1;
|
||||
strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
|
||||
|
||||
/* set mpc */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
|
||||
if (err) {
|
||||
brcmf_err("failed setting mpc\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup timeout if Beacons are lost and roam is off to report
|
||||
* link down
|
||||
*/
|
||||
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
|
||||
BRCMF_DEFAULT_BCN_TIMEOUT);
|
||||
if (err) {
|
||||
brcmf_err("bcn_timeout error (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Enable/Disable build-in roaming to allowed ext supplicant to take
|
||||
* of romaing
|
||||
*/
|
||||
err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
|
||||
if (err) {
|
||||
brcmf_err("roam_off error (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Setup join_pref to select target by RSSI(with boost on 5GHz) */
|
||||
join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
|
||||
join_pref_params[0].len = 2;
|
||||
join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
|
||||
join_pref_params[0].band = WLC_BAND_5G;
|
||||
join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
|
||||
join_pref_params[1].len = 2;
|
||||
join_pref_params[1].rssi_gain = 0;
|
||||
join_pref_params[1].band = 0;
|
||||
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
|
||||
sizeof(join_pref_params));
|
||||
if (err)
|
||||
brcmf_err("Set join_pref error (%d)\n", err);
|
||||
|
||||
/* Setup event_msgs, enable E_IF */
|
||||
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
|
||||
BRCMF_EVENTING_MASK_LEN);
|
||||
if (err) {
|
||||
brcmf_err("Get event_msgs error (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
setbit(eventmask, BRCMF_E_IF);
|
||||
err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
|
||||
BRCMF_EVENTING_MASK_LEN);
|
||||
if (err) {
|
||||
brcmf_err("Set event_msgs error (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Setup default scan channel time */
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
|
||||
BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
|
||||
if (err) {
|
||||
brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Setup default scan unassoc time */
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
|
||||
BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
|
||||
if (err) {
|
||||
brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Setup packet filter */
|
||||
brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
|
||||
brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
|
||||
0, true);
|
||||
|
||||
/* do bus specific preinit here */
|
||||
err = brcmf_bus_preinit(ifp->drvr->bus_if);
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRCM_TRACING
|
||||
void __brcmf_err(const char *func, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
pr_err("%s: %pV", func, &vaf);
|
||||
trace_brcmf_err(func, &vaf);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
|
||||
void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
if (brcmf_msg_level & level)
|
||||
pr_debug("%s %pV", func, &vaf);
|
||||
trace_brcmf_dbg(level, func, &vaf);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
117
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
Normal file
117
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* 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/netdevice.h>
|
||||
#include <linux/module.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;
|
||||
}
|
||||
|
||||
static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
|
||||
{
|
||||
struct brcmf_bus *bus = dev_get_drvdata(seq->private);
|
||||
|
||||
seq_printf(seq, "chip: %x(%u) rev %u\n",
|
||||
bus->chip, bus->chip, bus->chiprev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct device *dev = drvr->bus_if->dev;
|
||||
|
||||
if (!root_folder)
|
||||
return -ENODEV;
|
||||
|
||||
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
|
||||
brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
|
||||
|
||||
return PTR_ERR_OR_ZERO(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;
|
||||
}
|
||||
|
||||
struct brcmf_debugfs_entry {
|
||||
int (*read)(struct seq_file *seq, void *data);
|
||||
struct brcmf_pub *drvr;
|
||||
};
|
||||
|
||||
static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
struct brcmf_debugfs_entry *entry = inode->i_private;
|
||||
|
||||
return single_open(f, entry->read, entry->drvr->bus_if->dev);
|
||||
}
|
||||
|
||||
static const struct file_operations brcmf_debugfs_def_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = brcmf_debugfs_entry_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek
|
||||
};
|
||||
|
||||
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
|
||||
int (*read_fn)(struct seq_file *seq, void *data))
|
||||
{
|
||||
struct dentry *dentry = drvr->dbgfs_dir;
|
||||
struct brcmf_debugfs_entry *entry;
|
||||
|
||||
if (IS_ERR_OR_NULL(dentry))
|
||||
return -ENOENT;
|
||||
|
||||
entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->read = read_fn;
|
||||
entry->drvr = drvr;
|
||||
|
||||
dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
|
||||
&brcmf_debugfs_def_ops);
|
||||
|
||||
return PTR_ERR_OR_ZERO(dentry);
|
||||
}
|
||||
136
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
Normal file
136
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef _BRCMF_DBG_H_
|
||||
#define _BRCMF_DBG_H_
|
||||
|
||||
/* message levels */
|
||||
#define BRCMF_TRACE_VAL 0x00000002
|
||||
#define BRCMF_INFO_VAL 0x00000004
|
||||
#define BRCMF_DATA_VAL 0x00000008
|
||||
#define BRCMF_CTL_VAL 0x00000010
|
||||
#define BRCMF_TIMER_VAL 0x00000020
|
||||
#define BRCMF_HDRS_VAL 0x00000040
|
||||
#define BRCMF_BYTES_VAL 0x00000080
|
||||
#define BRCMF_INTR_VAL 0x00000100
|
||||
#define BRCMF_GLOM_VAL 0x00000200
|
||||
#define BRCMF_EVENT_VAL 0x00000400
|
||||
#define BRCMF_BTA_VAL 0x00000800
|
||||
#define BRCMF_FIL_VAL 0x00001000
|
||||
#define BRCMF_USB_VAL 0x00002000
|
||||
#define BRCMF_SCAN_VAL 0x00004000
|
||||
#define BRCMF_CONN_VAL 0x00008000
|
||||
#define BRCMF_BCDC_VAL 0x00010000
|
||||
#define BRCMF_SDIO_VAL 0x00020000
|
||||
#define BRCMF_MSGBUF_VAL 0x00040000
|
||||
#define BRCMF_PCIE_VAL 0x00080000
|
||||
|
||||
/* set default print format */
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
/* Macro for error messages. net_ratelimit() is used when driver
|
||||
* debugging is not selected. When debugging the driver error
|
||||
* messages are as important as other tracing or even more so.
|
||||
*/
|
||||
#ifndef CONFIG_BRCM_TRACING
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
#define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define brcmf_err(fmt, ...) \
|
||||
do { \
|
||||
if (net_ratelimit()) \
|
||||
pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
__printf(2, 3)
|
||||
void __brcmf_err(const char *func, const char *fmt, ...);
|
||||
#define brcmf_err(fmt, ...) \
|
||||
__brcmf_err(__func__, fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING)
|
||||
__printf(3, 4)
|
||||
void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...);
|
||||
#define brcmf_dbg(level, fmt, ...) \
|
||||
do { \
|
||||
__brcmf_dbg(BRCMF_##level##_VAL, __func__, \
|
||||
fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
|
||||
#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
|
||||
#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL)
|
||||
#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
|
||||
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
|
||||
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
|
||||
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
|
||||
|
||||
#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
|
||||
|
||||
#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define BRCMF_DATA_ON() 0
|
||||
#define BRCMF_CTL_ON() 0
|
||||
#define BRCMF_HDRS_ON() 0
|
||||
#define BRCMF_BYTES_ON() 0
|
||||
#define BRCMF_GLOM_ON() 0
|
||||
#define BRCMF_EVENT_ON() 0
|
||||
#define BRCMF_FIL_ON() 0
|
||||
|
||||
#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
|
||||
|
||||
#define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \
|
||||
do { \
|
||||
trace_brcmf_hexdump((void *)data, len); \
|
||||
if (test) \
|
||||
brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
extern int brcmf_msg_level;
|
||||
|
||||
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);
|
||||
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
|
||||
int (*read_fn)(struct seq_file *seq, void *data));
|
||||
#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)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
|
||||
int (*read_fn)(struct seq_file *seq, void *data))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BRCMF_DBG_H_ */
|
||||
1124
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Normal file
1124
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Normal file
File diff suppressed because it is too large
Load diff
4274
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
Normal file
4274
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
Normal file
File diff suppressed because it is too large
Load diff
138
drivers/net/wireless/brcm80211/brcmfmac/feature.c
Normal file
138
drivers/net/wireless/brcm80211/brcmfmac/feature.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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/netdevice.h>
|
||||
|
||||
#include <brcm_hw_ids.h>
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fwil.h"
|
||||
#include "feature.h"
|
||||
|
||||
/*
|
||||
* firmware error code received if iovar is unsupported.
|
||||
*/
|
||||
#define EBRCMF_FEAT_UNSUPPORTED 23
|
||||
|
||||
/*
|
||||
* expand feature list to array of feature strings.
|
||||
*/
|
||||
#define BRCMF_FEAT_DEF(_f) \
|
||||
#_f,
|
||||
static const char *brcmf_feat_names[] = {
|
||||
BRCMF_FEAT_LIST
|
||||
};
|
||||
#undef BRCMF_FEAT_DEF
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* expand quirk list to array of quirk strings.
|
||||
*/
|
||||
#define BRCMF_QUIRK_DEF(_q) \
|
||||
#_q,
|
||||
static const char * const brcmf_quirk_names[] = {
|
||||
BRCMF_QUIRK_LIST
|
||||
};
|
||||
#undef BRCMF_QUIRK_DEF
|
||||
|
||||
/**
|
||||
* brcmf_feat_debugfs_read() - expose feature info to debugfs.
|
||||
*
|
||||
* @seq: sequence for debugfs entry.
|
||||
* @data: raw data pointer.
|
||||
*/
|
||||
static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
|
||||
u32 feats = bus_if->drvr->feat_flags;
|
||||
u32 quirks = bus_if->drvr->chip_quirks;
|
||||
int id;
|
||||
|
||||
seq_printf(seq, "Features: %08x\n", feats);
|
||||
for (id = 0; id < BRCMF_FEAT_LAST; id++)
|
||||
if (feats & BIT(id))
|
||||
seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
|
||||
seq_printf(seq, "\nQuirks: %08x\n", quirks);
|
||||
for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
|
||||
if (quirks & BIT(id))
|
||||
seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/**
|
||||
* brcmf_feat_iovar_int_get() - determine feature through iovar query.
|
||||
*
|
||||
* @ifp: interface to query.
|
||||
* @id: feature id.
|
||||
* @name: iovar name.
|
||||
*/
|
||||
static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
|
||||
enum brcmf_feat_id id, char *name)
|
||||
{
|
||||
u32 data;
|
||||
int err;
|
||||
|
||||
err = brcmf_fil_iovar_int_get(ifp, name, &data);
|
||||
if (err == 0) {
|
||||
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
|
||||
ifp->drvr->feat_flags |= BIT(id);
|
||||
} else {
|
||||
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
|
||||
brcmf_feat_names[id], err);
|
||||
}
|
||||
}
|
||||
|
||||
void brcmf_feat_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_if *ifp = drvr->iflist[0];
|
||||
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
|
||||
if (drvr->bus_if->wowl_supported)
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
|
||||
|
||||
/* set chip related quirks */
|
||||
switch (drvr->bus_if->chip) {
|
||||
case BRCM_CC_43236_CHIP_ID:
|
||||
drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
|
||||
break;
|
||||
case BRCM_CC_4329_CHIP_ID:
|
||||
drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
|
||||
break;
|
||||
default:
|
||||
/* no quirks */
|
||||
break;
|
||||
}
|
||||
|
||||
brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
|
||||
}
|
||||
|
||||
bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
|
||||
{
|
||||
return (ifp->drvr->feat_flags & BIT(id));
|
||||
}
|
||||
|
||||
bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
|
||||
enum brcmf_feat_quirk quirk)
|
||||
{
|
||||
return (ifp->drvr->chip_quirks & BIT(quirk));
|
||||
}
|
||||
87
drivers/net/wireless/brcm80211/brcmfmac/feature.h
Normal file
87
drivers/net/wireless/brcm80211/brcmfmac/feature.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifndef _BRCMF_FEATURE_H
|
||||
#define _BRCMF_FEATURE_H
|
||||
|
||||
/*
|
||||
* Features:
|
||||
*
|
||||
* MCHAN: multi-channel for concurrent P2P.
|
||||
*/
|
||||
#define BRCMF_FEAT_LIST \
|
||||
BRCMF_FEAT_DEF(MCHAN) \
|
||||
BRCMF_FEAT_DEF(WOWL)
|
||||
/*
|
||||
* Quirks:
|
||||
*
|
||||
* AUTO_AUTH: workaround needed for automatic authentication type.
|
||||
* NEED_MPC: driver needs to disable MPC during scanning operation.
|
||||
*/
|
||||
#define BRCMF_QUIRK_LIST \
|
||||
BRCMF_QUIRK_DEF(AUTO_AUTH) \
|
||||
BRCMF_QUIRK_DEF(NEED_MPC)
|
||||
|
||||
#define BRCMF_FEAT_DEF(_f) \
|
||||
BRCMF_FEAT_ ## _f,
|
||||
/*
|
||||
* expand feature list to enumeration.
|
||||
*/
|
||||
enum brcmf_feat_id {
|
||||
BRCMF_FEAT_LIST
|
||||
BRCMF_FEAT_LAST
|
||||
};
|
||||
#undef BRCMF_FEAT_DEF
|
||||
|
||||
#define BRCMF_QUIRK_DEF(_q) \
|
||||
BRCMF_FEAT_QUIRK_ ## _q,
|
||||
/*
|
||||
* expand quirk list to enumeration.
|
||||
*/
|
||||
enum brcmf_feat_quirk {
|
||||
BRCMF_QUIRK_LIST
|
||||
BRCMF_FEAT_QUIRK_LAST
|
||||
};
|
||||
#undef BRCMF_QUIRK_DEF
|
||||
|
||||
/**
|
||||
* brcmf_feat_attach() - determine features and quirks.
|
||||
*
|
||||
* @drvr: driver instance.
|
||||
*/
|
||||
void brcmf_feat_attach(struct brcmf_pub *drvr);
|
||||
|
||||
/**
|
||||
* brcmf_feat_is_enabled() - query feature.
|
||||
*
|
||||
* @ifp: interface instance.
|
||||
* @id: feature id to check.
|
||||
*
|
||||
* Return: true is feature is enabled; otherwise false.
|
||||
*/
|
||||
bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id);
|
||||
|
||||
/**
|
||||
* brcmf_feat_is_quirk_enabled() - query chip quirk.
|
||||
*
|
||||
* @ifp: interface instance.
|
||||
* @quirk: quirk id to check.
|
||||
*
|
||||
* Return: true is quirk is enabled; otherwise false.
|
||||
*/
|
||||
bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
|
||||
enum brcmf_feat_quirk quirk);
|
||||
|
||||
#endif /* _BRCMF_FEATURE_H */
|
||||
337
drivers/net/wireless/brcm80211/brcmfmac/firmware.c
Normal file
337
drivers/net/wireless/brcm80211/brcmfmac/firmware.c
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "dhd_dbg.h"
|
||||
#include "firmware.h"
|
||||
|
||||
char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
|
||||
module_param_string(firmware_path, brcmf_firmware_path,
|
||||
BRCMF_FW_PATH_LEN, 0440);
|
||||
|
||||
enum nvram_parser_state {
|
||||
IDLE,
|
||||
KEY,
|
||||
VALUE,
|
||||
COMMENT,
|
||||
END
|
||||
};
|
||||
|
||||
/**
|
||||
* struct nvram_parser - internal info for parser.
|
||||
*
|
||||
* @state: current parser state.
|
||||
* @fwnv: input buffer being parsed.
|
||||
* @nvram: output buffer with parse result.
|
||||
* @nvram_len: lenght of parse result.
|
||||
* @line: current line.
|
||||
* @column: current column in line.
|
||||
* @pos: byte offset in input buffer.
|
||||
* @entry: start position of key,value entry.
|
||||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
const struct firmware *fwnv;
|
||||
u8 *nvram;
|
||||
u32 nvram_len;
|
||||
u32 line;
|
||||
u32 column;
|
||||
u32 pos;
|
||||
u32 entry;
|
||||
};
|
||||
|
||||
static bool is_nvram_char(char c)
|
||||
{
|
||||
/* comment marker excluded */
|
||||
if (c == '#')
|
||||
return false;
|
||||
|
||||
/* key and value may have any other readable character */
|
||||
return (c > 0x20 && c < 0x7f);
|
||||
}
|
||||
|
||||
static bool is_whitespace(char c)
|
||||
{
|
||||
return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
|
||||
}
|
||||
|
||||
static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
|
||||
{
|
||||
char c;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
if (c == '\n')
|
||||
return COMMENT;
|
||||
if (is_whitespace(c))
|
||||
goto proceed;
|
||||
if (c == '#')
|
||||
return COMMENT;
|
||||
if (is_nvram_char(c)) {
|
||||
nvp->entry = nvp->pos;
|
||||
return KEY;
|
||||
}
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
|
||||
nvp->line, nvp->column);
|
||||
proceed:
|
||||
nvp->column++;
|
||||
nvp->pos++;
|
||||
return IDLE;
|
||||
}
|
||||
|
||||
static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
|
||||
{
|
||||
enum nvram_parser_state st = nvp->state;
|
||||
char c;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
if (c == '=') {
|
||||
st = VALUE;
|
||||
} else if (!is_nvram_char(c)) {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
nvp->line, nvp->column);
|
||||
return COMMENT;
|
||||
}
|
||||
|
||||
nvp->column++;
|
||||
nvp->pos++;
|
||||
return st;
|
||||
}
|
||||
|
||||
static enum nvram_parser_state
|
||||
brcmf_nvram_handle_value(struct nvram_parser *nvp)
|
||||
{
|
||||
char c;
|
||||
char *skv;
|
||||
char *ekv;
|
||||
u32 cplen;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
if (!is_nvram_char(c)) {
|
||||
/* key,value pair complete */
|
||||
ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
|
||||
skv = (u8 *)&nvp->fwnv->data[nvp->entry];
|
||||
cplen = ekv - skv;
|
||||
/* copy to output buffer */
|
||||
memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
|
||||
nvp->nvram_len += cplen;
|
||||
nvp->nvram[nvp->nvram_len] = '\0';
|
||||
nvp->nvram_len++;
|
||||
return IDLE;
|
||||
}
|
||||
nvp->pos++;
|
||||
nvp->column++;
|
||||
return VALUE;
|
||||
}
|
||||
|
||||
static enum nvram_parser_state
|
||||
brcmf_nvram_handle_comment(struct nvram_parser *nvp)
|
||||
{
|
||||
char *eol, *sol;
|
||||
|
||||
sol = (char *)&nvp->fwnv->data[nvp->pos];
|
||||
eol = strchr(sol, '\n');
|
||||
if (eol == NULL)
|
||||
return END;
|
||||
|
||||
/* eat all moving to next line */
|
||||
nvp->line++;
|
||||
nvp->column = 1;
|
||||
nvp->pos += (eol - sol) + 1;
|
||||
return IDLE;
|
||||
}
|
||||
|
||||
static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
|
||||
{
|
||||
/* final state */
|
||||
return END;
|
||||
}
|
||||
|
||||
static enum nvram_parser_state
|
||||
(*nv_parser_states[])(struct nvram_parser *nvp) = {
|
||||
brcmf_nvram_handle_idle,
|
||||
brcmf_nvram_handle_key,
|
||||
brcmf_nvram_handle_value,
|
||||
brcmf_nvram_handle_comment,
|
||||
brcmf_nvram_handle_end
|
||||
};
|
||||
|
||||
static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
|
||||
const struct firmware *nv)
|
||||
{
|
||||
memset(nvp, 0, sizeof(*nvp));
|
||||
nvp->fwnv = nv;
|
||||
/* Alloc for extra 0 byte + roundup by 4 + length field */
|
||||
nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL);
|
||||
if (!nvp->nvram)
|
||||
return -ENOMEM;
|
||||
|
||||
nvp->line = 1;
|
||||
nvp->column = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
|
||||
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
|
||||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
* End of buffer is completed with token identifying length of buffer.
|
||||
*/
|
||||
static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length)
|
||||
{
|
||||
struct nvram_parser nvp;
|
||||
u32 pad;
|
||||
u32 token;
|
||||
__le32 token_le;
|
||||
|
||||
if (brcmf_init_nvram_parser(&nvp, nv) < 0)
|
||||
return NULL;
|
||||
|
||||
while (nvp.pos < nv->size) {
|
||||
nvp.state = nv_parser_states[nvp.state](&nvp);
|
||||
if (nvp.state == END)
|
||||
break;
|
||||
}
|
||||
pad = nvp.nvram_len;
|
||||
*new_length = roundup(nvp.nvram_len + 1, 4);
|
||||
while (pad != *new_length) {
|
||||
nvp.nvram[pad] = 0;
|
||||
pad++;
|
||||
}
|
||||
|
||||
token = *new_length / 4;
|
||||
token = (~token << 16) | (token & 0x0000FFFF);
|
||||
token_le = cpu_to_le32(token);
|
||||
|
||||
memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
|
||||
*new_length += sizeof(token_le);
|
||||
|
||||
return nvp.nvram;
|
||||
}
|
||||
|
||||
void brcmf_fw_nvram_free(void *nvram)
|
||||
{
|
||||
kfree(nvram);
|
||||
}
|
||||
|
||||
struct brcmf_fw {
|
||||
struct device *dev;
|
||||
u16 flags;
|
||||
const struct firmware *code;
|
||||
const char *nvram_name;
|
||||
void (*done)(struct device *dev, const struct firmware *fw,
|
||||
void *nvram_image, u32 nvram_len);
|
||||
};
|
||||
|
||||
static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
||||
{
|
||||
struct brcmf_fw *fwctx = ctx;
|
||||
u32 nvram_length = 0;
|
||||
void *nvram = NULL;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
|
||||
if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
goto fail;
|
||||
|
||||
if (fw) {
|
||||
nvram = brcmf_fw_nvram_strip(fw, &nvram_length);
|
||||
release_firmware(fw);
|
||||
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
|
||||
kfree(fwctx);
|
||||
return;
|
||||
|
||||
fail:
|
||||
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
||||
if (fwctx->code)
|
||||
release_firmware(fwctx->code);
|
||||
device_release_driver(fwctx->dev);
|
||||
kfree(fwctx);
|
||||
}
|
||||
|
||||
static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
|
||||
{
|
||||
struct brcmf_fw *fwctx = ctx;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
|
||||
if (!fw)
|
||||
goto fail;
|
||||
|
||||
/* only requested code so done here */
|
||||
if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
|
||||
fwctx->done(fwctx->dev, fw, NULL, 0);
|
||||
kfree(fwctx);
|
||||
return;
|
||||
}
|
||||
fwctx->code = fw;
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_nvram_done);
|
||||
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
/* when nvram is optional call .done() callback here */
|
||||
if (fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL) {
|
||||
fwctx->done(fwctx->dev, fw, NULL, 0);
|
||||
kfree(fwctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* failed nvram request */
|
||||
release_firmware(fw);
|
||||
fail:
|
||||
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
||||
device_release_driver(fwctx->dev);
|
||||
kfree(fwctx);
|
||||
}
|
||||
|
||||
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
|
||||
const char *code, const char *nvram,
|
||||
void (*fw_cb)(struct device *dev,
|
||||
const struct firmware *fw,
|
||||
void *nvram_image, u32 nvram_len))
|
||||
{
|
||||
struct brcmf_fw *fwctx;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
|
||||
if (!fw_cb || !code)
|
||||
return -EINVAL;
|
||||
|
||||
if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
|
||||
return -EINVAL;
|
||||
|
||||
fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
|
||||
if (!fwctx)
|
||||
return -ENOMEM;
|
||||
|
||||
fwctx->dev = dev;
|
||||
fwctx->flags = flags;
|
||||
fwctx->done = fw_cb;
|
||||
if (flags & BRCMF_FW_REQUEST_NVRAM)
|
||||
fwctx->nvram_name = nvram;
|
||||
|
||||
return request_firmware_nowait(THIS_MODULE, true, code, dev,
|
||||
GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_code_done);
|
||||
}
|
||||
41
drivers/net/wireless/brcm80211/brcmfmac/firmware.h
Normal file
41
drivers/net/wireless/brcm80211/brcmfmac/firmware.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_FIRMWARE_H
|
||||
#define BRCMFMAC_FIRMWARE_H
|
||||
|
||||
#define BRCMF_FW_REQUEST 0x000F
|
||||
#define BRCMF_FW_REQUEST_NVRAM 0x0001
|
||||
#define BRCMF_FW_REQ_FLAGS 0x00F0
|
||||
#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
|
||||
|
||||
#define BRCMF_FW_PATH_LEN 256
|
||||
#define BRCMF_FW_NAME_LEN 32
|
||||
|
||||
extern char brcmf_firmware_path[];
|
||||
|
||||
void brcmf_fw_nvram_free(void *nvram);
|
||||
/*
|
||||
* Request firmware(s) asynchronously. When the asynchronous request
|
||||
* fails it will not use the callback, but call device_release_driver()
|
||||
* instead which will call the driver .remove() callback.
|
||||
*/
|
||||
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
|
||||
const char *code, const char *nvram,
|
||||
void (*fw_cb)(struct device *dev,
|
||||
const struct firmware *fw,
|
||||
void *nvram_image, u32 nvram_len));
|
||||
|
||||
#endif /* BRCMFMAC_FIRMWARE_H */
|
||||
501
drivers/net/wireless/brcm80211/brcmfmac/flowring.c
Normal file
501
drivers/net/wireless/brcm80211/brcmfmac/flowring.c
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
/* Copyright (c) 2014 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/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <brcmu_utils.h>
|
||||
|
||||
#include "dhd.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "proto.h"
|
||||
#include "flowring.h"
|
||||
#include "msgbuf.h"
|
||||
|
||||
|
||||
#define BRCMF_FLOWRING_HIGH 1024
|
||||
#define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256)
|
||||
#define BRCMF_FLOWRING_INVALID_IFIDX 0xff
|
||||
|
||||
#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16)
|
||||
#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
|
||||
|
||||
static const u8 ALLZEROMAC[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
|
||||
static const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
static const u8 brcmf_flowring_prio2fifo[] = {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
3,
|
||||
3
|
||||
};
|
||||
|
||||
|
||||
static bool
|
||||
brcmf_flowring_is_tdls_mac(struct brcmf_flowring *flow, u8 mac[ETH_ALEN])
|
||||
{
|
||||
struct brcmf_flowring_tdls_entry *search;
|
||||
|
||||
search = flow->tdls_entry;
|
||||
|
||||
while (search) {
|
||||
if (memcmp(search->mac, mac, ETH_ALEN) == 0)
|
||||
return true;
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||
u8 prio, u8 ifidx)
|
||||
{
|
||||
struct brcmf_flowring_hash *hash;
|
||||
u8 hash_idx;
|
||||
u32 i;
|
||||
bool found;
|
||||
bool sta;
|
||||
u8 fifo;
|
||||
u8 *mac;
|
||||
|
||||
fifo = brcmf_flowring_prio2fifo[prio];
|
||||
sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
|
||||
mac = da;
|
||||
if ((!sta) && (is_multicast_ether_addr(da))) {
|
||||
mac = (u8 *)ALLFFMAC;
|
||||
fifo = 0;
|
||||
}
|
||||
if ((sta) && (flow->tdls_active) &&
|
||||
(brcmf_flowring_is_tdls_mac(flow, da))) {
|
||||
sta = false;
|
||||
}
|
||||
hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
|
||||
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
||||
found = false;
|
||||
hash = flow->hash;
|
||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||
if ((sta || (memcmp(hash[hash_idx].mac, mac, ETH_ALEN) == 0)) &&
|
||||
(hash[hash_idx].fifo == fifo) &&
|
||||
(hash[hash_idx].ifidx == ifidx)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
hash_idx++;
|
||||
}
|
||||
if (found)
|
||||
return hash[hash_idx].flowid;
|
||||
|
||||
return BRCMF_FLOWRING_INVALID_ID;
|
||||
}
|
||||
|
||||
|
||||
u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||
u8 prio, u8 ifidx)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
struct brcmf_flowring_hash *hash;
|
||||
u8 hash_idx;
|
||||
u32 i;
|
||||
bool found;
|
||||
u8 fifo;
|
||||
bool sta;
|
||||
u8 *mac;
|
||||
|
||||
fifo = brcmf_flowring_prio2fifo[prio];
|
||||
sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
|
||||
mac = da;
|
||||
if ((!sta) && (is_multicast_ether_addr(da))) {
|
||||
mac = (u8 *)ALLFFMAC;
|
||||
fifo = 0;
|
||||
}
|
||||
if ((sta) && (flow->tdls_active) &&
|
||||
(brcmf_flowring_is_tdls_mac(flow, da))) {
|
||||
sta = false;
|
||||
}
|
||||
hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
|
||||
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
||||
found = false;
|
||||
hash = flow->hash;
|
||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||
if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
|
||||
(memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
hash_idx++;
|
||||
}
|
||||
if (found) {
|
||||
for (i = 0; i < flow->nrofrings; i++) {
|
||||
if (flow->rings[i] == NULL)
|
||||
break;
|
||||
}
|
||||
if (i == flow->nrofrings)
|
||||
return -ENOMEM;
|
||||
|
||||
ring = kzalloc(sizeof(*ring), GFP_ATOMIC);
|
||||
if (!ring)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(hash[hash_idx].mac, mac, ETH_ALEN);
|
||||
hash[hash_idx].fifo = fifo;
|
||||
hash[hash_idx].ifidx = ifidx;
|
||||
hash[hash_idx].flowid = i;
|
||||
|
||||
ring->hash_id = hash_idx;
|
||||
ring->status = RING_CLOSED;
|
||||
skb_queue_head_init(&ring->skblist);
|
||||
flow->rings[i] = ring;
|
||||
|
||||
return i;
|
||||
}
|
||||
return BRCMF_FLOWRING_INVALID_ID;
|
||||
}
|
||||
|
||||
|
||||
u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
|
||||
return flow->hash[ring->hash_id].fifo;
|
||||
}
|
||||
|
||||
|
||||
static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
|
||||
bool blocked)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
struct brcmf_bus *bus_if;
|
||||
struct brcmf_pub *drvr;
|
||||
struct brcmf_if *ifp;
|
||||
bool currently_blocked;
|
||||
int i;
|
||||
u8 ifidx;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&flow->block_lock, flags);
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
ifidx = brcmf_flowring_ifidx_get(flow, flowid);
|
||||
|
||||
currently_blocked = false;
|
||||
for (i = 0; i < flow->nrofrings; i++) {
|
||||
if (flow->rings[i]) {
|
||||
ring = flow->rings[i];
|
||||
if ((ring->status == RING_OPEN) &&
|
||||
(brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
|
||||
if (ring->blocked) {
|
||||
currently_blocked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ring->blocked = blocked;
|
||||
if (currently_blocked == blocked) {
|
||||
spin_unlock_irqrestore(&flow->block_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
bus_if = dev_get_drvdata(flow->dev);
|
||||
drvr = bus_if->drvr;
|
||||
ifp = drvr->iflist[ifidx];
|
||||
brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
|
||||
|
||||
spin_unlock_irqrestore(&flow->block_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
u8 hash_idx;
|
||||
struct sk_buff *skb;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
if (!ring)
|
||||
return;
|
||||
brcmf_flowring_block(flow, flowid, false);
|
||||
hash_idx = ring->hash_id;
|
||||
flow->hash[hash_idx].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
|
||||
memset(flow->hash[hash_idx].mac, 0, ETH_ALEN);
|
||||
flow->rings[flowid] = NULL;
|
||||
|
||||
skb = skb_dequeue(&ring->skblist);
|
||||
while (skb) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
skb = skb_dequeue(&ring->skblist);
|
||||
}
|
||||
|
||||
kfree(ring);
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
|
||||
skb_queue_tail(&ring->skblist, skb);
|
||||
|
||||
if (!ring->blocked &&
|
||||
(skb_queue_len(&ring->skblist) > BRCMF_FLOWRING_HIGH)) {
|
||||
brcmf_flowring_block(flow, flowid, true);
|
||||
brcmf_dbg(MSGBUF, "Flowcontrol: BLOCK for ring %d\n", flowid);
|
||||
/* To prevent (work around) possible race condition, check
|
||||
* queue len again. It is also possible to use locking to
|
||||
* protect, but that is undesirable for every enqueue and
|
||||
* dequeue. This simple check will solve a possible race
|
||||
* condition if it occurs.
|
||||
*/
|
||||
if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
|
||||
brcmf_flowring_block(flow, flowid, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
struct sk_buff *skb;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
if (ring->status != RING_OPEN)
|
||||
return NULL;
|
||||
|
||||
skb = skb_dequeue(&ring->skblist);
|
||||
|
||||
if (ring->blocked &&
|
||||
(skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)) {
|
||||
brcmf_flowring_block(flow, flowid, false);
|
||||
brcmf_dbg(MSGBUF, "Flowcontrol: OPEN for ring %d\n", flowid);
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
|
||||
skb_queue_head(&ring->skblist, skb);
|
||||
}
|
||||
|
||||
|
||||
u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
if (!ring)
|
||||
return 0;
|
||||
|
||||
if (ring->status != RING_OPEN)
|
||||
return 0;
|
||||
|
||||
return skb_queue_len(&ring->skblist);
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
if (!ring) {
|
||||
brcmf_err("Ring NULL, for flowid %d\n", flowid);
|
||||
return;
|
||||
}
|
||||
|
||||
ring->status = RING_OPEN;
|
||||
}
|
||||
|
||||
|
||||
u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
u8 hash_idx;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
hash_idx = ring->hash_id;
|
||||
|
||||
return flow->hash[hash_idx].ifidx;
|
||||
}
|
||||
|
||||
|
||||
struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings)
|
||||
{
|
||||
struct brcmf_flowring *flow;
|
||||
u32 i;
|
||||
|
||||
flow = kzalloc(sizeof(*flow), GFP_KERNEL);
|
||||
if (flow) {
|
||||
flow->dev = dev;
|
||||
flow->nrofrings = nrofrings;
|
||||
spin_lock_init(&flow->block_lock);
|
||||
for (i = 0; i < ARRAY_SIZE(flow->addr_mode); i++)
|
||||
flow->addr_mode[i] = ADDR_INDIRECT;
|
||||
for (i = 0; i < ARRAY_SIZE(flow->hash); i++)
|
||||
flow->hash[i].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
|
||||
flow->rings = kcalloc(nrofrings, sizeof(*flow->rings),
|
||||
GFP_KERNEL);
|
||||
if (!flow->rings) {
|
||||
kfree(flow);
|
||||
flow = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return flow;
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_detach(struct brcmf_flowring *flow)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_flowring_tdls_entry *search;
|
||||
struct brcmf_flowring_tdls_entry *remove;
|
||||
u8 flowid;
|
||||
|
||||
for (flowid = 0; flowid < flow->nrofrings; flowid++) {
|
||||
if (flow->rings[flowid])
|
||||
brcmf_msgbuf_delete_flowring(drvr, flowid);
|
||||
}
|
||||
|
||||
search = flow->tdls_entry;
|
||||
while (search) {
|
||||
remove = search;
|
||||
search = search->next;
|
||||
kfree(remove);
|
||||
}
|
||||
kfree(flow->rings);
|
||||
kfree(flow);
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
|
||||
enum proto_addr_mode addr_mode)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
u32 i;
|
||||
u8 flowid;
|
||||
|
||||
if (flow->addr_mode[ifidx] != addr_mode) {
|
||||
for (i = 0; i < ARRAY_SIZE(flow->hash); i++) {
|
||||
if (flow->hash[i].ifidx == ifidx) {
|
||||
flowid = flow->hash[i].flowid;
|
||||
if (flow->rings[flowid]->status != RING_OPEN)
|
||||
continue;
|
||||
flow->rings[flowid]->status = RING_CLOSING;
|
||||
brcmf_msgbuf_delete_flowring(drvr, flowid);
|
||||
}
|
||||
}
|
||||
flow->addr_mode[ifidx] = addr_mode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
|
||||
u8 peer[ETH_ALEN])
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_flowring_hash *hash;
|
||||
struct brcmf_flowring_tdls_entry *prev;
|
||||
struct brcmf_flowring_tdls_entry *search;
|
||||
u32 i;
|
||||
u8 flowid;
|
||||
bool sta;
|
||||
|
||||
sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
|
||||
|
||||
search = flow->tdls_entry;
|
||||
prev = NULL;
|
||||
while (search) {
|
||||
if (memcmp(search->mac, peer, ETH_ALEN) == 0) {
|
||||
sta = false;
|
||||
break;
|
||||
}
|
||||
prev = search;
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
hash = flow->hash;
|
||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||
if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
|
||||
(hash[i].ifidx == ifidx)) {
|
||||
flowid = flow->hash[i].flowid;
|
||||
if (flow->rings[flowid]->status == RING_OPEN) {
|
||||
flow->rings[flowid]->status = RING_CLOSING;
|
||||
brcmf_msgbuf_delete_flowring(drvr, flowid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (search) {
|
||||
if (prev)
|
||||
prev->next = search->next;
|
||||
else
|
||||
flow->tdls_entry = search->next;
|
||||
kfree(search);
|
||||
if (flow->tdls_entry == NULL)
|
||||
flow->tdls_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
|
||||
u8 peer[ETH_ALEN])
|
||||
{
|
||||
struct brcmf_flowring_tdls_entry *tdls_entry;
|
||||
struct brcmf_flowring_tdls_entry *search;
|
||||
|
||||
tdls_entry = kzalloc(sizeof(*tdls_entry), GFP_ATOMIC);
|
||||
if (tdls_entry == NULL)
|
||||
return;
|
||||
|
||||
memcpy(tdls_entry->mac, peer, ETH_ALEN);
|
||||
tdls_entry->next = NULL;
|
||||
if (flow->tdls_entry == NULL) {
|
||||
flow->tdls_entry = tdls_entry;
|
||||
} else {
|
||||
search = flow->tdls_entry;
|
||||
if (memcmp(search->mac, peer, ETH_ALEN) == 0)
|
||||
return;
|
||||
while (search->next) {
|
||||
search = search->next;
|
||||
if (memcmp(search->mac, peer, ETH_ALEN) == 0)
|
||||
return;
|
||||
}
|
||||
search->next = tdls_entry;
|
||||
}
|
||||
|
||||
flow->tdls_active = true;
|
||||
}
|
||||
84
drivers/net/wireless/brcm80211/brcmfmac/flowring.h
Normal file
84
drivers/net/wireless/brcm80211/brcmfmac/flowring.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_FLOWRING_H
|
||||
#define BRCMFMAC_FLOWRING_H
|
||||
|
||||
|
||||
#define BRCMF_FLOWRING_HASHSIZE 256
|
||||
#define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF
|
||||
|
||||
|
||||
struct brcmf_flowring_hash {
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 fifo;
|
||||
u8 ifidx;
|
||||
u8 flowid;
|
||||
};
|
||||
|
||||
enum ring_status {
|
||||
RING_CLOSED,
|
||||
RING_CLOSING,
|
||||
RING_OPEN
|
||||
};
|
||||
|
||||
struct brcmf_flowring_ring {
|
||||
u8 hash_id;
|
||||
bool blocked;
|
||||
enum ring_status status;
|
||||
struct sk_buff_head skblist;
|
||||
};
|
||||
|
||||
struct brcmf_flowring_tdls_entry {
|
||||
u8 mac[ETH_ALEN];
|
||||
struct brcmf_flowring_tdls_entry *next;
|
||||
};
|
||||
|
||||
struct brcmf_flowring {
|
||||
struct device *dev;
|
||||
struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
|
||||
struct brcmf_flowring_ring **rings;
|
||||
spinlock_t block_lock;
|
||||
enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
|
||||
u16 nrofrings;
|
||||
bool tdls_active;
|
||||
struct brcmf_flowring_tdls_entry *tdls_entry;
|
||||
};
|
||||
|
||||
|
||||
u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||
u8 prio, u8 ifidx);
|
||||
u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||
u8 prio, u8 ifidx);
|
||||
void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
|
||||
void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
|
||||
u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
|
||||
void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb);
|
||||
struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
|
||||
void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb);
|
||||
u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid);
|
||||
u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid);
|
||||
struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings);
|
||||
void brcmf_flowring_detach(struct brcmf_flowring *flow);
|
||||
void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
|
||||
enum proto_addr_mode addr_mode);
|
||||
void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
|
||||
u8 peer[ETH_ALEN]);
|
||||
void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
|
||||
u8 peer[ETH_ALEN]);
|
||||
|
||||
|
||||
#endif /* BRCMFMAC_FLOWRING_H */
|
||||
466
drivers/net/wireless/brcm80211/brcmfmac/fweh.c
Normal file
466
drivers/net/wireless/brcm80211/brcmfmac/fweh.c
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
* 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/netdevice.h>
|
||||
|
||||
#include "brcmu_wifi.h"
|
||||
#include "brcmu_utils.h"
|
||||
|
||||
#include "dhd.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "tracepoint.h"
|
||||
#include "fwsignal.h"
|
||||
#include "fweh.h"
|
||||
#include "fwil.h"
|
||||
|
||||
/**
|
||||
* struct brcm_ethhdr - broadcom specific ether header.
|
||||
*
|
||||
* @subtype: subtype for this packet.
|
||||
* @length: TODO: length of appended data.
|
||||
* @version: version indication.
|
||||
* @oui: OUI of this packet.
|
||||
* @usr_subtype: subtype for this OUI.
|
||||
*/
|
||||
struct brcm_ethhdr {
|
||||
__be16 subtype;
|
||||
__be16 length;
|
||||
u8 version;
|
||||
u8 oui[3];
|
||||
__be16 usr_subtype;
|
||||
} __packed;
|
||||
|
||||
struct brcmf_event_msg_be {
|
||||
__be16 version;
|
||||
__be16 flags;
|
||||
__be32 event_type;
|
||||
__be32 status;
|
||||
__be32 reason;
|
||||
__be32 auth_type;
|
||||
__be32 datalen;
|
||||
u8 addr[ETH_ALEN];
|
||||
char ifname[IFNAMSIZ];
|
||||
u8 ifidx;
|
||||
u8 bsscfgidx;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct brcmf_event - contents of broadcom event packet.
|
||||
*
|
||||
* @eth: standard ether header.
|
||||
* @hdr: broadcom specific ether header.
|
||||
* @msg: common part of the actual event message.
|
||||
*/
|
||||
struct brcmf_event {
|
||||
struct ethhdr eth;
|
||||
struct brcm_ethhdr hdr;
|
||||
struct brcmf_event_msg_be msg;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct brcmf_fweh_queue_item - event item on event queue.
|
||||
*
|
||||
* @q: list element for queuing.
|
||||
* @code: event code.
|
||||
* @ifidx: interface index related to this event.
|
||||
* @ifaddr: ethernet address for interface.
|
||||
* @emsg: common parameters of the firmware event message.
|
||||
* @data: event specific data part of the firmware event.
|
||||
*/
|
||||
struct brcmf_fweh_queue_item {
|
||||
struct list_head q;
|
||||
enum brcmf_fweh_event_code code;
|
||||
u8 ifidx;
|
||||
u8 ifaddr[ETH_ALEN];
|
||||
struct brcmf_event_msg_be emsg;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_fweh_event_name - code, name mapping entry.
|
||||
*/
|
||||
struct brcmf_fweh_event_name {
|
||||
enum brcmf_fweh_event_code code;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define BRCMF_ENUM_DEF(id, val) \
|
||||
{ val, #id },
|
||||
|
||||
/* array for mapping code to event name */
|
||||
static struct brcmf_fweh_event_name fweh_event_names[] = {
|
||||
BRCMF_FWEH_EVENT_ENUM_DEFLIST
|
||||
};
|
||||
#undef BRCMF_ENUM_DEF
|
||||
|
||||
/**
|
||||
* brcmf_fweh_event_name() - returns name for given event code.
|
||||
*
|
||||
* @code: code to lookup.
|
||||
*/
|
||||
static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
|
||||
if (fweh_event_names[i].code == code)
|
||||
return fweh_event_names[i].name;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
#else
|
||||
static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
{
|
||||
return "nodebug";
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* brcmf_fweh_queue_event() - create and queue event.
|
||||
*
|
||||
* @fweh: firmware event handling info.
|
||||
* @event: event queue entry.
|
||||
*/
|
||||
static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
|
||||
struct brcmf_fweh_queue_item *event)
|
||||
{
|
||||
ulong flags;
|
||||
|
||||
spin_lock_irqsave(&fweh->evt_q_lock, flags);
|
||||
list_add_tail(&event->q, &fweh->event_q);
|
||||
spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
|
||||
schedule_work(&fweh->event_work);
|
||||
}
|
||||
|
||||
static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
|
||||
enum brcmf_fweh_event_code code,
|
||||
struct brcmf_event_msg *emsg,
|
||||
void *data)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (ifp) {
|
||||
fweh = &ifp->drvr->fweh;
|
||||
|
||||
/* handle the event if valid interface and handler */
|
||||
if (fweh->evt_handler[code])
|
||||
err = fweh->evt_handler[code](ifp, emsg, data);
|
||||
else
|
||||
brcmf_err("unhandled event %d ignored\n", code);
|
||||
} else {
|
||||
brcmf_err("no interface object\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_handle_if_event() - handle IF event.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @item: queue entry.
|
||||
* @ifpp: interface object (may change upon ADD action).
|
||||
*/
|
||||
static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||
struct brcmf_event_msg *emsg,
|
||||
void *data)
|
||||
{
|
||||
struct brcmf_if_event *ifevent = data;
|
||||
struct brcmf_if *ifp;
|
||||
int err = 0;
|
||||
|
||||
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
|
||||
ifevent->action, ifevent->ifidx, ifevent->bssidx,
|
||||
ifevent->flags, ifevent->role);
|
||||
|
||||
/* The P2P Device interface event must not be ignored
|
||||
* contrary to what firmware tells us. The only way to
|
||||
* distinguish the P2P Device is by looking at the ifidx
|
||||
* and bssidx received.
|
||||
*/
|
||||
if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
|
||||
(ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
|
||||
brcmf_dbg(EVENT, "event can be ignored\n");
|
||||
return;
|
||||
}
|
||||
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
||||
brcmf_err("invalid interface index: %u\n",
|
||||
ifevent->ifidx);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->bssidx];
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||
emsg->addr);
|
||||
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
|
||||
emsg->ifname, emsg->addr);
|
||||
if (IS_ERR(ifp))
|
||||
return;
|
||||
brcmf_fws_add_interface(ifp);
|
||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||
if (brcmf_net_attach(ifp, false) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifp && ifevent->action == BRCMF_E_IF_CHANGE)
|
||||
brcmf_fws_reset_interface(ifp);
|
||||
|
||||
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
|
||||
|
||||
if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
|
||||
brcmf_fws_del_interface(ifp);
|
||||
brcmf_del_if(drvr, ifevent->bssidx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_dequeue_event() - get event from the queue.
|
||||
*
|
||||
* @fweh: firmware event handling info.
|
||||
*/
|
||||
static struct brcmf_fweh_queue_item *
|
||||
brcmf_fweh_dequeue_event(struct brcmf_fweh_info *fweh)
|
||||
{
|
||||
struct brcmf_fweh_queue_item *event = NULL;
|
||||
ulong flags;
|
||||
|
||||
spin_lock_irqsave(&fweh->evt_q_lock, flags);
|
||||
if (!list_empty(&fweh->event_q)) {
|
||||
event = list_first_entry(&fweh->event_q,
|
||||
struct brcmf_fweh_queue_item, q);
|
||||
list_del(&event->q);
|
||||
}
|
||||
spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_event_worker() - firmware event worker.
|
||||
*
|
||||
* @work: worker object.
|
||||
*/
|
||||
static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_pub *drvr;
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_fweh_info *fweh;
|
||||
struct brcmf_fweh_queue_item *event;
|
||||
int err = 0;
|
||||
struct brcmf_event_msg_be *emsg_be;
|
||||
struct brcmf_event_msg emsg;
|
||||
|
||||
fweh = container_of(work, struct brcmf_fweh_info, event_work);
|
||||
drvr = container_of(fweh, struct brcmf_pub, fweh);
|
||||
|
||||
while ((event = brcmf_fweh_dequeue_event(fweh))) {
|
||||
brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
|
||||
brcmf_fweh_event_name(event->code), event->code,
|
||||
event->emsg.ifidx, event->emsg.bsscfgidx,
|
||||
event->emsg.addr);
|
||||
|
||||
/* convert event message */
|
||||
emsg_be = &event->emsg;
|
||||
emsg.version = be16_to_cpu(emsg_be->version);
|
||||
emsg.flags = be16_to_cpu(emsg_be->flags);
|
||||
emsg.event_code = event->code;
|
||||
emsg.status = be32_to_cpu(emsg_be->status);
|
||||
emsg.reason = be32_to_cpu(emsg_be->reason);
|
||||
emsg.auth_type = be32_to_cpu(emsg_be->auth_type);
|
||||
emsg.datalen = be32_to_cpu(emsg_be->datalen);
|
||||
memcpy(emsg.addr, emsg_be->addr, ETH_ALEN);
|
||||
memcpy(emsg.ifname, emsg_be->ifname, sizeof(emsg.ifname));
|
||||
emsg.ifidx = emsg_be->ifidx;
|
||||
emsg.bsscfgidx = emsg_be->bsscfgidx;
|
||||
|
||||
brcmf_dbg(EVENT, " version %u flags %u status %u reason %u\n",
|
||||
emsg.version, emsg.flags, emsg.status, emsg.reason);
|
||||
brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
|
||||
min_t(u32, emsg.datalen, 64),
|
||||
"event payload, len=%d\n", emsg.datalen);
|
||||
|
||||
/* special handling of interface event */
|
||||
if (event->code == BRCMF_E_IF) {
|
||||
brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
|
||||
goto event_free;
|
||||
}
|
||||
|
||||
if ((event->code == BRCMF_E_TDLS_PEER_EVENT) &&
|
||||
(emsg.bsscfgidx == 1))
|
||||
ifp = drvr->iflist[0];
|
||||
else
|
||||
ifp = drvr->iflist[emsg.bsscfgidx];
|
||||
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||
event->data);
|
||||
if (err) {
|
||||
brcmf_err("event handler failed (%d)\n",
|
||||
event->code);
|
||||
err = 0;
|
||||
}
|
||||
event_free:
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_attach() - initialize firmware event handling.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
*/
|
||||
void brcmf_fweh_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
INIT_WORK(&fweh->event_work, brcmf_fweh_event_worker);
|
||||
spin_lock_init(&fweh->evt_q_lock);
|
||||
INIT_LIST_HEAD(&fweh->event_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_detach() - cleanup firmware event handling.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
*/
|
||||
void brcmf_fweh_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
struct brcmf_if *ifp = drvr->iflist[0];
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
if (ifp) {
|
||||
/* clear all events */
|
||||
memset(eventmask, 0, BRCMF_EVENTING_MASK_LEN);
|
||||
(void)brcmf_fil_iovar_data_set(ifp, "event_msgs",
|
||||
eventmask,
|
||||
BRCMF_EVENTING_MASK_LEN);
|
||||
}
|
||||
/* cancel the worker */
|
||||
cancel_work_sync(&fweh->event_work);
|
||||
WARN_ON(!list_empty(&fweh->event_q));
|
||||
memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_register() - register handler for given event code.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @code: event code.
|
||||
* @handler: handler for the given event code.
|
||||
*/
|
||||
int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
|
||||
brcmf_fweh_handler_t handler)
|
||||
{
|
||||
if (drvr->fweh.evt_handler[code]) {
|
||||
brcmf_err("event code %d already registered\n", code);
|
||||
return -ENOSPC;
|
||||
}
|
||||
drvr->fweh.evt_handler[code] = handler;
|
||||
brcmf_dbg(TRACE, "event handler registered for %s\n",
|
||||
brcmf_fweh_event_name(code));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_unregister() - remove handler for given code.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @code: event code.
|
||||
*/
|
||||
void brcmf_fweh_unregister(struct brcmf_pub *drvr,
|
||||
enum brcmf_fweh_event_code code)
|
||||
{
|
||||
brcmf_dbg(TRACE, "event handler cleared for %s\n",
|
||||
brcmf_fweh_event_name(code));
|
||||
drvr->fweh.evt_handler[code] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_activate_events() - enables firmware events registered.
|
||||
*
|
||||
* @ifp: primary interface object.
|
||||
*/
|
||||
int brcmf_fweh_activate_events(struct brcmf_if *ifp)
|
||||
{
|
||||
int i, err;
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
for (i = 0; i < BRCMF_E_LAST; i++) {
|
||||
if (ifp->drvr->fweh.evt_handler[i]) {
|
||||
brcmf_dbg(EVENT, "enable event %s\n",
|
||||
brcmf_fweh_event_name(i));
|
||||
setbit(eventmask, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* want to handle IF event as well */
|
||||
brcmf_dbg(EVENT, "enable event IF\n");
|
||||
setbit(eventmask, BRCMF_E_IF);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "event_msgs",
|
||||
eventmask, BRCMF_EVENTING_MASK_LEN);
|
||||
if (err)
|
||||
brcmf_err("Set event_msgs error (%d)\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_process_event() - process skb as firmware event.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @event_packet: event packet to process.
|
||||
*
|
||||
* If the packet buffer contains a firmware event message it will
|
||||
* dispatch the event to a registered handler (using worker).
|
||||
*/
|
||||
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||
struct brcmf_event *event_packet)
|
||||
{
|
||||
enum brcmf_fweh_event_code code;
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
struct brcmf_fweh_queue_item *event;
|
||||
gfp_t alloc_flag = GFP_KERNEL;
|
||||
void *data;
|
||||
u32 datalen;
|
||||
|
||||
/* get event info */
|
||||
code = get_unaligned_be32(&event_packet->msg.event_type);
|
||||
datalen = get_unaligned_be32(&event_packet->msg.datalen);
|
||||
data = &event_packet[1];
|
||||
|
||||
if (code >= BRCMF_E_LAST)
|
||||
return;
|
||||
|
||||
if (code != BRCMF_E_IF && !fweh->evt_handler[code])
|
||||
return;
|
||||
|
||||
if (in_interrupt())
|
||||
alloc_flag = GFP_ATOMIC;
|
||||
|
||||
event = kzalloc(sizeof(*event) + datalen, alloc_flag);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->code = code;
|
||||
event->ifidx = event_packet->msg.ifidx;
|
||||
|
||||
/* use memcpy to get aligned event message */
|
||||
memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
|
||||
memcpy(event->data, data, datalen);
|
||||
memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
|
||||
|
||||
brcmf_fweh_queue_event(fweh, event);
|
||||
}
|
||||
284
drivers/net/wireless/brcm80211/brcmfmac/fweh.h
Normal file
284
drivers/net/wireless/brcm80211/brcmfmac/fweh.h
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FWEH_H_
|
||||
#define FWEH_H_
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
/* formward declarations */
|
||||
struct brcmf_pub;
|
||||
struct brcmf_if;
|
||||
struct brcmf_cfg80211_info;
|
||||
struct brcmf_event;
|
||||
|
||||
/* list of firmware events */
|
||||
#define BRCMF_FWEH_EVENT_ENUM_DEFLIST \
|
||||
BRCMF_ENUM_DEF(SET_SSID, 0) \
|
||||
BRCMF_ENUM_DEF(JOIN, 1) \
|
||||
BRCMF_ENUM_DEF(START, 2) \
|
||||
BRCMF_ENUM_DEF(AUTH, 3) \
|
||||
BRCMF_ENUM_DEF(AUTH_IND, 4) \
|
||||
BRCMF_ENUM_DEF(DEAUTH, 5) \
|
||||
BRCMF_ENUM_DEF(DEAUTH_IND, 6) \
|
||||
BRCMF_ENUM_DEF(ASSOC, 7) \
|
||||
BRCMF_ENUM_DEF(ASSOC_IND, 8) \
|
||||
BRCMF_ENUM_DEF(REASSOC, 9) \
|
||||
BRCMF_ENUM_DEF(REASSOC_IND, 10) \
|
||||
BRCMF_ENUM_DEF(DISASSOC, 11) \
|
||||
BRCMF_ENUM_DEF(DISASSOC_IND, 12) \
|
||||
BRCMF_ENUM_DEF(QUIET_START, 13) \
|
||||
BRCMF_ENUM_DEF(QUIET_END, 14) \
|
||||
BRCMF_ENUM_DEF(BEACON_RX, 15) \
|
||||
BRCMF_ENUM_DEF(LINK, 16) \
|
||||
BRCMF_ENUM_DEF(MIC_ERROR, 17) \
|
||||
BRCMF_ENUM_DEF(NDIS_LINK, 18) \
|
||||
BRCMF_ENUM_DEF(ROAM, 19) \
|
||||
BRCMF_ENUM_DEF(TXFAIL, 20) \
|
||||
BRCMF_ENUM_DEF(PMKID_CACHE, 21) \
|
||||
BRCMF_ENUM_DEF(RETROGRADE_TSF, 22) \
|
||||
BRCMF_ENUM_DEF(PRUNE, 23) \
|
||||
BRCMF_ENUM_DEF(AUTOAUTH, 24) \
|
||||
BRCMF_ENUM_DEF(EAPOL_MSG, 25) \
|
||||
BRCMF_ENUM_DEF(SCAN_COMPLETE, 26) \
|
||||
BRCMF_ENUM_DEF(ADDTS_IND, 27) \
|
||||
BRCMF_ENUM_DEF(DELTS_IND, 28) \
|
||||
BRCMF_ENUM_DEF(BCNSENT_IND, 29) \
|
||||
BRCMF_ENUM_DEF(BCNRX_MSG, 30) \
|
||||
BRCMF_ENUM_DEF(BCNLOST_MSG, 31) \
|
||||
BRCMF_ENUM_DEF(ROAM_PREP, 32) \
|
||||
BRCMF_ENUM_DEF(PFN_NET_FOUND, 33) \
|
||||
BRCMF_ENUM_DEF(PFN_NET_LOST, 34) \
|
||||
BRCMF_ENUM_DEF(RESET_COMPLETE, 35) \
|
||||
BRCMF_ENUM_DEF(JOIN_START, 36) \
|
||||
BRCMF_ENUM_DEF(ROAM_START, 37) \
|
||||
BRCMF_ENUM_DEF(ASSOC_START, 38) \
|
||||
BRCMF_ENUM_DEF(IBSS_ASSOC, 39) \
|
||||
BRCMF_ENUM_DEF(RADIO, 40) \
|
||||
BRCMF_ENUM_DEF(PSM_WATCHDOG, 41) \
|
||||
BRCMF_ENUM_DEF(PROBREQ_MSG, 44) \
|
||||
BRCMF_ENUM_DEF(SCAN_CONFIRM_IND, 45) \
|
||||
BRCMF_ENUM_DEF(PSK_SUP, 46) \
|
||||
BRCMF_ENUM_DEF(COUNTRY_CODE_CHANGED, 47) \
|
||||
BRCMF_ENUM_DEF(EXCEEDED_MEDIUM_TIME, 48) \
|
||||
BRCMF_ENUM_DEF(ICV_ERROR, 49) \
|
||||
BRCMF_ENUM_DEF(UNICAST_DECODE_ERROR, 50) \
|
||||
BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
|
||||
BRCMF_ENUM_DEF(TRACE, 52) \
|
||||
BRCMF_ENUM_DEF(IF, 54) \
|
||||
BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
|
||||
BRCMF_ENUM_DEF(RSSI, 56) \
|
||||
BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
|
||||
BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
|
||||
BRCMF_ENUM_DEF(PRE_ASSOC_IND, 61) \
|
||||
BRCMF_ENUM_DEF(PRE_REASSOC_IND, 62) \
|
||||
BRCMF_ENUM_DEF(CHANNEL_ADOPTED, 63) \
|
||||
BRCMF_ENUM_DEF(AP_STARTED, 64) \
|
||||
BRCMF_ENUM_DEF(DFS_AP_STOP, 65) \
|
||||
BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
|
||||
BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
|
||||
BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \
|
||||
BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
|
||||
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
|
||||
BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
|
||||
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
|
||||
BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
|
||||
|
||||
#define BRCMF_ENUM_DEF(id, val) \
|
||||
BRCMF_E_##id = (val),
|
||||
|
||||
/* firmware event codes sent by the dongle */
|
||||
enum brcmf_fweh_event_code {
|
||||
BRCMF_FWEH_EVENT_ENUM_DEFLIST
|
||||
BRCMF_E_LAST
|
||||
};
|
||||
#undef BRCMF_ENUM_DEF
|
||||
|
||||
#define BRCMF_EVENTING_MASK_LEN DIV_ROUND_UP(BRCMF_E_LAST, 8)
|
||||
|
||||
/* flags field values in struct brcmf_event_msg */
|
||||
#define BRCMF_EVENT_MSG_LINK 0x01
|
||||
#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
|
||||
#define BRCMF_EVENT_MSG_GROUP 0x04
|
||||
|
||||
/* status field values in struct brcmf_event_msg */
|
||||
#define BRCMF_E_STATUS_SUCCESS 0
|
||||
#define BRCMF_E_STATUS_FAIL 1
|
||||
#define BRCMF_E_STATUS_TIMEOUT 2
|
||||
#define BRCMF_E_STATUS_NO_NETWORKS 3
|
||||
#define BRCMF_E_STATUS_ABORT 4
|
||||
#define BRCMF_E_STATUS_NO_ACK 5
|
||||
#define BRCMF_E_STATUS_UNSOLICITED 6
|
||||
#define BRCMF_E_STATUS_ATTEMPT 7
|
||||
#define BRCMF_E_STATUS_PARTIAL 8
|
||||
#define BRCMF_E_STATUS_NEWSCAN 9
|
||||
#define BRCMF_E_STATUS_NEWASSOC 10
|
||||
#define BRCMF_E_STATUS_11HQUIET 11
|
||||
#define BRCMF_E_STATUS_SUPPRESS 12
|
||||
#define BRCMF_E_STATUS_NOCHANS 13
|
||||
#define BRCMF_E_STATUS_CS_ABORT 15
|
||||
#define BRCMF_E_STATUS_ERROR 16
|
||||
|
||||
/* reason field values in struct brcmf_event_msg */
|
||||
#define BRCMF_E_REASON_INITIAL_ASSOC 0
|
||||
#define BRCMF_E_REASON_LOW_RSSI 1
|
||||
#define BRCMF_E_REASON_DEAUTH 2
|
||||
#define BRCMF_E_REASON_DISASSOC 3
|
||||
#define BRCMF_E_REASON_BCNS_LOST 4
|
||||
#define BRCMF_E_REASON_MINTXRATE 9
|
||||
#define BRCMF_E_REASON_TXFAIL 10
|
||||
|
||||
#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4
|
||||
#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
|
||||
#define BRCMF_E_REASON_DIRECTED_ROAM 6
|
||||
#define BRCMF_E_REASON_TSPEC_REJECTED 7
|
||||
#define BRCMF_E_REASON_BETTER_AP 8
|
||||
|
||||
#define BRCMF_E_REASON_TDLS_PEER_DISCOVERED 0
|
||||
#define BRCMF_E_REASON_TDLS_PEER_CONNECTED 1
|
||||
#define BRCMF_E_REASON_TDLS_PEER_DISCONNECTED 2
|
||||
|
||||
/* action field values for brcmf_ifevent */
|
||||
#define BRCMF_E_IF_ADD 1
|
||||
#define BRCMF_E_IF_DEL 2
|
||||
#define BRCMF_E_IF_CHANGE 3
|
||||
|
||||
/* flag field values for brcmf_ifevent */
|
||||
#define BRCMF_E_IF_FLAG_NOIF 1
|
||||
|
||||
/* role field values for brcmf_ifevent */
|
||||
#define BRCMF_E_IF_ROLE_STA 0
|
||||
#define BRCMF_E_IF_ROLE_AP 1
|
||||
#define BRCMF_E_IF_ROLE_WDS 2
|
||||
#define BRCMF_E_IF_ROLE_P2P_GO 3
|
||||
#define BRCMF_E_IF_ROLE_P2P_CLIENT 4
|
||||
|
||||
/**
|
||||
* definitions for event packet validation.
|
||||
*/
|
||||
#define BRCMF_EVENT_OUI_OFFSET 19
|
||||
#define BRCM_OUI "\x00\x10\x18"
|
||||
#define DOT11_OUI_LEN 3
|
||||
#define BCMILCP_BCM_SUBTYPE_EVENT 1
|
||||
|
||||
|
||||
/**
|
||||
* struct brcmf_event_msg - firmware event message.
|
||||
*
|
||||
* @version: version information.
|
||||
* @flags: event flags.
|
||||
* @event_code: firmware event code.
|
||||
* @status: status information.
|
||||
* @reason: reason code.
|
||||
* @auth_type: authentication type.
|
||||
* @datalen: lenght of event data buffer.
|
||||
* @addr: ether address.
|
||||
* @ifname: interface name.
|
||||
* @ifidx: interface index.
|
||||
* @bsscfgidx: bsscfg index.
|
||||
*/
|
||||
struct brcmf_event_msg {
|
||||
u16 version;
|
||||
u16 flags;
|
||||
u32 event_code;
|
||||
u32 status;
|
||||
u32 reason;
|
||||
s32 auth_type;
|
||||
u32 datalen;
|
||||
u8 addr[ETH_ALEN];
|
||||
char ifname[IFNAMSIZ];
|
||||
u8 ifidx;
|
||||
u8 bsscfgidx;
|
||||
};
|
||||
|
||||
struct brcmf_if_event {
|
||||
u8 ifidx;
|
||||
u8 action;
|
||||
u8 flags;
|
||||
u8 bssidx;
|
||||
u8 role;
|
||||
};
|
||||
|
||||
typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* struct brcmf_fweh_info - firmware event handling information.
|
||||
*
|
||||
* @event_work: event worker.
|
||||
* @evt_q_lock: lock for event queue protection.
|
||||
* @event_q: event queue.
|
||||
* @evt_handler: registered event handlers.
|
||||
*/
|
||||
struct brcmf_fweh_info {
|
||||
struct work_struct event_work;
|
||||
spinlock_t evt_q_lock;
|
||||
struct list_head event_q;
|
||||
int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data);
|
||||
};
|
||||
|
||||
void brcmf_fweh_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_fweh_detach(struct brcmf_pub *drvr);
|
||||
int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
|
||||
int (*handler)(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data));
|
||||
void brcmf_fweh_unregister(struct brcmf_pub *drvr,
|
||||
enum brcmf_fweh_event_code code);
|
||||
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
|
||||
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||
struct brcmf_event *event_packet);
|
||||
|
||||
static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_event *event_packet;
|
||||
u8 *data;
|
||||
u16 usr_stype;
|
||||
|
||||
/* only process events when protocol matches */
|
||||
if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
|
||||
return;
|
||||
|
||||
/* check for BRCM oui match */
|
||||
event_packet = (struct brcmf_event *)skb_mac_header(skb);
|
||||
data = (u8 *)event_packet;
|
||||
data += BRCMF_EVENT_OUI_OFFSET;
|
||||
if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN))
|
||||
return;
|
||||
|
||||
/* final match on usr_subtype */
|
||||
data += DOT11_OUI_LEN;
|
||||
usr_stype = get_unaligned_be16(data);
|
||||
if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
|
||||
return;
|
||||
|
||||
brcmf_fweh_process_event(drvr, event_packet);
|
||||
}
|
||||
|
||||
#endif /* FWEH_H_ */
|
||||
348
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
Normal file
348
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* FWIL is the Firmware Interface Layer. In this module the support functions
|
||||
* are located to set and get variables to and from the firmware.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "tracepoint.h"
|
||||
#include "fwil.h"
|
||||
#include "proto.h"
|
||||
|
||||
|
||||
#define MAX_HEX_DUMP_LEN 64
|
||||
|
||||
|
||||
static s32
|
||||
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
s32 err;
|
||||
|
||||
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
|
||||
brcmf_err("bus is down. we have nothing to do.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (data != NULL)
|
||||
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
|
||||
if (set)
|
||||
err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
|
||||
else
|
||||
err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
|
||||
|
||||
if (err >= 0)
|
||||
err = 0;
|
||||
else
|
||||
brcmf_dbg(FIL, "Failed err=%d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
|
||||
{
|
||||
s32 err;
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
|
||||
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
|
||||
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
|
||||
{
|
||||
s32 err;
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
|
||||
|
||||
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
|
||||
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
s32
|
||||
brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
|
||||
{
|
||||
s32 err;
|
||||
__le32 data_le = cpu_to_le32(data);
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
|
||||
{
|
||||
s32 err;
|
||||
__le32 data_le = cpu_to_le32(*data);
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
*data = le32_to_cpu(data_le);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32
|
||||
brcmf_create_iovar(char *name, const char *data, u32 datalen,
|
||||
char *buf, u32 buflen)
|
||||
{
|
||||
u32 len;
|
||||
|
||||
len = strlen(name) + 1;
|
||||
|
||||
if ((len + datalen) > buflen)
|
||||
return 0;
|
||||
|
||||
memcpy(buf, name, len);
|
||||
|
||||
/* append data onto the end of the name string */
|
||||
if (data && datalen)
|
||||
memcpy(&buf[len], data, datalen);
|
||||
|
||||
return len + datalen;
|
||||
}
|
||||
|
||||
|
||||
s32
|
||||
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
|
||||
u32 len)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
s32 err;
|
||||
u32 buflen;
|
||||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
|
||||
|
||||
buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
|
||||
sizeof(drvr->proto_buf));
|
||||
if (buflen) {
|
||||
err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
|
||||
buflen, true);
|
||||
} else {
|
||||
err = -EPERM;
|
||||
brcmf_err("Creating iovar failed\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
return err;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||
u32 len)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
s32 err;
|
||||
u32 buflen;
|
||||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
|
||||
sizeof(drvr->proto_buf));
|
||||
if (buflen) {
|
||||
err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
|
||||
buflen, false);
|
||||
if (err == 0)
|
||||
memcpy(data, drvr->proto_buf, len);
|
||||
} else {
|
||||
err = -EPERM;
|
||||
brcmf_err("Creating iovar failed\n");
|
||||
}
|
||||
|
||||
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
return err;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
|
||||
{
|
||||
__le32 data_le = cpu_to_le32(data);
|
||||
|
||||
return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
|
||||
{
|
||||
__le32 data_le = cpu_to_le32(*data);
|
||||
s32 err;
|
||||
|
||||
err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
|
||||
if (err == 0)
|
||||
*data = le32_to_cpu(data_le);
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32
|
||||
brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
|
||||
u32 buflen)
|
||||
{
|
||||
const s8 *prefix = "bsscfg:";
|
||||
s8 *p;
|
||||
u32 prefixlen;
|
||||
u32 namelen;
|
||||
u32 iolen;
|
||||
__le32 bssidx_le;
|
||||
|
||||
if (bssidx == 0)
|
||||
return brcmf_create_iovar(name, data, datalen, buf, buflen);
|
||||
|
||||
prefixlen = strlen(prefix);
|
||||
namelen = strlen(name) + 1; /* lengh of iovar name + null */
|
||||
iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
|
||||
|
||||
if (buflen < iolen) {
|
||||
brcmf_err("buffer is too short\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
|
||||
/* copy prefix, no null */
|
||||
memcpy(p, prefix, prefixlen);
|
||||
p += prefixlen;
|
||||
|
||||
/* copy iovar name including null */
|
||||
memcpy(p, name, namelen);
|
||||
p += namelen;
|
||||
|
||||
/* bss config index as first data */
|
||||
bssidx_le = cpu_to_le32(bssidx);
|
||||
memcpy(p, &bssidx_le, sizeof(bssidx_le));
|
||||
p += sizeof(bssidx_le);
|
||||
|
||||
/* parameter buffer follows */
|
||||
if (datalen)
|
||||
memcpy(p, data, datalen);
|
||||
|
||||
return iolen;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
|
||||
void *data, u32 len)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
s32 err;
|
||||
u32 buflen;
|
||||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
|
||||
|
||||
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
|
||||
drvr->proto_buf, sizeof(drvr->proto_buf));
|
||||
if (buflen) {
|
||||
err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
|
||||
buflen, true);
|
||||
} else {
|
||||
err = -EPERM;
|
||||
brcmf_err("Creating bsscfg failed\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
return err;
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
|
||||
void *data, u32 len)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
s32 err;
|
||||
u32 buflen;
|
||||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
|
||||
drvr->proto_buf, sizeof(drvr->proto_buf));
|
||||
if (buflen) {
|
||||
err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
|
||||
buflen, false);
|
||||
if (err == 0)
|
||||
memcpy(data, drvr->proto_buf, len);
|
||||
} else {
|
||||
err = -EPERM;
|
||||
brcmf_err("Creating bsscfg failed\n");
|
||||
}
|
||||
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
|
||||
{
|
||||
__le32 data_le = cpu_to_le32(data);
|
||||
|
||||
return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
|
||||
sizeof(data_le));
|
||||
}
|
||||
|
||||
s32
|
||||
brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
|
||||
{
|
||||
__le32 data_le = cpu_to_le32(*data);
|
||||
s32 err;
|
||||
|
||||
err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
|
||||
sizeof(data_le));
|
||||
if (err == 0)
|
||||
*data = le32_to_cpu(data_le);
|
||||
return err;
|
||||
}
|
||||
100
drivers/net/wireless/brcm80211/brcmfmac/fwil.h
Normal file
100
drivers/net/wireless/brcm80211/brcmfmac/fwil.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _fwil_h_
|
||||
#define _fwil_h_
|
||||
|
||||
/*******************************************************************************
|
||||
* Dongle command codes that are interpreted by firmware
|
||||
******************************************************************************/
|
||||
#define BRCMF_C_GET_VERSION 1
|
||||
#define BRCMF_C_UP 2
|
||||
#define BRCMF_C_DOWN 3
|
||||
#define BRCMF_C_SET_PROMISC 10
|
||||
#define BRCMF_C_GET_RATE 12
|
||||
#define BRCMF_C_GET_INFRA 19
|
||||
#define BRCMF_C_SET_INFRA 20
|
||||
#define BRCMF_C_GET_AUTH 21
|
||||
#define BRCMF_C_SET_AUTH 22
|
||||
#define BRCMF_C_GET_BSSID 23
|
||||
#define BRCMF_C_GET_SSID 25
|
||||
#define BRCMF_C_SET_SSID 26
|
||||
#define BRCMF_C_TERMINATED 28
|
||||
#define BRCMF_C_GET_CHANNEL 29
|
||||
#define BRCMF_C_SET_CHANNEL 30
|
||||
#define BRCMF_C_GET_SRL 31
|
||||
#define BRCMF_C_SET_SRL 32
|
||||
#define BRCMF_C_GET_LRL 33
|
||||
#define BRCMF_C_SET_LRL 34
|
||||
#define BRCMF_C_GET_RADIO 37
|
||||
#define BRCMF_C_SET_RADIO 38
|
||||
#define BRCMF_C_GET_PHYTYPE 39
|
||||
#define BRCMF_C_SET_KEY 45
|
||||
#define BRCMF_C_SET_PASSIVE_SCAN 49
|
||||
#define BRCMF_C_SCAN 50
|
||||
#define BRCMF_C_SCAN_RESULTS 51
|
||||
#define BRCMF_C_DISASSOC 52
|
||||
#define BRCMF_C_REASSOC 53
|
||||
#define BRCMF_C_SET_ROAM_TRIGGER 55
|
||||
#define BRCMF_C_SET_ROAM_DELTA 57
|
||||
#define BRCMF_C_GET_BCNPRD 75
|
||||
#define BRCMF_C_SET_BCNPRD 76
|
||||
#define BRCMF_C_GET_DTIMPRD 77
|
||||
#define BRCMF_C_SET_DTIMPRD 78
|
||||
#define BRCMF_C_SET_COUNTRY 84
|
||||
#define BRCMF_C_GET_PM 85
|
||||
#define BRCMF_C_SET_PM 86
|
||||
#define BRCMF_C_GET_CURR_RATESET 114
|
||||
#define BRCMF_C_GET_AP 117
|
||||
#define BRCMF_C_SET_AP 118
|
||||
#define BRCMF_C_GET_RSSI 127
|
||||
#define BRCMF_C_GET_WSEC 133
|
||||
#define BRCMF_C_SET_WSEC 134
|
||||
#define BRCMF_C_GET_PHY_NOISE 135
|
||||
#define BRCMF_C_GET_BSS_INFO 136
|
||||
#define BRCMF_C_GET_BANDLIST 140
|
||||
#define BRCMF_C_SET_SCB_TIMEOUT 158
|
||||
#define BRCMF_C_GET_PHYLIST 180
|
||||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
||||
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
|
||||
#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201
|
||||
#define BRCMF_C_GET_VALID_CHANNELS 217
|
||||
#define BRCMF_C_GET_KEY_PRIMARY 235
|
||||
#define BRCMF_C_SET_KEY_PRIMARY 236
|
||||
#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258
|
||||
#define BRCMF_C_GET_VAR 262
|
||||
#define BRCMF_C_SET_VAR 263
|
||||
|
||||
s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
|
||||
s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
|
||||
s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
|
||||
s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
|
||||
|
||||
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
|
||||
u32 len);
|
||||
s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||
u32 len);
|
||||
s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data);
|
||||
s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data);
|
||||
|
||||
s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data,
|
||||
u32 len);
|
||||
s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||
u32 len);
|
||||
s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data);
|
||||
s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data);
|
||||
|
||||
#endif /* _fwil_h_ */
|
||||
487
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
Normal file
487
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FWIL_TYPES_H_
|
||||
#define FWIL_TYPES_H_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
|
||||
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
|
||||
|
||||
/* ARP Offload feature flags for arp_ol iovar */
|
||||
#define BRCMF_ARP_OL_AGENT 0x00000001
|
||||
#define BRCMF_ARP_OL_SNOOP 0x00000002
|
||||
#define BRCMF_ARP_OL_HOST_AUTO_REPLY 0x00000004
|
||||
#define BRCMF_ARP_OL_PEER_AUTO_REPLY 0x00000008
|
||||
|
||||
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
|
||||
#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
|
||||
|
||||
#define BRCMF_STA_ASSOC 0x10 /* Associated */
|
||||
|
||||
/* size of brcmf_scan_params not including variable length array */
|
||||
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
||||
|
||||
/* masks for channel and ssid count */
|
||||
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
|
||||
#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
|
||||
|
||||
/* primary (ie tx) key */
|
||||
#define BRCMF_PRIMARY_KEY (1 << 1)
|
||||
#define DOT11_BSSTYPE_ANY 2
|
||||
#define BRCMF_ESCAN_REQ_VERSION 1
|
||||
|
||||
#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
|
||||
|
||||
/* OBSS Coex Auto/On/Off */
|
||||
#define BRCMF_OBSS_COEX_AUTO (-1)
|
||||
#define BRCMF_OBSS_COEX_OFF 0
|
||||
#define BRCMF_OBSS_COEX_ON 1
|
||||
|
||||
/* WOWL bits */
|
||||
/* Wakeup on Magic packet: */
|
||||
#define WL_WOWL_MAGIC (1 << 0)
|
||||
/* Wakeup on Netpattern */
|
||||
#define WL_WOWL_NET (1 << 1)
|
||||
/* Wakeup on loss-of-link due to Disassoc/Deauth: */
|
||||
#define WL_WOWL_DIS (1 << 2)
|
||||
/* Wakeup on retrograde TSF: */
|
||||
#define WL_WOWL_RETR (1 << 3)
|
||||
/* Wakeup on loss of beacon: */
|
||||
#define WL_WOWL_BCN (1 << 4)
|
||||
/* Wakeup after test: */
|
||||
#define WL_WOWL_TST (1 << 5)
|
||||
/* Wakeup after PTK refresh: */
|
||||
#define WL_WOWL_M1 (1 << 6)
|
||||
/* Wakeup after receipt of EAP-Identity Req: */
|
||||
#define WL_WOWL_EAPID (1 << 7)
|
||||
/* Wakeind via PME(0) or GPIO(1): */
|
||||
#define WL_WOWL_PME_GPIO (1 << 8)
|
||||
/* need tkip phase 1 key to be updated by the driver: */
|
||||
#define WL_WOWL_NEEDTKIP1 (1 << 9)
|
||||
/* enable wakeup if GTK fails: */
|
||||
#define WL_WOWL_GTK_FAILURE (1 << 10)
|
||||
/* support extended magic packets: */
|
||||
#define WL_WOWL_EXTMAGPAT (1 << 11)
|
||||
/* support ARP/NS/keepalive offloading: */
|
||||
#define WL_WOWL_ARPOFFLOAD (1 << 12)
|
||||
/* read protocol version for EAPOL frames: */
|
||||
#define WL_WOWL_WPA2 (1 << 13)
|
||||
/* If the bit is set, use key rotaton: */
|
||||
#define WL_WOWL_KEYROT (1 << 14)
|
||||
/* If the bit is set, frm received was bcast frame: */
|
||||
#define WL_WOWL_BCAST (1 << 15)
|
||||
/* If the bit is set, scan offload is enabled: */
|
||||
#define WL_WOWL_SCANOL (1 << 16)
|
||||
/* Wakeup on tcpkeep alive timeout: */
|
||||
#define WL_WOWL_TCPKEEP_TIME (1 << 17)
|
||||
/* Wakeup on mDNS Conflict Resolution: */
|
||||
#define WL_WOWL_MDNS_CONFLICT (1 << 18)
|
||||
/* Wakeup on mDNS Service Connect: */
|
||||
#define WL_WOWL_MDNS_SERVICE (1 << 19)
|
||||
/* tcp keepalive got data: */
|
||||
#define WL_WOWL_TCPKEEP_DATA (1 << 20)
|
||||
/* Firmware died in wowl mode: */
|
||||
#define WL_WOWL_FW_HALT (1 << 21)
|
||||
/* Enable detection of radio button changes: */
|
||||
#define WL_WOWL_ENAB_HWRADIO (1 << 22)
|
||||
/* Offloads detected MIC failure(s): */
|
||||
#define WL_WOWL_MIC_FAIL (1 << 23)
|
||||
/* Wakeup in Unassociated state (Net/Magic Pattern): */
|
||||
#define WL_WOWL_UNASSOC (1 << 24)
|
||||
/* Wakeup if received matched secured pattern: */
|
||||
#define WL_WOWL_SECURE (1 << 25)
|
||||
/* Link Down indication in WoWL mode: */
|
||||
#define WL_WOWL_LINKDOWN (1 << 31)
|
||||
|
||||
/* join preference types for join_pref iovar */
|
||||
enum brcmf_join_pref_types {
|
||||
BRCMF_JOIN_PREF_RSSI = 1,
|
||||
BRCMF_JOIN_PREF_WPA,
|
||||
BRCMF_JOIN_PREF_BAND,
|
||||
BRCMF_JOIN_PREF_RSSI_DELTA,
|
||||
};
|
||||
|
||||
enum brcmf_fil_p2p_if_types {
|
||||
BRCMF_FIL_P2P_IF_CLIENT,
|
||||
BRCMF_FIL_P2P_IF_GO,
|
||||
BRCMF_FIL_P2P_IF_DYNBCN_GO,
|
||||
BRCMF_FIL_P2P_IF_DEV,
|
||||
};
|
||||
|
||||
struct brcmf_fil_p2p_if_le {
|
||||
u8 addr[ETH_ALEN];
|
||||
__le16 type;
|
||||
__le16 chspec;
|
||||
};
|
||||
|
||||
struct brcmf_fil_chan_info_le {
|
||||
__le32 hw_channel;
|
||||
__le32 target_channel;
|
||||
__le32 scan_channel;
|
||||
};
|
||||
|
||||
struct brcmf_fil_action_frame_le {
|
||||
u8 da[ETH_ALEN];
|
||||
__le16 len;
|
||||
__le32 packet_id;
|
||||
u8 data[BRCMF_FIL_ACTION_FRAME_SIZE];
|
||||
};
|
||||
|
||||
struct brcmf_fil_af_params_le {
|
||||
__le32 channel;
|
||||
__le32 dwell_time;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pad[2];
|
||||
struct brcmf_fil_action_frame_le action_frame;
|
||||
};
|
||||
|
||||
struct brcmf_fil_bss_enable_le {
|
||||
__le32 bsscfg_idx;
|
||||
__le32 enable;
|
||||
};
|
||||
|
||||
struct brcmf_fil_bwcap_le {
|
||||
__le32 band;
|
||||
__le32 bw_cap;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tdls_iovar - common structure for tdls iovars.
|
||||
*
|
||||
* @ea: ether address of peer station.
|
||||
* @mode: mode value depending on specific tdls iovar.
|
||||
* @chanspec: channel specification.
|
||||
* @pad: unused (for future use).
|
||||
*/
|
||||
struct brcmf_tdls_iovar_le {
|
||||
u8 ea[ETH_ALEN]; /* Station address */
|
||||
u8 mode; /* mode: depends on iovar */
|
||||
__le16 chanspec;
|
||||
__le32 pad; /* future */
|
||||
};
|
||||
|
||||
enum brcmf_tdls_manual_ep_ops {
|
||||
BRCMF_TDLS_MANUAL_EP_CREATE = 1,
|
||||
BRCMF_TDLS_MANUAL_EP_DELETE = 3,
|
||||
BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6
|
||||
};
|
||||
|
||||
/* Pattern matching filter. Specifies an offset within received packets to
|
||||
* start matching, the pattern to match, the size of the pattern, and a bitmask
|
||||
* that indicates which bits within the pattern should be matched.
|
||||
*/
|
||||
struct brcmf_pkt_filter_pattern_le {
|
||||
/*
|
||||
* Offset within received packet to start pattern matching.
|
||||
* Offset '0' is the first byte of the ethernet header.
|
||||
*/
|
||||
__le32 offset;
|
||||
/* Size of the pattern. Bitmask must be the same size.*/
|
||||
__le32 size_bytes;
|
||||
/*
|
||||
* Variable length mask and pattern data. mask starts at offset 0.
|
||||
* Pattern immediately follows mask.
|
||||
*/
|
||||
u8 mask_and_pattern[1];
|
||||
};
|
||||
|
||||
/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
|
||||
struct brcmf_pkt_filter_le {
|
||||
__le32 id; /* Unique filter id, specified by app. */
|
||||
__le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
|
||||
__le32 negate_match; /* Negate the result of filter matches */
|
||||
union { /* Filter definitions */
|
||||
struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */
|
||||
} u;
|
||||
};
|
||||
|
||||
/* IOVAR "pkt_filter_enable" parameter. */
|
||||
struct brcmf_pkt_filter_enable_le {
|
||||
__le32 id; /* Unique filter id */
|
||||
__le32 enable; /* Enable/disable bool */
|
||||
};
|
||||
|
||||
/* BSS info structure
|
||||
* Applications MUST CHECK ie_offset field and length field to access IEs and
|
||||
* next bss_info structure in a vector (in struct brcmf_scan_results)
|
||||
*/
|
||||
struct brcmf_bss_info_le {
|
||||
__le32 version; /* version field */
|
||||
__le32 length; /* byte length of data in this record,
|
||||
* starting at version and including IEs
|
||||
*/
|
||||
u8 BSSID[ETH_ALEN];
|
||||
__le16 beacon_period; /* units are Kusec */
|
||||
__le16 capability; /* Capability information */
|
||||
u8 SSID_len;
|
||||
u8 SSID[32];
|
||||
struct {
|
||||
__le32 count; /* # rates in this set */
|
||||
u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
|
||||
} rateset; /* supported rates */
|
||||
__le16 chanspec; /* chanspec for bss */
|
||||
__le16 atim_window; /* units are Kusec */
|
||||
u8 dtim_period; /* DTIM period */
|
||||
__le16 RSSI; /* receive signal strength (in dBm) */
|
||||
s8 phy_noise; /* noise (in dBm) */
|
||||
|
||||
u8 n_cap; /* BSS is 802.11N Capable */
|
||||
/* 802.11N BSS Capabilities (based on HT_CAP_*): */
|
||||
__le32 nbss_cap;
|
||||
u8 ctl_ch; /* 802.11N BSS control channel number */
|
||||
__le32 reserved32[1]; /* Reserved for expansion of BSS properties */
|
||||
u8 flags; /* flags */
|
||||
u8 reserved[3]; /* Reserved for expansion of BSS properties */
|
||||
u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
|
||||
|
||||
__le16 ie_offset; /* offset at which IEs start, from beginning */
|
||||
__le32 ie_length; /* byte length of Information Elements */
|
||||
__le16 SNR; /* average SNR of during frame reception */
|
||||
/* Add new fields here */
|
||||
/* variable length Information Elements */
|
||||
};
|
||||
|
||||
struct brcm_rateset_le {
|
||||
/* # rates in this set */
|
||||
__le32 count;
|
||||
/* rates in 500kbps units w/hi bit set if basic */
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET];
|
||||
};
|
||||
|
||||
struct brcmf_ssid {
|
||||
u32 SSID_len;
|
||||
unsigned char SSID[32];
|
||||
};
|
||||
|
||||
struct brcmf_ssid_le {
|
||||
__le32 SSID_len;
|
||||
unsigned char SSID[32];
|
||||
};
|
||||
|
||||
struct brcmf_scan_params_le {
|
||||
struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
|
||||
u8 bssid[ETH_ALEN]; /* default: bcast */
|
||||
s8 bss_type; /* default: any,
|
||||
* DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
|
||||
*/
|
||||
u8 scan_type; /* flags, 0 use default */
|
||||
__le32 nprobes; /* -1 use default, number of probes per channel */
|
||||
__le32 active_time; /* -1 use default, dwell time per channel for
|
||||
* active scanning
|
||||
*/
|
||||
__le32 passive_time; /* -1 use default, dwell time per channel
|
||||
* for passive scanning
|
||||
*/
|
||||
__le32 home_time; /* -1 use default, dwell time for the
|
||||
* home channel between channel scans
|
||||
*/
|
||||
__le32 channel_num; /* count of channels and ssids that follow
|
||||
*
|
||||
* low half is count of channels in
|
||||
* channel_list, 0 means default (use all
|
||||
* available channels)
|
||||
*
|
||||
* high half is entries in struct brcmf_ssid
|
||||
* array that follows channel_list, aligned for
|
||||
* s32 (4 bytes) meaning an odd channel count
|
||||
* implies a 2-byte pad between end of
|
||||
* channel_list and first ssid
|
||||
*
|
||||
* if ssid count is zero, single ssid in the
|
||||
* fixed parameter portion is assumed, otherwise
|
||||
* ssid in the fixed portion is ignored
|
||||
*/
|
||||
__le16 channel_list[1]; /* list of chanspecs */
|
||||
};
|
||||
|
||||
struct brcmf_scan_results {
|
||||
u32 buflen;
|
||||
u32 version;
|
||||
u32 count;
|
||||
struct brcmf_bss_info_le bss_info_le[];
|
||||
};
|
||||
|
||||
struct brcmf_escan_params_le {
|
||||
__le32 version;
|
||||
__le16 action;
|
||||
__le16 sync_id;
|
||||
struct brcmf_scan_params_le params_le;
|
||||
};
|
||||
|
||||
struct brcmf_escan_result_le {
|
||||
__le32 buflen;
|
||||
__le32 version;
|
||||
__le16 sync_id;
|
||||
__le16 bss_count;
|
||||
struct brcmf_bss_info_le bss_info_le;
|
||||
};
|
||||
|
||||
#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \
|
||||
sizeof(struct brcmf_bss_info_le))
|
||||
|
||||
/* used for association with a specific BSSID and chanspec list */
|
||||
struct brcmf_assoc_params_le {
|
||||
/* 00:00:00:00:00:00: broadcast scan */
|
||||
u8 bssid[ETH_ALEN];
|
||||
/* 0: all available channels, otherwise count of chanspecs in
|
||||
* chanspec_list */
|
||||
__le32 chanspec_num;
|
||||
/* list of chanspecs */
|
||||
__le16 chanspec_list[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct join_pref params - parameters for preferred join selection.
|
||||
*
|
||||
* @type: preference type (see enum brcmf_join_pref_types).
|
||||
* @len: length of bytes following (currently always 2).
|
||||
* @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA).
|
||||
* @band: band to which selection preference applies.
|
||||
* This is used if @type is BAND or RSSI_DELTA.
|
||||
*/
|
||||
struct brcmf_join_pref_params {
|
||||
u8 type;
|
||||
u8 len;
|
||||
u8 rssi_gain;
|
||||
u8 band;
|
||||
};
|
||||
|
||||
/* used for join with or without a specific bssid and channel list */
|
||||
struct brcmf_join_params {
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
struct brcmf_assoc_params_le params_le;
|
||||
};
|
||||
|
||||
/* scan params for extended join */
|
||||
struct brcmf_join_scan_params_le {
|
||||
u8 scan_type; /* 0 use default, active or passive scan */
|
||||
__le32 nprobes; /* -1 use default, nr of probes per channel */
|
||||
__le32 active_time; /* -1 use default, dwell time per channel for
|
||||
* active scanning
|
||||
*/
|
||||
__le32 passive_time; /* -1 use default, dwell time per channel
|
||||
* for passive scanning
|
||||
*/
|
||||
__le32 home_time; /* -1 use default, dwell time for the home
|
||||
* channel between channel scans
|
||||
*/
|
||||
};
|
||||
|
||||
/* extended join params */
|
||||
struct brcmf_ext_join_params_le {
|
||||
struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */
|
||||
struct brcmf_join_scan_params_le scan_le;
|
||||
struct brcmf_assoc_params_le assoc_le;
|
||||
};
|
||||
|
||||
struct brcmf_wsec_key {
|
||||
u32 index; /* key index */
|
||||
u32 len; /* key length */
|
||||
u8 data[WLAN_MAX_KEY_LEN]; /* key data */
|
||||
u32 pad_1[18];
|
||||
u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
|
||||
u32 flags; /* misc flags */
|
||||
u32 pad_2[3];
|
||||
u32 iv_initialized; /* has IV been initialized already? */
|
||||
u32 pad_3;
|
||||
/* Rx IV */
|
||||
struct {
|
||||
u32 hi; /* upper 32 bits of IV */
|
||||
u16 lo; /* lower 16 bits of IV */
|
||||
} rxiv;
|
||||
u32 pad_4[2];
|
||||
u8 ea[ETH_ALEN]; /* per station */
|
||||
};
|
||||
|
||||
/*
|
||||
* dongle requires same struct as above but with fields in little endian order
|
||||
*/
|
||||
struct brcmf_wsec_key_le {
|
||||
__le32 index; /* key index */
|
||||
__le32 len; /* key length */
|
||||
u8 data[WLAN_MAX_KEY_LEN]; /* key data */
|
||||
__le32 pad_1[18];
|
||||
__le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
|
||||
__le32 flags; /* misc flags */
|
||||
__le32 pad_2[3];
|
||||
__le32 iv_initialized; /* has IV been initialized already? */
|
||||
__le32 pad_3;
|
||||
/* Rx IV */
|
||||
struct {
|
||||
__le32 hi; /* upper 32 bits of IV */
|
||||
__le16 lo; /* lower 16 bits of IV */
|
||||
} rxiv;
|
||||
__le32 pad_4[2];
|
||||
u8 ea[ETH_ALEN]; /* per station */
|
||||
};
|
||||
|
||||
/* Used to get specific STA parameters */
|
||||
struct brcmf_scb_val_le {
|
||||
__le32 val;
|
||||
u8 ea[ETH_ALEN];
|
||||
};
|
||||
|
||||
/* channel encoding */
|
||||
struct brcmf_channel_info_le {
|
||||
__le32 hw_channel;
|
||||
__le32 target_channel;
|
||||
__le32 scan_channel;
|
||||
};
|
||||
|
||||
struct brcmf_sta_info_le {
|
||||
__le16 ver; /* version of this struct */
|
||||
__le16 len; /* length in bytes of this structure */
|
||||
__le16 cap; /* sta's advertised capabilities */
|
||||
__le32 flags; /* flags defined below */
|
||||
__le32 idle; /* time since data pkt rx'd from sta */
|
||||
u8 ea[ETH_ALEN]; /* Station address */
|
||||
__le32 count; /* # rates in this set */
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
/* w/hi bit set if basic */
|
||||
__le32 in; /* seconds elapsed since associated */
|
||||
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
__le32 tx_pkts; /* # of packets transmitted */
|
||||
__le32 tx_failures; /* # of packets failed */
|
||||
__le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
__le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
__le32 tx_rate; /* Rate of last successful tx frame */
|
||||
__le32 rx_rate; /* Rate of last successful rx frame */
|
||||
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
};
|
||||
|
||||
struct brcmf_chanspec_list {
|
||||
__le32 count; /* # of entries */
|
||||
__le32 element[1]; /* variable length uint32 list */
|
||||
};
|
||||
|
||||
/*
|
||||
* WLC_E_PROBRESP_MSG
|
||||
* WLC_E_P2P_PROBREQ_MSG
|
||||
* WLC_E_ACTION_FRAME_RX
|
||||
*/
|
||||
struct brcmf_rx_mgmt_data {
|
||||
__be16 version;
|
||||
__be16 chanspec;
|
||||
__be32 rssi;
|
||||
__be32 mactime;
|
||||
__be32 rate;
|
||||
};
|
||||
|
||||
#endif /* FWIL_TYPES_H_ */
|
||||
2270
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
Normal file
2270
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
Normal file
File diff suppressed because it is too large
Load diff
34
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
Normal file
34
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FWSIGNAL_H_
|
||||
#define FWSIGNAL_H_
|
||||
|
||||
int brcmf_fws_init(struct brcmf_pub *drvr);
|
||||
void brcmf_fws_deinit(struct brcmf_pub *drvr);
|
||||
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
|
||||
int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
struct sk_buff *skb);
|
||||
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
|
||||
void brcmf_fws_reset_interface(struct brcmf_if *ifp);
|
||||
void brcmf_fws_add_interface(struct brcmf_if *ifp);
|
||||
void brcmf_fws_del_interface(struct brcmf_if *ifp);
|
||||
void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
|
||||
void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
|
||||
|
||||
#endif /* FWSIGNAL_H_ */
|
||||
1496
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
Normal file
1496
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
Normal file
File diff suppressed because it is too large
Load diff
47
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
Normal file
47
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_MSGBUF_H
|
||||
#define BRCMFMAC_MSGBUF_H
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF
|
||||
|
||||
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 20
|
||||
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 256
|
||||
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 20
|
||||
#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 256
|
||||
#define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512
|
||||
|
||||
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40
|
||||
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE 32
|
||||
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE 24
|
||||
#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE 16
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32
|
||||
#define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48
|
||||
|
||||
|
||||
int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
|
||||
void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid);
|
||||
int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
|
||||
#else
|
||||
static inline int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr) {}
|
||||
#endif
|
||||
|
||||
#endif /* BRCMFMAC_MSGBUF_H */
|
||||
56
drivers/net/wireless/brcm80211/brcmfmac/of.c
Normal file
56
drivers/net/wireless/brcm80211/brcmfmac/of.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/platform_data/brcmfmac-sdio.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include "dhd_dbg.h"
|
||||
#include "sdio_host.h"
|
||||
|
||||
void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
struct device *dev = sdiodev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
int irq;
|
||||
u32 irqf;
|
||||
u32 val;
|
||||
|
||||
if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
|
||||
return;
|
||||
|
||||
sdiodev->pdata = devm_kzalloc(dev, sizeof(*sdiodev->pdata), GFP_KERNEL);
|
||||
if (!sdiodev->pdata)
|
||||
return;
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq) {
|
||||
brcmf_err("interrupt could not be mapped\n");
|
||||
devm_kfree(dev, sdiodev->pdata);
|
||||
return;
|
||||
}
|
||||
irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
|
||||
|
||||
sdiodev->pdata->oob_irq_supported = true;
|
||||
sdiodev->pdata->oob_irq_nr = irq;
|
||||
sdiodev->pdata->oob_irq_flags = irqf;
|
||||
|
||||
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
|
||||
sdiodev->pdata->drive_strength = val;
|
||||
}
|
||||
22
drivers/net/wireless/brcm80211/brcmfmac/of.h
Normal file
22
drivers/net/wireless/brcm80211/brcmfmac/of.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifdef CONFIG_OF
|
||||
void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev);
|
||||
#else
|
||||
static void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
2424
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Normal file
2424
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Normal file
File diff suppressed because it is too large
Load diff
183
drivers/net/wireless/brcm80211/brcmfmac/p2p.h
Normal file
183
drivers/net/wireless/brcm80211/brcmfmac/p2p.h
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef WL_CFGP2P_H_
|
||||
#define WL_CFGP2P_H_
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
struct brcmf_cfg80211_info;
|
||||
|
||||
/**
|
||||
* enum p2p_bss_type - different type of BSS configurations.
|
||||
*
|
||||
* @P2PAPI_BSSCFG_PRIMARY: maps to driver's primary bsscfg.
|
||||
* @P2PAPI_BSSCFG_DEVICE: maps to driver's P2P device discovery bsscfg.
|
||||
* @P2PAPI_BSSCFG_CONNECTION: maps to driver's P2P connection bsscfg.
|
||||
* @P2PAPI_BSSCFG_MAX: used for range checking.
|
||||
*/
|
||||
enum p2p_bss_type {
|
||||
P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
|
||||
P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
|
||||
P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */
|
||||
P2PAPI_BSSCFG_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_bss - peer-to-peer bss related information.
|
||||
*
|
||||
* @vif: virtual interface of this P2P bss.
|
||||
* @private_data: TBD
|
||||
*/
|
||||
struct p2p_bss {
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum brcmf_p2p_status - P2P specific dongle status.
|
||||
*
|
||||
* @BRCMF_P2P_STATUS_IF_ADD: peer-to-peer vif add sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_DEL: NOT-USED?
|
||||
* @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
|
||||
* @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
|
||||
* @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
|
||||
* @BRCMF_P2P_STATUS_SENDING_ACT_FRAME: In the process of sending action frame.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN: extra listen time for af tx.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME: waiting for action frame response.
|
||||
* @BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL: search channel for AF active.
|
||||
*/
|
||||
enum brcmf_p2p_status {
|
||||
BRCMF_P2P_STATUS_ENABLED,
|
||||
BRCMF_P2P_STATUS_IF_ADD,
|
||||
BRCMF_P2P_STATUS_IF_DEL,
|
||||
BRCMF_P2P_STATUS_IF_DELETING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_NOACK,
|
||||
BRCMF_P2P_STATUS_GO_NEG_PHASE,
|
||||
BRCMF_P2P_STATUS_DISCOVER_LISTEN,
|
||||
BRCMF_P2P_STATUS_SENDING_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL
|
||||
};
|
||||
|
||||
/**
|
||||
* struct afx_hdl - action frame off channel storage.
|
||||
*
|
||||
* @afx_work: worker thread for searching channel
|
||||
* @act_frm_scan: thread synchronizing struct.
|
||||
* @is_active: channel searching active.
|
||||
* @peer_chan: current channel.
|
||||
* @is_listen: sets mode for afx worker.
|
||||
* @my_listen_chan: this peers listen channel.
|
||||
* @peer_listen_chan: remote peers listen channel.
|
||||
* @tx_dst_addr: mac address where tx af should be sent to.
|
||||
*/
|
||||
struct afx_hdl {
|
||||
struct work_struct afx_work;
|
||||
struct completion act_frm_scan;
|
||||
bool is_active;
|
||||
s32 peer_chan;
|
||||
bool is_listen;
|
||||
u16 my_listen_chan;
|
||||
u16 peer_listen_chan;
|
||||
u8 tx_dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_p2p_info - p2p specific driver information.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
* @status: status of P2P (see enum brcmf_p2p_status).
|
||||
* @dev_addr: P2P device address.
|
||||
* @int_addr: P2P interface address.
|
||||
* @bss_idx: informate for P2P bss types.
|
||||
* @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @ssid: ssid for P2P GO.
|
||||
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @remain_on_channel: contains copy of struct used by cfg80211.
|
||||
* @remain_on_channel_cookie: cookie counter for remain on channel cmd
|
||||
* @next_af_subtype: expected action frame subtype.
|
||||
* @send_af_done: indication that action frame tx is complete.
|
||||
* @afx_hdl: action frame search handler info.
|
||||
* @af_sent_channel: channel action frame is sent.
|
||||
* @af_tx_sent_jiffies: jiffies time when af tx was transmitted.
|
||||
* @wait_next_af: thread synchronizing struct.
|
||||
* @gon_req_action: about to send go negotiation requets frame.
|
||||
* @block_gon_req_tx: drop tx go negotiation requets frame.
|
||||
*/
|
||||
struct brcmf_p2p_info {
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
unsigned long status;
|
||||
u8 dev_addr[ETH_ALEN];
|
||||
u8 int_addr[ETH_ALEN];
|
||||
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
|
||||
struct timer_list listen_timer;
|
||||
struct brcmf_ssid ssid;
|
||||
u8 listen_channel;
|
||||
struct ieee80211_channel remain_on_channel;
|
||||
u32 remain_on_channel_cookie;
|
||||
u8 next_af_subtype;
|
||||
struct completion send_af_done;
|
||||
struct afx_hdl afx_hdl;
|
||||
u32 af_sent_channel;
|
||||
unsigned long af_tx_sent_jiffies;
|
||||
struct completion wait_next_af;
|
||||
bool gon_req_action;
|
||||
bool block_gon_req_tx;
|
||||
};
|
||||
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
|
||||
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
||||
enum nl80211_iftype type, u32 *flags,
|
||||
struct vif_params *params);
|
||||
int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
|
||||
enum brcmf_fil_p2p_if_types if_type);
|
||||
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
||||
struct cfg80211_scan_request *request,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int duration, u64 *cookie);
|
||||
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
|
||||
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct brcmf_fil_af_params_le *af_params);
|
||||
bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bi);
|
||||
s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
#endif /* WL_CFGP2P_H_ */
|
||||
1895
drivers/net/wireless/brcm80211/brcmfmac/pcie.c
Normal file
1895
drivers/net/wireless/brcm80211/brcmfmac/pcie.c
Normal file
File diff suppressed because it is too large
Load diff
29
drivers/net/wireless/brcm80211/brcmfmac/pcie.h
Normal file
29
drivers/net/wireless/brcm80211/brcmfmac/pcie.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* Copyright (c) 2014 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_PCIE_H
|
||||
#define BRCMFMAC_PCIE_H
|
||||
|
||||
|
||||
struct brcmf_pciedev {
|
||||
struct brcmf_bus *bus;
|
||||
struct brcmf_pciedev_info *devinfo;
|
||||
};
|
||||
|
||||
|
||||
void brcmf_pcie_exit(void);
|
||||
void brcmf_pcie_register(void);
|
||||
|
||||
|
||||
#endif /* BRCMFMAC_PCIE_H */
|
||||
81
drivers/net/wireless/brcm80211/brcmfmac/proto.c
Normal file
81
drivers/net/wireless/brcm80211/brcmfmac/proto.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <brcmu_wifi.h>
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "proto.h"
|
||||
#include "bcdc.h"
|
||||
#include "msgbuf.h"
|
||||
|
||||
|
||||
int brcmf_proto_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_proto *proto;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
proto = kzalloc(sizeof(*proto), GFP_ATOMIC);
|
||||
if (!proto)
|
||||
goto fail;
|
||||
|
||||
drvr->proto = proto;
|
||||
|
||||
if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) {
|
||||
if (brcmf_proto_bcdc_attach(drvr))
|
||||
goto fail;
|
||||
} else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) {
|
||||
if (brcmf_proto_msgbuf_attach(drvr))
|
||||
goto fail;
|
||||
} else {
|
||||
brcmf_err("Unsupported proto type %d\n",
|
||||
drvr->bus_if->proto_type);
|
||||
goto fail;
|
||||
}
|
||||
if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
|
||||
(proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
|
||||
(proto->configure_addr_mode == NULL) ||
|
||||
(proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
|
||||
brcmf_err("Not all proto handlers have been installed\n");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kfree(proto);
|
||||
drvr->proto = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void brcmf_proto_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (drvr->proto) {
|
||||
if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
|
||||
brcmf_proto_bcdc_detach(drvr);
|
||||
else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
|
||||
brcmf_proto_msgbuf_detach(drvr);
|
||||
kfree(drvr->proto);
|
||||
drvr->proto = NULL;
|
||||
}
|
||||
}
|
||||
86
drivers/net/wireless/brcm80211/brcmfmac/proto.h
Normal file
86
drivers/net/wireless/brcm80211/brcmfmac/proto.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_PROTO_H
|
||||
#define BRCMFMAC_PROTO_H
|
||||
|
||||
|
||||
enum proto_addr_mode {
|
||||
ADDR_INDIRECT = 0,
|
||||
ADDR_DIRECT
|
||||
};
|
||||
|
||||
|
||||
struct brcmf_proto {
|
||||
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
|
||||
struct sk_buff *skb);
|
||||
int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len);
|
||||
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
|
||||
uint len);
|
||||
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
|
||||
struct sk_buff *skb);
|
||||
void (*configure_addr_mode)(struct brcmf_pub *drvr, int ifidx,
|
||||
enum proto_addr_mode addr_mode);
|
||||
void (*delete_peer)(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 peer[ETH_ALEN]);
|
||||
void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 peer[ETH_ALEN]);
|
||||
void *pd;
|
||||
};
|
||||
|
||||
|
||||
int brcmf_proto_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_proto_detach(struct brcmf_pub *drvr);
|
||||
|
||||
static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
||||
u8 *ifidx, struct sk_buff *skb)
|
||||
{
|
||||
return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb);
|
||||
}
|
||||
static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
uint cmd, void *buf, uint len)
|
||||
{
|
||||
return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len);
|
||||
}
|
||||
static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
uint cmd, void *buf, uint len)
|
||||
{
|
||||
return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
|
||||
}
|
||||
static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 offset, struct sk_buff *skb)
|
||||
{
|
||||
return drvr->proto->txdata(drvr, ifidx, offset, skb);
|
||||
}
|
||||
static inline void
|
||||
brcmf_proto_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
|
||||
enum proto_addr_mode addr_mode)
|
||||
{
|
||||
drvr->proto->configure_addr_mode(drvr, ifidx, addr_mode);
|
||||
}
|
||||
static inline void
|
||||
brcmf_proto_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
|
||||
{
|
||||
drvr->proto->delete_peer(drvr, ifidx, peer);
|
||||
}
|
||||
static inline void
|
||||
brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
|
||||
{
|
||||
drvr->proto->add_tdls_peer(drvr, ifidx, peer);
|
||||
}
|
||||
|
||||
|
||||
#endif /* BRCMFMAC_PROTO_H */
|
||||
338
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
Normal file
338
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef _BRCM_SDH_H_
|
||||
#define _BRCM_SDH_H_
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "firmware.h"
|
||||
|
||||
#define SDIO_FUNC_0 0
|
||||
#define SDIO_FUNC_1 1
|
||||
#define SDIO_FUNC_2 2
|
||||
|
||||
#define SDIOD_FBR_SIZE 0x100
|
||||
|
||||
/* io_en */
|
||||
#define SDIO_FUNC_ENABLE_1 0x02
|
||||
#define SDIO_FUNC_ENABLE_2 0x04
|
||||
|
||||
/* io_rdys */
|
||||
#define SDIO_FUNC_READY_1 0x02
|
||||
#define SDIO_FUNC_READY_2 0x04
|
||||
|
||||
/* intr_status */
|
||||
#define INTR_STATUS_FUNC1 0x2
|
||||
#define INTR_STATUS_FUNC2 0x4
|
||||
|
||||
/* Maximum number of I/O funcs */
|
||||
#define SDIOD_MAX_IOFUNCS 7
|
||||
|
||||
/* mask of register map */
|
||||
#define REG_F0_REG_MASK 0x7FF
|
||||
#define REG_F1_MISC_MASK 0x1FFFF
|
||||
|
||||
/* as of sdiod rev 0, supports 3 functions */
|
||||
#define SBSDIO_NUM_FUNCTION 3
|
||||
|
||||
/* function 0 vendor specific CCCR registers */
|
||||
#define SDIO_CCCR_BRCM_CARDCAP 0xf0
|
||||
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
|
||||
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
|
||||
#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
|
||||
#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
|
||||
#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
|
||||
#define SDIO_CCCR_BRCM_SEPINT 0xf2
|
||||
|
||||
#define SDIO_SEPINT_MASK 0x01
|
||||
#define SDIO_SEPINT_OE 0x02
|
||||
#define SDIO_SEPINT_ACT_HI 0x04
|
||||
|
||||
/* function 1 miscellaneous registers */
|
||||
|
||||
/* sprom command and status */
|
||||
#define SBSDIO_SPROM_CS 0x10000
|
||||
/* sprom info register */
|
||||
#define SBSDIO_SPROM_INFO 0x10001
|
||||
/* sprom indirect access data byte 0 */
|
||||
#define SBSDIO_SPROM_DATA_LOW 0x10002
|
||||
/* sprom indirect access data byte 1 */
|
||||
#define SBSDIO_SPROM_DATA_HIGH 0x10003
|
||||
/* sprom indirect access addr byte 0 */
|
||||
#define SBSDIO_SPROM_ADDR_LOW 0x10004
|
||||
/* gpio select */
|
||||
#define SBSDIO_GPIO_SELECT 0x10005
|
||||
/* gpio output */
|
||||
#define SBSDIO_GPIO_OUT 0x10006
|
||||
/* gpio enable */
|
||||
#define SBSDIO_GPIO_EN 0x10007
|
||||
/* rev < 7, watermark for sdio device */
|
||||
#define SBSDIO_WATERMARK 0x10008
|
||||
/* control busy signal generation */
|
||||
#define SBSDIO_DEVICE_CTL 0x10009
|
||||
|
||||
/* SB Address Window Low (b15) */
|
||||
#define SBSDIO_FUNC1_SBADDRLOW 0x1000A
|
||||
/* SB Address Window Mid (b23:b16) */
|
||||
#define SBSDIO_FUNC1_SBADDRMID 0x1000B
|
||||
/* SB Address Window High (b31:b24) */
|
||||
#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C
|
||||
/* Frame Control (frame term/abort) */
|
||||
#define SBSDIO_FUNC1_FRAMECTRL 0x1000D
|
||||
/* ChipClockCSR (ALP/HT ctl/status) */
|
||||
#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E
|
||||
/* SdioPullUp (on cmd, d0-d2) */
|
||||
#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F
|
||||
/* Write Frame Byte Count Low */
|
||||
#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019
|
||||
/* Write Frame Byte Count High */
|
||||
#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A
|
||||
/* Read Frame Byte Count Low */
|
||||
#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
|
||||
/* Read Frame Byte Count High */
|
||||
#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
|
||||
/* MesBusyCtl (rev 11) */
|
||||
#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D
|
||||
/* Sdio Core Rev 12 */
|
||||
#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
|
||||
#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
|
||||
#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
|
||||
#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
|
||||
#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
|
||||
#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
|
||||
|
||||
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
|
||||
#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */
|
||||
|
||||
/* function 1 OCP space */
|
||||
|
||||
/* sb offset addr is <= 15 bits, 32k */
|
||||
#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF
|
||||
#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
|
||||
/* with b15, maps to 32-bit SB access */
|
||||
#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
|
||||
|
||||
/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
|
||||
|
||||
#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
|
||||
#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
|
||||
#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
|
||||
/* Address bits from SBADDR regs */
|
||||
#define SBSDIO_SBWINDOW_MASK 0xffff8000
|
||||
|
||||
#define SDIOH_READ 0 /* Read request */
|
||||
#define SDIOH_WRITE 1 /* Write request */
|
||||
|
||||
#define SDIOH_DATA_FIX 0 /* Fixed addressing */
|
||||
#define SDIOH_DATA_INC 1 /* Incremental addressing */
|
||||
|
||||
/* internal return code */
|
||||
#define SUCCESS 0
|
||||
#define ERROR 1
|
||||
|
||||
/* Packet alignment for most efficient SDIO (can change based on platform) */
|
||||
#define BRCMF_SDALIGN (1 << 6)
|
||||
|
||||
/* watchdog polling interval in ms */
|
||||
#define BRCMF_WD_POLL_MS 10
|
||||
|
||||
struct brcmf_sdreg {
|
||||
int func;
|
||||
int offset;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct brcmf_sdio;
|
||||
|
||||
struct brcmf_sdio_dev {
|
||||
struct sdio_func *func[SDIO_MAX_FUNCS];
|
||||
u8 num_funcs; /* Supported funcs on client */
|
||||
u32 sbwad; /* Save backplane window address */
|
||||
struct brcmf_sdio *bus;
|
||||
atomic_t suspend; /* suspend flag */
|
||||
wait_queue_head_t request_word_wait;
|
||||
wait_queue_head_t request_buffer_wait;
|
||||
struct device *dev;
|
||||
struct brcmf_bus *bus_if;
|
||||
struct brcmfmac_sdio_platform_data *pdata;
|
||||
bool oob_irq_requested;
|
||||
bool irq_en; /* irq enable flags */
|
||||
spinlock_t irq_en_lock;
|
||||
bool irq_wake; /* irq wake enable flags */
|
||||
bool sg_support;
|
||||
uint max_request_size;
|
||||
ushort max_segment_count;
|
||||
uint max_segment_size;
|
||||
uint txglomsz;
|
||||
struct sg_table sgtable;
|
||||
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
|
||||
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
|
||||
};
|
||||
|
||||
/* sdio core registers */
|
||||
struct sdpcmd_regs {
|
||||
u32 corecontrol; /* 0x00, rev8 */
|
||||
u32 corestatus; /* rev8 */
|
||||
u32 PAD[1];
|
||||
u32 biststatus; /* rev8 */
|
||||
|
||||
/* PCMCIA access */
|
||||
u16 pcmciamesportaladdr; /* 0x010, rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciamesportalmask; /* rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciawrframebc; /* rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciaunderflowtimer; /* rev8 */
|
||||
u16 PAD[1];
|
||||
|
||||
/* interrupt */
|
||||
u32 intstatus; /* 0x020, rev8 */
|
||||
u32 hostintmask; /* rev8 */
|
||||
u32 intmask; /* rev8 */
|
||||
u32 sbintstatus; /* rev8 */
|
||||
u32 sbintmask; /* rev8 */
|
||||
u32 funcintmask; /* rev4 */
|
||||
u32 PAD[2];
|
||||
u32 tosbmailbox; /* 0x040, rev8 */
|
||||
u32 tohostmailbox; /* rev8 */
|
||||
u32 tosbmailboxdata; /* rev8 */
|
||||
u32 tohostmailboxdata; /* rev8 */
|
||||
|
||||
/* synchronized access to registers in SDIO clock domain */
|
||||
u32 sdioaccess; /* 0x050, rev8 */
|
||||
u32 PAD[3];
|
||||
|
||||
/* PCMCIA frame control */
|
||||
u8 pcmciaframectrl; /* 0x060, rev8 */
|
||||
u8 PAD[3];
|
||||
u8 pcmciawatermark; /* rev8 */
|
||||
u8 PAD[155];
|
||||
|
||||
/* interrupt batching control */
|
||||
u32 intrcvlazy; /* 0x100, rev8 */
|
||||
u32 PAD[3];
|
||||
|
||||
/* counters */
|
||||
u32 cmd52rd; /* 0x110, rev8 */
|
||||
u32 cmd52wr; /* rev8 */
|
||||
u32 cmd53rd; /* rev8 */
|
||||
u32 cmd53wr; /* rev8 */
|
||||
u32 abort; /* rev8 */
|
||||
u32 datacrcerror; /* rev8 */
|
||||
u32 rdoutofsync; /* rev8 */
|
||||
u32 wroutofsync; /* rev8 */
|
||||
u32 writebusy; /* rev8 */
|
||||
u32 readwait; /* rev8 */
|
||||
u32 readterm; /* rev8 */
|
||||
u32 writeterm; /* rev8 */
|
||||
u32 PAD[40];
|
||||
u32 clockctlstatus; /* rev8 */
|
||||
u32 PAD[7];
|
||||
|
||||
u32 PAD[128]; /* DMA engines */
|
||||
|
||||
/* SDIO/PCMCIA CIS region */
|
||||
char cis[512]; /* 0x400-0x5ff, rev6 */
|
||||
|
||||
/* PCMCIA function control registers */
|
||||
char pcmciafcr[256]; /* 0x600-6ff, rev6 */
|
||||
u16 PAD[55];
|
||||
|
||||
/* PCMCIA backplane access */
|
||||
u16 backplanecsr; /* 0x76E, rev6 */
|
||||
u16 backplaneaddr0; /* rev6 */
|
||||
u16 backplaneaddr1; /* rev6 */
|
||||
u16 backplaneaddr2; /* rev6 */
|
||||
u16 backplaneaddr3; /* rev6 */
|
||||
u16 backplanedata0; /* rev6 */
|
||||
u16 backplanedata1; /* rev6 */
|
||||
u16 backplanedata2; /* rev6 */
|
||||
u16 backplanedata3; /* rev6 */
|
||||
u16 PAD[31];
|
||||
|
||||
/* sprom "size" & "blank" info */
|
||||
u16 spromstatus; /* 0x7BE, rev2 */
|
||||
u32 PAD[464];
|
||||
|
||||
u16 PAD[0x80];
|
||||
};
|
||||
|
||||
/* Register/deregister interrupt handler. */
|
||||
int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
|
||||
int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
|
||||
|
||||
/* sdio device register access interface */
|
||||
u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
|
||||
u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
|
||||
void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data,
|
||||
int *ret);
|
||||
void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
|
||||
int *ret);
|
||||
|
||||
/* Buffer transfer to/from device (client) core via cmd53.
|
||||
* fn: function number
|
||||
* flags: backplane width, address increment, sync/async
|
||||
* buf: pointer to memory data buffer
|
||||
* nbytes: number of bytes to transfer to/from buf
|
||||
* pkt: pointer to packet associated with buf (if any)
|
||||
* complete: callback function for command completion (async only)
|
||||
* handle: handle for completion callback (first arg in callback)
|
||||
* Returns 0 or error code.
|
||||
* NOTE: Async operation is not currently supported.
|
||||
*/
|
||||
int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
|
||||
struct sk_buff_head *pktq);
|
||||
int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
|
||||
|
||||
int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt);
|
||||
int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
|
||||
int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
|
||||
struct sk_buff_head *pktq, uint totlen);
|
||||
|
||||
/* Flags bits */
|
||||
|
||||
/* Four-byte target (backplane) width (vs. two-byte) */
|
||||
#define SDIO_REQ_4BYTE 0x1
|
||||
/* Fixed address (FIFO) (vs. incrementing address) */
|
||||
#define SDIO_REQ_FIXED 0x2
|
||||
|
||||
/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
|
||||
* rw: read or write (0/1)
|
||||
* addr: direct SDIO address
|
||||
* buf: pointer to memory data buffer
|
||||
* nbytes: number of bytes to transfer to/from buf
|
||||
* Returns 0 or error code.
|
||||
*/
|
||||
int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
|
||||
u8 *data, uint size);
|
||||
|
||||
/* Issue an abort to the specified function */
|
||||
int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
|
||||
|
||||
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
|
||||
void brcmf_sdio_remove(struct brcmf_sdio *bus);
|
||||
void brcmf_sdio_isr(struct brcmf_sdio *bus);
|
||||
|
||||
void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick);
|
||||
|
||||
#endif /* _BRCM_SDH_H_ */
|
||||
22
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
Normal file
22
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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/module.h> /* bug in tracepoint.h, it should include this */
|
||||
|
||||
#ifndef __CHECKER__
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "tracepoint.h"
|
||||
#endif
|
||||
152
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
Normal file
152
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define BRCMF_TRACEPOINT_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#ifndef CONFIG_BRCM_TRACING
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(...)
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(evt_class, name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
|
||||
#endif /* CONFIG_BRCM_TRACING */
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM brcmfmac
|
||||
|
||||
#define MAX_MSG_LEN 100
|
||||
|
||||
TRACE_EVENT(brcmf_err,
|
||||
TP_PROTO(const char *func, struct va_format *vaf),
|
||||
TP_ARGS(func, vaf),
|
||||
TP_STRUCT__entry(
|
||||
__string(func, func)
|
||||
__dynamic_array(char, msg, MAX_MSG_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(func, func);
|
||||
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s: %s", __get_str(func), __get_str(msg))
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcmf_dbg,
|
||||
TP_PROTO(u32 level, const char *func, struct va_format *vaf),
|
||||
TP_ARGS(level, func, vaf),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, level)
|
||||
__string(func, func)
|
||||
__dynamic_array(char, msg, MAX_MSG_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->level = level;
|
||||
__assign_str(func, func);
|
||||
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s: %s", __get_str(func), __get_str(msg))
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcmf_hexdump,
|
||||
TP_PROTO(void *data, size_t len),
|
||||
TP_ARGS(data, len),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, len)
|
||||
__field(unsigned long, addr)
|
||||
__dynamic_array(u8, hdata, len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->len = len;
|
||||
__entry->addr = (unsigned long)data;
|
||||
memcpy(__get_dynamic_array(hdata), data, len);
|
||||
),
|
||||
TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len)
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcmf_bcdchdr,
|
||||
TP_PROTO(void *data),
|
||||
TP_ARGS(data),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, flags)
|
||||
__field(u8, prio)
|
||||
__field(u8, flags2)
|
||||
__field(u32, siglen)
|
||||
__dynamic_array(u8, signal, *((u8 *)data + 3) * 4)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->flags = *(u8 *)data;
|
||||
__entry->prio = *((u8 *)data + 1);
|
||||
__entry->flags2 = *((u8 *)data + 2);
|
||||
__entry->siglen = *((u8 *)data + 3) * 4;
|
||||
memcpy(__get_dynamic_array(signal),
|
||||
(u8 *)data + 4, __entry->siglen);
|
||||
),
|
||||
TP_printk("bcdc: prio=%d siglen=%d", __entry->prio, __entry->siglen)
|
||||
);
|
||||
|
||||
#ifndef SDPCM_RX
|
||||
#define SDPCM_RX 0
|
||||
#endif
|
||||
#ifndef SDPCM_TX
|
||||
#define SDPCM_TX 1
|
||||
#endif
|
||||
#ifndef SDPCM_GLOM
|
||||
#define SDPCM_GLOM 2
|
||||
#endif
|
||||
|
||||
TRACE_EVENT(brcmf_sdpcm_hdr,
|
||||
TP_PROTO(u8 dir, void *data),
|
||||
TP_ARGS(dir, data),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, dir)
|
||||
__field(u16, len)
|
||||
__dynamic_array(u8, hdr, dir == SDPCM_GLOM ? 20 : 12)
|
||||
),
|
||||
TP_fast_assign(
|
||||
memcpy(__get_dynamic_array(hdr), data, dir == SDPCM_GLOM ? 20 : 12);
|
||||
__entry->len = *(u8 *)data | (*((u8 *)data + 1) << 8);
|
||||
__entry->dir = dir;
|
||||
),
|
||||
TP_printk("sdpcm: %s len %u, seq %d",
|
||||
__entry->dir == SDPCM_RX ? "RX" : "TX",
|
||||
__entry->len, ((u8 *)__get_dynamic_array(hdr))[4])
|
||||
);
|
||||
|
||||
#ifdef CONFIG_BRCM_TRACING
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE tracepoint
|
||||
|
||||
#include <trace/define_trace.h>
|
||||
|
||||
#endif /* CONFIG_BRCM_TRACING */
|
||||
|
||||
#endif /* BRCMF_TRACEPOINT_H_ */
|
||||
1427
drivers/net/wireless/brcm80211/brcmfmac/usb.c
Normal file
1427
drivers/net/wireless/brcm80211/brcmfmac/usb.c
Normal file
File diff suppressed because it is too large
Load diff
53
drivers/net/wireless/brcm80211/brcmfmac/usb.h
Normal file
53
drivers/net/wireless/brcm80211/brcmfmac/usb.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
#ifndef BRCMFMAC_USB_H
|
||||
#define BRCMFMAC_USB_H
|
||||
|
||||
enum brcmf_usb_state {
|
||||
BRCMFMAC_USB_STATE_DOWN,
|
||||
BRCMFMAC_USB_STATE_DL_FAIL,
|
||||
BRCMFMAC_USB_STATE_DL_DONE,
|
||||
BRCMFMAC_USB_STATE_UP,
|
||||
BRCMFMAC_USB_STATE_SLEEP
|
||||
};
|
||||
|
||||
struct brcmf_stats {
|
||||
u32 tx_ctlpkts;
|
||||
u32 tx_ctlerrs;
|
||||
u32 rx_ctlpkts;
|
||||
u32 rx_ctlerrs;
|
||||
};
|
||||
|
||||
struct brcmf_usbdev {
|
||||
struct brcmf_bus *bus;
|
||||
struct brcmf_usbdev_info *devinfo;
|
||||
enum brcmf_usb_state state;
|
||||
struct brcmf_stats stats;
|
||||
int ntxq, nrxq, rxsize;
|
||||
u32 bus_mtu;
|
||||
int devid;
|
||||
int chiprev; /* chip revsion number */
|
||||
};
|
||||
|
||||
/* IO Request Block (IRB) */
|
||||
struct brcmf_usbreq {
|
||||
struct list_head list;
|
||||
struct brcmf_usbdev_info *devinfo;
|
||||
struct urb *urb;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
|
||||
#endif /* BRCMFMAC_USB_H */
|
||||
75
drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
Normal file
75
drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef _USB_RDL_H
|
||||
#define _USB_RDL_H
|
||||
|
||||
/* Control messages: bRequest values */
|
||||
#define DL_GETSTATE 0 /* returns the rdl_state_t struct */
|
||||
#define DL_CHECK_CRC 1 /* currently unused */
|
||||
#define DL_GO 2 /* execute downloaded image */
|
||||
#define DL_START 3 /* initialize dl state */
|
||||
#define DL_REBOOT 4 /* reboot the device in 2 seconds */
|
||||
#define DL_GETVER 5 /* returns the bootrom_id_t struct */
|
||||
#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset
|
||||
* event to occur in 2 seconds. It is the
|
||||
* responsibility of the downloaded code to
|
||||
* clear this event
|
||||
*/
|
||||
#define DL_EXEC 7 /* jump to a supplied address */
|
||||
#define DL_RESETCFG 8 /* To support single enum on dongle
|
||||
* - Not used by bootloader
|
||||
*/
|
||||
#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup
|
||||
* if resp unavailable
|
||||
*/
|
||||
|
||||
/* states */
|
||||
#define DL_WAITING 0 /* waiting to rx first pkt */
|
||||
#define DL_READY 1 /* hdr was good, waiting for more of the
|
||||
* compressed image */
|
||||
#define DL_BAD_HDR 2 /* hdr was corrupted */
|
||||
#define DL_BAD_CRC 3 /* compressed image was corrupted */
|
||||
#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */
|
||||
#define DL_START_FAIL 5 /* failed to initialize correctly */
|
||||
#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM
|
||||
* value */
|
||||
#define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START
|
||||
* for rdl) */
|
||||
|
||||
struct rdl_state_le {
|
||||
__le32 state;
|
||||
__le32 bytes;
|
||||
};
|
||||
|
||||
struct bootrom_id_le {
|
||||
__le32 chip; /* Chip id */
|
||||
__le32 chiprev; /* Chip rev */
|
||||
__le32 ramsize; /* Size of RAM */
|
||||
__le32 remapbase; /* Current remap base address */
|
||||
__le32 boardtype; /* Type of board */
|
||||
__le32 boardrev; /* Board revision */
|
||||
};
|
||||
|
||||
#define RDL_CHUNK 1500 /* size of each dl transfer */
|
||||
|
||||
#define TRX_OFFSETS_DLFWLEN_IDX 0
|
||||
#define TRX_OFFSETS_JUMPTO_IDX 1
|
||||
#define TRX_OFFSETS_NVM_LEN_IDX 2
|
||||
|
||||
#define TRX_OFFSETS_DLBASE_IDX 0
|
||||
|
||||
#endif /* _USB_RDL_H */
|
||||
115
drivers/net/wireless/brcm80211/brcmfmac/vendor.c
Normal file
115
drivers/net/wireless/brcm80211/brcmfmac/vendor.c
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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/vmalloc.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <brcmu_wifi.h>
|
||||
#include "fwil_types.h"
|
||||
#include "dhd.h"
|
||||
#include "p2p.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "wl_cfg80211.h"
|
||||
#include "vendor.h"
|
||||
#include "fwil.h"
|
||||
|
||||
static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct net_device *ndev = cfg_to_ndev(cfg);
|
||||
const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
|
||||
struct sk_buff *reply;
|
||||
int ret, payload, ret_len;
|
||||
void *dcmd_buf = NULL, *wr_pointer;
|
||||
u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
|
||||
|
||||
brcmf_dbg(TRACE, "cmd %x set %d len %d\n", cmdhdr->cmd, cmdhdr->set,
|
||||
cmdhdr->len);
|
||||
|
||||
len -= sizeof(struct brcmf_vndr_dcmd_hdr);
|
||||
ret_len = cmdhdr->len;
|
||||
if (ret_len > 0 || len > 0) {
|
||||
if (len > BRCMF_DCMD_MAXLEN) {
|
||||
brcmf_err("oversize input buffer %d\n", len);
|
||||
len = BRCMF_DCMD_MAXLEN;
|
||||
}
|
||||
if (ret_len > BRCMF_DCMD_MAXLEN) {
|
||||
brcmf_err("oversize return buffer %d\n", ret_len);
|
||||
ret_len = BRCMF_DCMD_MAXLEN;
|
||||
}
|
||||
payload = max(ret_len, len) + 1;
|
||||
dcmd_buf = vzalloc(payload);
|
||||
if (NULL == dcmd_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(dcmd_buf, (void *)cmdhdr + cmdhdr->offset, len);
|
||||
*(char *)(dcmd_buf + len) = '\0';
|
||||
}
|
||||
|
||||
if (cmdhdr->set)
|
||||
ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), cmdhdr->cmd,
|
||||
dcmd_buf, ret_len);
|
||||
else
|
||||
ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), cmdhdr->cmd,
|
||||
dcmd_buf, ret_len);
|
||||
if (ret != 0)
|
||||
goto exit;
|
||||
|
||||
wr_pointer = dcmd_buf;
|
||||
while (ret_len > 0) {
|
||||
msglen = ret_len > maxmsglen ? maxmsglen : ret_len;
|
||||
ret_len -= msglen;
|
||||
payload = msglen + sizeof(msglen);
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
if (NULL == reply) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nla_put(reply, BRCMF_NLATTR_DATA, msglen, wr_pointer) ||
|
||||
nla_put_u16(reply, BRCMF_NLATTR_LEN, msglen)) {
|
||||
kfree_skb(reply);
|
||||
ret = -ENOBUFS;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
wr_pointer += msglen;
|
||||
}
|
||||
|
||||
exit:
|
||||
vfree(dcmd_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
|
||||
{
|
||||
{
|
||||
.vendor_id = BROADCOM_OUI,
|
||||
.subcmd = BRCMF_VNDR_CMDS_DCMD
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
|
||||
WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
|
||||
},
|
||||
};
|
||||
64
drivers/net/wireless/brcm80211/brcmfmac/vendor.h
Normal file
64
drivers/net/wireless/brcm80211/brcmfmac/vendor.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef _vendor_h_
|
||||
#define _vendor_h_
|
||||
|
||||
#define BROADCOM_OUI 0x001018
|
||||
|
||||
enum brcmf_vndr_cmds {
|
||||
BRCMF_VNDR_CMDS_UNSPEC,
|
||||
BRCMF_VNDR_CMDS_DCMD,
|
||||
BRCMF_VNDR_CMDS_LAST
|
||||
};
|
||||
|
||||
/**
|
||||
* enum brcmf_nlattrs - nl80211 message attributes
|
||||
*
|
||||
* @BRCMF_NLATTR_LEN: message body length
|
||||
* @BRCMF_NLATTR_DATA: message body
|
||||
*/
|
||||
enum brcmf_nlattrs {
|
||||
BRCMF_NLATTR_UNSPEC,
|
||||
|
||||
BRCMF_NLATTR_LEN,
|
||||
BRCMF_NLATTR_DATA,
|
||||
|
||||
__BRCMF_NLATTR_AFTER_LAST,
|
||||
BRCMF_NLATTR_MAX = __BRCMF_NLATTR_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_vndr_dcmd_hdr - message header for cfg80211 vendor command dcmd
|
||||
* support
|
||||
*
|
||||
* @cmd: common dongle cmd definition
|
||||
* @len: length of expecting return buffer
|
||||
* @offset: offset of data buffer
|
||||
* @set: get or set request(optional)
|
||||
* @magic: magic number for verification
|
||||
*/
|
||||
struct brcmf_vndr_dcmd_hdr {
|
||||
uint cmd;
|
||||
int len;
|
||||
uint offset;
|
||||
uint set;
|
||||
uint magic;
|
||||
};
|
||||
|
||||
extern const struct wiphy_vendor_command brcmf_vendor_cmds[];
|
||||
|
||||
#endif /* _vendor_h_ */
|
||||
5818
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
Normal file
5818
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
Normal file
File diff suppressed because it is too large
Load diff
496
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
Normal file
496
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef _wl_cfg80211_h_
|
||||
#define _wl_cfg80211_h_
|
||||
|
||||
/* for brcmu_d11inf */
|
||||
#include <brcmu_d11.h>
|
||||
|
||||
#define WL_NUM_SCAN_MAX 10
|
||||
#define WL_NUM_PMKIDS_MAX MAXPMKID
|
||||
#define WL_TLV_INFO_MAX 1024
|
||||
#define WL_BSS_INFO_MAX 2048
|
||||
#define WL_ASSOC_INFO_MAX 512 /* assoc related fil max buf */
|
||||
#define WL_EXTRA_BUF_MAX 2048
|
||||
#define WL_ROAM_TRIGGER_LEVEL -75
|
||||
#define WL_ROAM_DELTA 20
|
||||
#define WL_BEACON_TIMEOUT 3
|
||||
|
||||
#define WL_SCAN_CHANNEL_TIME 40
|
||||
#define WL_SCAN_UNASSOC_TIME 40
|
||||
#define WL_SCAN_PASSIVE_TIME 120
|
||||
|
||||
#define WL_ESCAN_BUF_SIZE (1024 * 64)
|
||||
#define WL_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */
|
||||
|
||||
#define WL_ESCAN_ACTION_START 1
|
||||
#define WL_ESCAN_ACTION_CONTINUE 2
|
||||
#define WL_ESCAN_ACTION_ABORT 3
|
||||
|
||||
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
|
||||
#define IE_MAX_LEN 512
|
||||
|
||||
/* IE TLV processing */
|
||||
#define TLV_LEN_OFF 1 /* length offset */
|
||||
#define TLV_HDR_LEN 2 /* header length */
|
||||
#define TLV_BODY_OFF 2 /* body offset */
|
||||
#define TLV_OUI_LEN 3 /* oui id length */
|
||||
|
||||
/* 802.11 Mgmt Packet flags */
|
||||
#define BRCMF_VNDR_IE_BEACON_FLAG 0x1
|
||||
#define BRCMF_VNDR_IE_PRBRSP_FLAG 0x2
|
||||
#define BRCMF_VNDR_IE_ASSOCRSP_FLAG 0x4
|
||||
#define BRCMF_VNDR_IE_AUTHRSP_FLAG 0x8
|
||||
#define BRCMF_VNDR_IE_PRBREQ_FLAG 0x10
|
||||
#define BRCMF_VNDR_IE_ASSOCREQ_FLAG 0x20
|
||||
/* vendor IE in IW advertisement protocol ID field */
|
||||
#define BRCMF_VNDR_IE_IWAPID_FLAG 0x40
|
||||
/* allow custom IE id */
|
||||
#define BRCMF_VNDR_IE_CUSTOM_FLAG 0x100
|
||||
|
||||
/* P2P Action Frames flags (spec ordered) */
|
||||
#define BRCMF_VNDR_IE_GONREQ_FLAG 0x001000
|
||||
#define BRCMF_VNDR_IE_GONRSP_FLAG 0x002000
|
||||
#define BRCMF_VNDR_IE_GONCFM_FLAG 0x004000
|
||||
#define BRCMF_VNDR_IE_INVREQ_FLAG 0x008000
|
||||
#define BRCMF_VNDR_IE_INVRSP_FLAG 0x010000
|
||||
#define BRCMF_VNDR_IE_DISREQ_FLAG 0x020000
|
||||
#define BRCMF_VNDR_IE_DISRSP_FLAG 0x040000
|
||||
#define BRCMF_VNDR_IE_PRDREQ_FLAG 0x080000
|
||||
#define BRCMF_VNDR_IE_PRDRSP_FLAG 0x100000
|
||||
|
||||
#define BRCMF_VNDR_IE_P2PAF_SHIFT 12
|
||||
|
||||
|
||||
/**
|
||||
* enum brcmf_scan_status - scan engine status
|
||||
*
|
||||
* @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
|
||||
* @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
|
||||
* @BRCMF_SCAN_STATUS_SUPPRESS: scanning is suppressed in driver.
|
||||
*/
|
||||
enum brcmf_scan_status {
|
||||
BRCMF_SCAN_STATUS_BUSY,
|
||||
BRCMF_SCAN_STATUS_ABORT,
|
||||
BRCMF_SCAN_STATUS_SUPPRESS,
|
||||
};
|
||||
|
||||
/* dongle configuration */
|
||||
struct brcmf_cfg80211_conf {
|
||||
u32 frag_threshold;
|
||||
u32 rts_threshold;
|
||||
u32 retry_short;
|
||||
u32 retry_long;
|
||||
s32 tx_power;
|
||||
struct ieee80211_channel channel;
|
||||
};
|
||||
|
||||
/* basic structure of scan request */
|
||||
struct brcmf_cfg80211_scan_req {
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
};
|
||||
|
||||
/* basic structure of information element */
|
||||
struct brcmf_cfg80211_ie {
|
||||
u16 offset;
|
||||
u8 buf[WL_TLV_INFO_MAX];
|
||||
};
|
||||
|
||||
/* security information with currently associated ap */
|
||||
struct brcmf_cfg80211_security {
|
||||
u32 wpa_versions;
|
||||
u32 auth_type;
|
||||
u32 cipher_pairwise;
|
||||
u32 cipher_group;
|
||||
u32 wpa_auth;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_profile - profile information.
|
||||
*
|
||||
* @ssid: ssid of associated/associating ap.
|
||||
* @bssid: bssid of joined/joining ibss.
|
||||
* @sec: security information.
|
||||
*/
|
||||
struct brcmf_cfg80211_profile {
|
||||
struct brcmf_ssid ssid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct brcmf_cfg80211_security sec;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum brcmf_vif_status - bit indices for vif status.
|
||||
*
|
||||
* @BRCMF_VIF_STATUS_READY: ready for operation.
|
||||
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
|
||||
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
|
||||
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
|
||||
*/
|
||||
enum brcmf_vif_status {
|
||||
BRCMF_VIF_STATUS_READY,
|
||||
BRCMF_VIF_STATUS_CONNECTING,
|
||||
BRCMF_VIF_STATUS_CONNECTED,
|
||||
BRCMF_VIF_STATUS_DISCONNECTING,
|
||||
BRCMF_VIF_STATUS_AP_CREATING,
|
||||
BRCMF_VIF_STATUS_AP_CREATED
|
||||
};
|
||||
|
||||
/**
|
||||
* struct vif_saved_ie - holds saved IEs for a virtual interface.
|
||||
*
|
||||
* @probe_req_ie: IE info for probe request.
|
||||
* @probe_res_ie: IE info for probe response.
|
||||
* @beacon_ie: IE info for beacon frame.
|
||||
* @probe_req_ie_len: IE info length for probe request.
|
||||
* @probe_res_ie_len: IE info length for probe response.
|
||||
* @beacon_ie_len: IE info length for beacon frame.
|
||||
*/
|
||||
struct vif_saved_ie {
|
||||
u8 probe_req_ie[IE_MAX_LEN];
|
||||
u8 probe_res_ie[IE_MAX_LEN];
|
||||
u8 beacon_ie[IE_MAX_LEN];
|
||||
u8 assoc_req_ie[IE_MAX_LEN];
|
||||
u32 probe_req_ie_len;
|
||||
u32 probe_res_ie_len;
|
||||
u32 beacon_ie_len;
|
||||
u32 assoc_req_ie_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_vif - virtual interface specific information.
|
||||
*
|
||||
* @ifp: lower layer interface pointer
|
||||
* @wdev: wireless device.
|
||||
* @profile: profile information.
|
||||
* @roam_off: roaming state.
|
||||
* @sme_state: SME state using enum brcmf_vif_status bits.
|
||||
* @pm_block: power-management blocked.
|
||||
* @list: linked list.
|
||||
* @mgmt_rx_reg: registered rx mgmt frame types.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif {
|
||||
struct brcmf_if *ifp;
|
||||
struct wireless_dev wdev;
|
||||
struct brcmf_cfg80211_profile profile;
|
||||
s32 roam_off;
|
||||
unsigned long sme_state;
|
||||
bool pm_block;
|
||||
struct vif_saved_ie saved_ie;
|
||||
struct list_head list;
|
||||
u16 mgmt_rx_reg;
|
||||
};
|
||||
|
||||
/* association inform */
|
||||
struct brcmf_cfg80211_connect_info {
|
||||
u8 *req_ie;
|
||||
s32 req_ie_len;
|
||||
u8 *resp_ie;
|
||||
s32 resp_ie_len;
|
||||
};
|
||||
|
||||
/* assoc ie length */
|
||||
struct brcmf_cfg80211_assoc_ielen_le {
|
||||
__le32 req_len;
|
||||
__le32 resp_len;
|
||||
};
|
||||
|
||||
/* wpa2 pmk list */
|
||||
struct brcmf_cfg80211_pmk_list {
|
||||
struct pmkid_list pmkids;
|
||||
struct pmkid foo[MAXPMKID - 1];
|
||||
};
|
||||
|
||||
/* dongle escan state */
|
||||
enum wl_escan_state {
|
||||
WL_ESCAN_STATE_IDLE,
|
||||
WL_ESCAN_STATE_SCANNING
|
||||
};
|
||||
|
||||
struct escan_info {
|
||||
u32 escan_state;
|
||||
u8 escan_buf[WL_ESCAN_BUF_SIZE];
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_if *ifp;
|
||||
s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
||||
struct cfg80211_scan_request *request, u16 action);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_param_le - PNO scan configuration parameters
|
||||
*
|
||||
* @version: PNO parameters version.
|
||||
* @scan_freq: scan frequency.
|
||||
* @lost_network_timeout: #sec. to declare discovered network as lost.
|
||||
* @flags: Bit field to control features of PFN such as sort criteria auto
|
||||
* enable switch and background scan.
|
||||
* @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort
|
||||
* criteria.
|
||||
* @bestn: number of best networks in each scan.
|
||||
* @mscan: number of scans recorded.
|
||||
* @repeat: minimum number of scan intervals before scan frequency changes
|
||||
* in adaptive scan.
|
||||
* @exp: exponent of 2 for maximum scan interval.
|
||||
* @slow_freq: slow scan period.
|
||||
*/
|
||||
struct brcmf_pno_param_le {
|
||||
__le32 version;
|
||||
__le32 scan_freq;
|
||||
__le32 lost_network_timeout;
|
||||
__le16 flags;
|
||||
__le16 rssi_margin;
|
||||
u8 bestn;
|
||||
u8 mscan;
|
||||
u8 repeat;
|
||||
u8 exp;
|
||||
__le32 slow_freq;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_net_param_le - scan parameters per preferred network.
|
||||
*
|
||||
* @ssid: ssid name and its length.
|
||||
* @flags: bit2: hidden.
|
||||
* @infra: BSS vs IBSS.
|
||||
* @auth: Open vs Closed.
|
||||
* @wpa_auth: WPA type.
|
||||
* @wsec: wsec value.
|
||||
*/
|
||||
struct brcmf_pno_net_param_le {
|
||||
struct brcmf_ssid_le ssid;
|
||||
__le32 flags;
|
||||
__le32 infra;
|
||||
__le32 auth;
|
||||
__le32 wpa_auth;
|
||||
__le32 wsec;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_net_info_le - information per found network.
|
||||
*
|
||||
* @bssid: BSS network identifier.
|
||||
* @channel: channel number only.
|
||||
* @SSID_len: length of ssid.
|
||||
* @SSID: ssid characters.
|
||||
* @RSSI: receive signal strength (in dBm).
|
||||
* @timestamp: age in seconds.
|
||||
*/
|
||||
struct brcmf_pno_net_info_le {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 channel;
|
||||
u8 SSID_len;
|
||||
u8 SSID[32];
|
||||
__le16 RSSI;
|
||||
__le16 timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event.
|
||||
*
|
||||
* @version: PNO version identifier.
|
||||
* @status: indicates completion status of PNO scan.
|
||||
* @count: amount of brcmf_pno_net_info_le entries appended.
|
||||
*/
|
||||
struct brcmf_pno_scanresults_le {
|
||||
__le32 version;
|
||||
__le32 status;
|
||||
__le32 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_vif_event - virtual interface event information.
|
||||
*
|
||||
* @vif_wq: waitqueue awaiting interface event from firmware.
|
||||
* @vif_event_lock: protects other members in this structure.
|
||||
* @vif_complete: completion for net attach.
|
||||
* @action: either add, change, or delete.
|
||||
* @vif: virtual interface object related to the event.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif_event {
|
||||
wait_queue_head_t vif_wq;
|
||||
struct mutex vif_event_lock;
|
||||
u8 action;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||
*
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @p2p: peer-to-peer specific information.
|
||||
* @btcoex: Bluetooth coexistence information.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @usr_sync: mainly for dongle up/down synchronization.
|
||||
* @bss_list: bss_list holding scanned ap information.
|
||||
* @scan_req_int: internal scan request object.
|
||||
* @bss_info: bss information for cfg80211 layer.
|
||||
* @ie: information element object for internal purpose.
|
||||
* @conn_info: association info.
|
||||
* @pmk_list: wpa2 pmk list.
|
||||
* @scan_status: scan activity on the dongle.
|
||||
* @pub: common driver information.
|
||||
* @channel: current channel.
|
||||
* @active_scan: current scan mode.
|
||||
* @sched_escan: e-scan for scheduled scan support running.
|
||||
* @ibss_starter: indicates this sta is ibss starter.
|
||||
* @pwr_save: indicate whether dongle to support power save mode.
|
||||
* @dongle_up: indicate whether dongle up or not.
|
||||
* @roam_on: on/off switch for dongle self-roaming.
|
||||
* @scan_tried: indicates if first scan attempted.
|
||||
* @dcmd_buf: dcmd buffer.
|
||||
* @extra_buf: mainly to grab assoc information.
|
||||
* @debugfsdir: debugfs folder for this device.
|
||||
* @escan_info: escan information.
|
||||
* @escan_timeout: Timer for catch scan timeout.
|
||||
* @escan_timeout_work: scan timeout worker.
|
||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @vif_list: linked list of vif instances.
|
||||
* @vif_cnt: number of vif instances.
|
||||
* @vif_event: vif event signalling.
|
||||
* @wowl_enabled; set during suspend, is wowl used.
|
||||
* @pre_wowl_pmmode: intermediate storage of pm mode during wowl.
|
||||
*/
|
||||
struct brcmf_cfg80211_info {
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct brcmf_p2p_info p2p;
|
||||
struct brcmf_btcoex_info *btcoex;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct mutex usr_sync;
|
||||
struct brcmf_cfg80211_scan_req scan_req_int;
|
||||
struct wl_cfg80211_bss_info *bss_info;
|
||||
struct brcmf_cfg80211_ie ie;
|
||||
struct brcmf_cfg80211_connect_info conn_info;
|
||||
struct brcmf_cfg80211_pmk_list *pmk_list;
|
||||
unsigned long scan_status;
|
||||
struct brcmf_pub *pub;
|
||||
u32 channel;
|
||||
bool active_scan;
|
||||
bool sched_escan;
|
||||
bool ibss_starter;
|
||||
bool pwr_save;
|
||||
bool dongle_up;
|
||||
bool scan_tried;
|
||||
u8 *dcmd_buf;
|
||||
u8 *extra_buf;
|
||||
struct dentry *debugfsdir;
|
||||
struct escan_info escan_info;
|
||||
struct timer_list escan_timeout;
|
||||
struct work_struct escan_timeout_work;
|
||||
u8 *escan_ioctl_buf;
|
||||
struct list_head vif_list;
|
||||
struct brcmf_cfg80211_vif_event vif_event;
|
||||
struct completion vif_disabled;
|
||||
struct brcmu_d11inf d11inf;
|
||||
bool wowl_enabled;
|
||||
u32 pre_wowl_pmmode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_tlv - tag_ID/length/value_buffer tuple.
|
||||
*
|
||||
* @id: tag identifier.
|
||||
* @len: number of bytes in value buffer.
|
||||
* @data: value buffer.
|
||||
*/
|
||||
struct brcmf_tlv {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
return cfg->wiphy;
|
||||
}
|
||||
|
||||
static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
|
||||
{
|
||||
return (struct brcmf_cfg80211_info *)(wiphy_priv(w));
|
||||
}
|
||||
|
||||
static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
|
||||
{
|
||||
return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
|
||||
}
|
||||
|
||||
static inline
|
||||
struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
|
||||
return vif->wdev.netdev;
|
||||
}
|
||||
|
||||
static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
|
||||
{
|
||||
return wdev_to_cfg(ndev->ieee80211_ptr);
|
||||
}
|
||||
|
||||
static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(nd);
|
||||
return &ifp->vif->profile;
|
||||
}
|
||||
|
||||
static inline struct brcmf_cfg80211_vif *ndev_to_vif(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
return ifp->vif;
|
||||
}
|
||||
|
||||
static inline struct
|
||||
brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
return &cfg->conn_info;
|
||||
}
|
||||
|
||||
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||
struct device *busdev);
|
||||
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||
s32 brcmf_cfg80211_up(struct net_device *ndev);
|
||||
s32 brcmf_cfg80211_down(struct net_device *ndev);
|
||||
enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
|
||||
|
||||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
enum nl80211_iftype type,
|
||||
bool pm_block);
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
|
||||
|
||||
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
|
||||
const struct brcmf_tlv *
|
||||
brcmf_parse_tlvs(const void *buf, int buflen, uint key);
|
||||
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
|
||||
struct ieee80211_channel *ch);
|
||||
bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state);
|
||||
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
|
||||
int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
|
||||
u8 action, ulong timeout);
|
||||
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_if *ifp, bool aborted,
|
||||
bool fw_abort);
|
||||
void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
|
||||
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_cfg80211_free_netdev(struct net_device *ndev);
|
||||
|
||||
#endif /* _wl_cfg80211_h_ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue