diff options
| -rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c | 72 |
3 files changed, 87 insertions, 3 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 6260240743d5..1fbb640e896a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
| @@ -1915,6 +1915,12 @@ int cxgb4_change_mac(struct port_info *pi, unsigned int viid, | |||
| 1915 | int *tcam_idx, const u8 *addr, | 1915 | int *tcam_idx, const u8 *addr, |
| 1916 | bool persistent, u8 *smt_idx); | 1916 | bool persistent, u8 *smt_idx); |
| 1917 | 1917 | ||
| 1918 | int cxgb4_alloc_mac_filt(struct adapter *adap, unsigned int viid, | ||
| 1919 | bool free, unsigned int naddr, | ||
| 1920 | const u8 **addr, u16 *idx, | ||
| 1921 | u64 *hash, bool sleep_ok); | ||
| 1922 | int cxgb4_free_mac_filt(struct adapter *adap, unsigned int viid, | ||
| 1923 | unsigned int naddr, const u8 **addr, bool sleep_ok); | ||
| 1918 | int cxgb4_init_mps_ref_entries(struct adapter *adap); | 1924 | int cxgb4_init_mps_ref_entries(struct adapter *adap); |
| 1919 | void cxgb4_free_mps_ref_entries(struct adapter *adap); | 1925 | void cxgb4_free_mps_ref_entries(struct adapter *adap); |
| 1920 | int cxgb4_alloc_encap_mac_filt(struct adapter *adap, unsigned int viid, | 1926 | int cxgb4_alloc_encap_mac_filt(struct adapter *adap, unsigned int viid, |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 1520e5294289..b08efc48d42f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
| @@ -366,13 +366,19 @@ static int cxgb4_mac_sync(struct net_device *netdev, const u8 *mac_addr) | |||
| 366 | int ret; | 366 | int ret; |
| 367 | u64 mhash = 0; | 367 | u64 mhash = 0; |
| 368 | u64 uhash = 0; | 368 | u64 uhash = 0; |
| 369 | /* idx stores the index of allocated filters, | ||
| 370 | * its size should be modified based on the number of | ||
| 371 | * MAC addresses that we allocate filters for | ||
| 372 | */ | ||
| 373 | |||
| 374 | u16 idx[1] = {}; | ||
| 369 | bool free = false; | 375 | bool free = false; |
| 370 | bool ucast = is_unicast_ether_addr(mac_addr); | 376 | bool ucast = is_unicast_ether_addr(mac_addr); |
| 371 | const u8 *maclist[1] = {mac_addr}; | 377 | const u8 *maclist[1] = {mac_addr}; |
| 372 | struct hash_mac_addr *new_entry; | 378 | struct hash_mac_addr *new_entry; |
| 373 | 379 | ||
| 374 | ret = t4_alloc_mac_filt(adap, adap->mbox, pi->viid, free, 1, maclist, | 380 | ret = cxgb4_alloc_mac_filt(adap, pi->viid, free, 1, maclist, |
| 375 | NULL, ucast ? &uhash : &mhash, false); | 381 | idx, ucast ? &uhash : &mhash, false); |
| 376 | if (ret < 0) | 382 | if (ret < 0) |
| 377 | goto out; | 383 | goto out; |
| 378 | /* if hash != 0, then add the addr to hash addr list | 384 | /* if hash != 0, then add the addr to hash addr list |
| @@ -410,7 +416,7 @@ static int cxgb4_mac_unsync(struct net_device *netdev, const u8 *mac_addr) | |||
| 410 | } | 416 | } |
| 411 | } | 417 | } |
| 412 | 418 | ||
| 413 | ret = t4_free_mac_filt(adap, adap->mbox, pi->viid, 1, maclist, false); | 419 | ret = cxgb4_free_mac_filt(adap, pi->viid, 1, maclist, false); |
| 414 | return ret < 0 ? -EINVAL : 0; | 420 | return ret < 0 ? -EINVAL : 0; |
| 415 | } | 421 | } |
| 416 | 422 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c index 067217c6ca05..b1a073eea60b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c | |||
| @@ -3,6 +3,31 @@ | |||
| 3 | 3 | ||
| 4 | #include "cxgb4.h" | 4 | #include "cxgb4.h" |
| 5 | 5 | ||
| 6 | static int cxgb4_mps_ref_dec_by_mac(struct adapter *adap, | ||
| 7 | const u8 *addr, const u8 *mask) | ||
| 8 | { | ||
| 9 | u8 bitmask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
| 10 | struct mps_entries_ref *mps_entry, *tmp; | ||
| 11 | int ret = -EINVAL; | ||
| 12 | |||
| 13 | spin_lock_bh(&adap->mps_ref_lock); | ||
| 14 | list_for_each_entry_safe(mps_entry, tmp, &adap->mps_ref, list) { | ||
| 15 | if (ether_addr_equal(mps_entry->addr, addr) && | ||
| 16 | ether_addr_equal(mps_entry->mask, mask ? mask : bitmask)) { | ||
| 17 | if (!refcount_dec_and_test(&mps_entry->refcnt)) { | ||
| 18 | spin_unlock_bh(&adap->mps_ref_lock); | ||
| 19 | return -EBUSY; | ||
| 20 | } | ||
| 21 | list_del(&mps_entry->list); | ||
| 22 | kfree(mps_entry); | ||
| 23 | ret = 0; | ||
| 24 | break; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | spin_unlock_bh(&adap->mps_ref_lock); | ||
| 28 | return ret; | ||
| 29 | } | ||
| 30 | |||
| 6 | static int cxgb4_mps_ref_dec(struct adapter *adap, u16 idx) | 31 | static int cxgb4_mps_ref_dec(struct adapter *adap, u16 idx) |
| 7 | { | 32 | { |
| 8 | struct mps_entries_ref *mps_entry, *tmp; | 33 | struct mps_entries_ref *mps_entry, *tmp; |
| @@ -54,6 +79,53 @@ unlock: | |||
| 54 | return ret; | 79 | return ret; |
| 55 | } | 80 | } |
| 56 | 81 | ||
| 82 | int cxgb4_free_mac_filt(struct adapter *adap, unsigned int viid, | ||
| 83 | unsigned int naddr, const u8 **addr, bool sleep_ok) | ||
| 84 | { | ||
| 85 | int ret, i; | ||
| 86 | |||
| 87 | for (i = 0; i < naddr; i++) { | ||
| 88 | if (!cxgb4_mps_ref_dec_by_mac(adap, addr[i], NULL)) { | ||
| 89 | ret = t4_free_mac_filt(adap, adap->mbox, viid, | ||
| 90 | 1, &addr[i], sleep_ok); | ||
| 91 | if (ret < 0) | ||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | /* return number of filters freed */ | ||
| 97 | return naddr; | ||
| 98 | } | ||
| 99 | |||
| 100 | int cxgb4_alloc_mac_filt(struct adapter *adap, unsigned int viid, | ||
| 101 | bool free, unsigned int naddr, const u8 **addr, | ||
| 102 | u16 *idx, u64 *hash, bool sleep_ok) | ||
| 103 | { | ||
| 104 | int ret, i; | ||
| 105 | |||
| 106 | ret = t4_alloc_mac_filt(adap, adap->mbox, viid, free, | ||
| 107 | naddr, addr, idx, hash, sleep_ok); | ||
| 108 | if (ret < 0) | ||
| 109 | return ret; | ||
| 110 | |||
| 111 | for (i = 0; i < naddr; i++) { | ||
| 112 | if (idx[i] != 0xffff) { | ||
| 113 | if (cxgb4_mps_ref_inc(adap, addr[i], idx[i], NULL)) { | ||
| 114 | ret = -ENOMEM; | ||
| 115 | goto error; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | goto out; | ||
| 121 | error: | ||
| 122 | cxgb4_free_mac_filt(adap, viid, naddr, addr, sleep_ok); | ||
| 123 | |||
| 124 | out: | ||
| 125 | /* Returns a negative error number or the number of filters allocated */ | ||
| 126 | return ret; | ||
| 127 | } | ||
| 128 | |||
| 57 | int cxgb4_update_mac_filt(struct port_info *pi, unsigned int viid, | 129 | int cxgb4_update_mac_filt(struct port_info *pi, unsigned int viid, |
| 58 | int *tcam_idx, const u8 *addr, | 130 | int *tcam_idx, const u8 *addr, |
| 59 | bool persistent, u8 *smt_idx) | 131 | bool persistent, u8 *smt_idx) |
