diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/flowring.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/flowring.c | 94 |
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 | ||
52 | static bool | ||
53 | brcmf_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 | |||
52 | u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | 69 | u32 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 | |||
474 | void 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 | } |