aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/flowring.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/flowring.c94
1 files changed, 90 insertions, 4 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
index 07009046fda5..a1016b811284 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
@@ -49,6 +49,23 @@ static const u8 brcmf_flowring_prio2fifo[] = {
49}; 49};
50 50
51 51
52static bool
53brcmf_flowring_is_tdls_mac(struct brcmf_flowring *flow, u8 mac[ETH_ALEN])
54{
55 struct brcmf_flowring_tdls_entry *search;
56
57 search = flow->tdls_entry;
58
59 while (search) {
60 if (memcmp(search->mac, mac, ETH_ALEN) == 0)
61 return true;
62 search = search->next;
63 }
64
65 return false;
66}
67
68
52u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], 69u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
53 u8 prio, u8 ifidx) 70 u8 prio, u8 ifidx)
54{ 71{
@@ -67,6 +84,10 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
67 mac = (u8 *)ALLFFMAC; 84 mac = (u8 *)ALLFFMAC;
68 fifo = 0; 85 fifo = 0;
69 } 86 }
87 if ((sta) && (flow->tdls_active) &&
88 (brcmf_flowring_is_tdls_mac(flow, da))) {
89 sta = false;
90 }
70 hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : 91 hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
71 BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); 92 BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
72 found = false; 93 found = false;
@@ -106,15 +127,17 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
106 mac = (u8 *)ALLFFMAC; 127 mac = (u8 *)ALLFFMAC;
107 fifo = 0; 128 fifo = 0;
108 } 129 }
130 if ((sta) && (flow->tdls_active) &&
131 (brcmf_flowring_is_tdls_mac(flow, da))) {
132 sta = false;
133 }
109 hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : 134 hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
110 BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); 135 BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
111 found = false; 136 found = false;
112 hash = flow->hash; 137 hash = flow->hash;
113 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { 138 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
114 if (((sta) && 139 if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
115 (hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX)) || 140 (memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
116 ((!sta) &&
117 (memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0))) {
118 found = true; 141 found = true;
119 break; 142 break;
120 } 143 }
@@ -356,12 +379,21 @@ void brcmf_flowring_detach(struct brcmf_flowring *flow)
356{ 379{
357 struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev); 380 struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
358 struct brcmf_pub *drvr = bus_if->drvr; 381 struct brcmf_pub *drvr = bus_if->drvr;
382 struct brcmf_flowring_tdls_entry *search;
383 struct brcmf_flowring_tdls_entry *remove;
359 u8 flowid; 384 u8 flowid;
360 385
361 for (flowid = 0; flowid < flow->nrofrings; flowid++) { 386 for (flowid = 0; flowid < flow->nrofrings; flowid++) {
362 if (flow->rings[flowid]) 387 if (flow->rings[flowid])
363 brcmf_msgbuf_delete_flowring(drvr, flowid); 388 brcmf_msgbuf_delete_flowring(drvr, flowid);
364 } 389 }
390
391 search = flow->tdls_entry;
392 while (search) {
393 remove = search;
394 search = search->next;
395 kfree(remove);
396 }
365 kfree(flow->rings); 397 kfree(flow->rings);
366 kfree(flow); 398 kfree(flow);
367} 399}
@@ -396,11 +428,25 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
396 struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev); 428 struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
397 struct brcmf_pub *drvr = bus_if->drvr; 429 struct brcmf_pub *drvr = bus_if->drvr;
398 struct brcmf_flowring_hash *hash; 430 struct brcmf_flowring_hash *hash;
431 struct brcmf_flowring_tdls_entry *prev;
432 struct brcmf_flowring_tdls_entry *search;
399 u32 i; 433 u32 i;
400 u8 flowid; 434 u8 flowid;
401 bool sta; 435 bool sta;
402 436
403 sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT); 437 sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
438
439 search = flow->tdls_entry;
440 prev = NULL;
441 while (search) {
442 if (memcmp(search->mac, peer, ETH_ALEN) == 0) {
443 sta = false;
444 break;
445 }
446 prev = search;
447 search = search->next;
448 }
449
404 hash = flow->hash; 450 hash = flow->hash;
405 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { 451 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
406 if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) && 452 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,
412 } 458 }
413 } 459 }
414 } 460 }
461
462 if (search) {
463 if (prev)
464 prev->next = search->next;
465 else
466 flow->tdls_entry = search->next;
467 kfree(search);
468 if (flow->tdls_entry == NULL)
469 flow->tdls_active = false;
470 }
471}
472
473
474void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
475 u8 peer[ETH_ALEN])
476{
477 struct brcmf_flowring_tdls_entry *tdls_entry;
478 struct brcmf_flowring_tdls_entry *search;
479
480 tdls_entry = kzalloc(sizeof(*tdls_entry), GFP_ATOMIC);
481 if (tdls_entry == NULL)
482 return;
483
484 memcpy(tdls_entry->mac, peer, ETH_ALEN);
485 tdls_entry->next = NULL;
486 if (flow->tdls_entry == NULL) {
487 flow->tdls_entry = tdls_entry;
488 } else {
489 search = flow->tdls_entry;
490 if (memcmp(search->mac, peer, ETH_ALEN) == 0)
491 return;
492 while (search->next) {
493 search = search->next;
494 if (memcmp(search->mac, peer, ETH_ALEN) == 0)
495 return;
496 }
497 search->next = tdls_entry;
498 }
499
500 flow->tdls_active = true;
415} 501}