Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70b7d94b authored by Hante Meuleman's avatar Hante Meuleman Committed by John W. Linville
Browse files

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: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarDaniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 17ca5c71
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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)
{
	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->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;
+90 −4
Original line number Diff line number Diff line
@@ -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],
			  u8 prio, u8 ifidx)
{
@@ -67,6 +84,10 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
		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;
@@ -106,15 +127,17 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
		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) &&
		     (hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX)) ||
		    ((!sta) &&
		     (memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0))) {
		if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
		    (memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
			found = true;
			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_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);
}
@@ -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_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)) &&
@@ -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;
}
+9 −0
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ struct brcmf_flowring_ring {
	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];
@@ -47,6 +52,8 @@ struct brcmf_flowring {
	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;
};


@@ -70,6 +77,8 @@ 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 */
+5 −1
Original line number Diff line number Diff line
@@ -293,6 +293,10 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
			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);
+5 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ struct brcmf_event;
	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)

@@ -155,6 +156,10 @@ enum brcmf_fweh_event_code {
#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
Loading