brcmfmac: Add TDLS support to msgbuf.
TDLS connections require dedicated flowrings. This patches adds TDLS event handling and flowring creation/deletion based on these events. Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
17ca5c7184
commit
70b7d94bcc
9 changed files with 158 additions and 6 deletions
|
@ -349,6 +349,12 @@ brcmf_proto_bcdc_delete_peer(struct brcmf_pub *drvr, int ifidx,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
||||||
{
|
{
|
||||||
struct brcmf_bcdc *bcdc;
|
struct brcmf_bcdc *bcdc;
|
||||||
|
@ -369,6 +375,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
||||||
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
|
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
|
||||||
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
|
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
|
||||||
drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
|
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->proto->pd = bcdc;
|
||||||
|
|
||||||
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
|
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
|
||||||
|
|
|
@ -49,6 +49,23 @@ static const u8 brcmf_flowring_prio2fifo[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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],
|
u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||||
u8 prio, u8 ifidx)
|
u8 prio, u8 ifidx)
|
||||||
{
|
{
|
||||||
|
@ -67,6 +84,10 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||||
mac = (u8 *)ALLFFMAC;
|
mac = (u8 *)ALLFFMAC;
|
||||||
fifo = 0;
|
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) :
|
hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
|
||||||
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
||||||
found = false;
|
found = false;
|
||||||
|
@ -106,15 +127,17 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||||
mac = (u8 *)ALLFFMAC;
|
mac = (u8 *)ALLFFMAC;
|
||||||
fifo = 0;
|
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) :
|
hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
|
||||||
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
||||||
found = false;
|
found = false;
|
||||||
hash = flow->hash;
|
hash = flow->hash;
|
||||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||||
if (((sta) &&
|
if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
|
||||||
(hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX)) ||
|
(memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
|
||||||
((!sta) &&
|
|
||||||
(memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0))) {
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -356,12 +379,21 @@ void brcmf_flowring_detach(struct brcmf_flowring *flow)
|
||||||
{
|
{
|
||||||
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
||||||
struct brcmf_pub *drvr = bus_if->drvr;
|
struct brcmf_pub *drvr = bus_if->drvr;
|
||||||
|
struct brcmf_flowring_tdls_entry *search;
|
||||||
|
struct brcmf_flowring_tdls_entry *remove;
|
||||||
u8 flowid;
|
u8 flowid;
|
||||||
|
|
||||||
for (flowid = 0; flowid < flow->nrofrings; flowid++) {
|
for (flowid = 0; flowid < flow->nrofrings; flowid++) {
|
||||||
if (flow->rings[flowid])
|
if (flow->rings[flowid])
|
||||||
brcmf_msgbuf_delete_flowring(drvr, 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->rings);
|
||||||
kfree(flow);
|
kfree(flow);
|
||||||
}
|
}
|
||||||
|
@ -396,11 +428,25 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
|
||||||
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
||||||
struct brcmf_pub *drvr = bus_if->drvr;
|
struct brcmf_pub *drvr = bus_if->drvr;
|
||||||
struct brcmf_flowring_hash *hash;
|
struct brcmf_flowring_hash *hash;
|
||||||
|
struct brcmf_flowring_tdls_entry *prev;
|
||||||
|
struct brcmf_flowring_tdls_entry *search;
|
||||||
u32 i;
|
u32 i;
|
||||||
u8 flowid;
|
u8 flowid;
|
||||||
bool sta;
|
bool sta;
|
||||||
|
|
||||||
sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
|
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;
|
hash = flow->hash;
|
||||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||||
if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
|
if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
|
||||||
|
@ -412,4 +458,44 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,11 @@ struct brcmf_flowring_ring {
|
||||||
struct sk_buff_head skblist;
|
struct sk_buff_head skblist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct brcmf_flowring_tdls_entry {
|
||||||
|
u8 mac[ETH_ALEN];
|
||||||
|
struct brcmf_flowring_tdls_entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct brcmf_flowring {
|
struct brcmf_flowring {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
|
struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
|
||||||
|
@ -47,6 +52,8 @@ struct brcmf_flowring {
|
||||||
spinlock_t block_lock;
|
spinlock_t block_lock;
|
||||||
enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
|
enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
|
||||||
u16 nrofrings;
|
u16 nrofrings;
|
||||||
|
bool tdls_active;
|
||||||
|
struct brcmf_flowring_tdls_entry *tdls_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +77,8 @@ void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
|
||||||
enum proto_addr_mode addr_mode);
|
enum proto_addr_mode addr_mode);
|
||||||
void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
|
void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
|
||||||
u8 peer[ETH_ALEN]);
|
u8 peer[ETH_ALEN]);
|
||||||
|
void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
|
||||||
|
u8 peer[ETH_ALEN]);
|
||||||
|
|
||||||
|
|
||||||
#endif /* BRCMFMAC_FLOWRING_H */
|
#endif /* BRCMFMAC_FLOWRING_H */
|
||||||
|
|
|
@ -293,7 +293,11 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||||
goto event_free;
|
goto event_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifp = drvr->iflist[emsg.bsscfgidx];
|
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,
|
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||||
event->data);
|
event->data);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -102,6 +102,7 @@ struct brcmf_event;
|
||||||
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
|
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
|
||||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
||||||
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
|
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
|
||||||
|
BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
|
||||||
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
|
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
|
||||||
BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
|
BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
|
||||||
|
|
||||||
|
@ -155,6 +156,10 @@ enum brcmf_fweh_event_code {
|
||||||
#define BRCMF_E_REASON_TSPEC_REJECTED 7
|
#define BRCMF_E_REASON_TSPEC_REJECTED 7
|
||||||
#define BRCMF_E_REASON_BETTER_AP 8
|
#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 */
|
/* action field values for brcmf_ifevent */
|
||||||
#define BRCMF_E_IF_ADD 1
|
#define BRCMF_E_IF_ADD 1
|
||||||
#define BRCMF_E_IF_DEL 2
|
#define BRCMF_E_IF_DEL 2
|
||||||
|
|
|
@ -751,6 +751,15 @@ brcmf_msgbuf_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
brcmf_msgbuf_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
|
||||||
|
{
|
||||||
|
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
|
||||||
|
|
||||||
|
brcmf_flowring_add_tdls_peer(msgbuf->flow, ifidx, peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
|
brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
|
||||||
{
|
{
|
||||||
|
@ -1298,6 +1307,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
|
||||||
drvr->proto->txdata = brcmf_msgbuf_txdata;
|
drvr->proto->txdata = brcmf_msgbuf_txdata;
|
||||||
drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
|
drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
|
||||||
drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
|
drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
|
||||||
|
drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
|
||||||
drvr->proto->pd = msgbuf;
|
drvr->proto->pd = msgbuf;
|
||||||
|
|
||||||
init_waitqueue_head(&msgbuf->ioctl_resp_wait);
|
init_waitqueue_head(&msgbuf->ioctl_resp_wait);
|
||||||
|
|
|
@ -54,7 +54,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
|
||||||
if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
|
if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
|
||||||
(proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
|
(proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
|
||||||
(proto->configure_addr_mode == NULL) ||
|
(proto->configure_addr_mode == NULL) ||
|
||||||
(proto->delete_peer == NULL)) {
|
(proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
|
||||||
brcmf_err("Not all proto handlers have been installed\n");
|
brcmf_err("Not all proto handlers have been installed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ struct brcmf_proto {
|
||||||
enum proto_addr_mode addr_mode);
|
enum proto_addr_mode addr_mode);
|
||||||
void (*delete_peer)(struct brcmf_pub *drvr, int ifidx,
|
void (*delete_peer)(struct brcmf_pub *drvr, int ifidx,
|
||||||
u8 peer[ETH_ALEN]);
|
u8 peer[ETH_ALEN]);
|
||||||
|
void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
|
||||||
|
u8 peer[ETH_ALEN]);
|
||||||
void *pd;
|
void *pd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,6 +76,11 @@ brcmf_proto_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
|
||||||
{
|
{
|
||||||
drvr->proto->delete_peer(drvr, ifidx, peer);
|
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 */
|
#endif /* BRCMFMAC_PROTO_H */
|
||||||
|
|
|
@ -4155,6 +4155,27 @@ static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
|
||||||
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
|
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s32
|
||||||
|
brcmf_notify_tdls_peer_event(struct brcmf_if *ifp,
|
||||||
|
const struct brcmf_event_msg *e, void *data)
|
||||||
|
{
|
||||||
|
switch (e->reason) {
|
||||||
|
case BRCMF_E_REASON_TDLS_PEER_DISCOVERED:
|
||||||
|
brcmf_dbg(TRACE, "TDLS Peer Discovered\n");
|
||||||
|
break;
|
||||||
|
case BRCMF_E_REASON_TDLS_PEER_CONNECTED:
|
||||||
|
brcmf_dbg(TRACE, "TDLS Peer Connected\n");
|
||||||
|
brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
|
||||||
|
break;
|
||||||
|
case BRCMF_E_REASON_TDLS_PEER_DISCONNECTED:
|
||||||
|
brcmf_dbg(TRACE, "TDLS Peer Disconnected\n");
|
||||||
|
brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
|
static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -5691,6 +5712,9 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||||
if (err) {
|
if (err) {
|
||||||
brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
|
brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
|
||||||
wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
|
wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
|
||||||
|
} else {
|
||||||
|
brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
|
||||||
|
brcmf_notify_tdls_peer_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg;
|
return cfg;
|
||||||
|
|
Loading…
Add table
Reference in a new issue