1178302Skmacy/************************************************************************** 2178302Skmacy 3237263SnpCopyright (c) 2007-2009, Chelsio Inc. 4178302SkmacyAll rights reserved. 5178302Skmacy 6178302SkmacyRedistribution and use in source and binary forms, with or without 7178302Skmacymodification, are permitted provided that the following conditions are met: 8178302Skmacy 9178302Skmacy 1. Redistributions of source code must retain the above copyright notice, 10178302Skmacy this list of conditions and the following disclaimer. 11178302Skmacy 12178302Skmacy 2. Neither the name of the Chelsio Corporation nor the names of its 13178302Skmacy contributors may be used to endorse or promote products derived from 14178302Skmacy this software without specific prior written permission. 15178302Skmacy 16178302SkmacyTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17178302SkmacyAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18178302SkmacyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19178302SkmacyARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20178302SkmacyLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21178302SkmacyCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22178302SkmacySUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23178302SkmacyINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24178302SkmacyCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25178302SkmacyARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26178302SkmacyPOSSIBILITY OF SUCH DAMAGE. 27178302Skmacy 28178302Skmacy$FreeBSD$ 29178302Skmacy 30178302Skmacy***************************************************************************/ 31178302Skmacy#ifndef _CHELSIO_L2T_H 32178302Skmacy#define _CHELSIO_L2T_H 33178302Skmacy 34178302Skmacy#include <sys/lock.h> 35178302Skmacy#include <sys/rwlock.h> 36178302Skmacy 37178302Skmacyenum { 38237263Snp L2T_SIZE = 2048 39178302Skmacy}; 40178302Skmacy 41237263Snpenum { 42237263Snp L2T_STATE_VALID, /* entry is up to date */ 43237263Snp L2T_STATE_STALE, /* entry may be used but needs revalidation */ 44237263Snp L2T_STATE_RESOLVING, /* entry needs address resolution */ 45237263Snp L2T_STATE_FAILED, /* failed to resolve */ 46237263Snp L2T_STATE_UNUSED /* entry not in use */ 47237263Snp}; 48237263Snp 49178302Skmacy/* 50178302Skmacy * Each L2T entry plays multiple roles. First of all, it keeps state for the 51178302Skmacy * corresponding entry of the HW L2 table and maintains a queue of offload 52178302Skmacy * packets awaiting address resolution. Second, it is a node of a hash table 53178302Skmacy * chain, where the nodes of the chain are linked together through their next 54178302Skmacy * pointer. Finally, each node is a bucket of a hash table, pointing to the 55178302Skmacy * first element in its chain through its first pointer. 56178302Skmacy */ 57178302Skmacystruct l2t_entry { 58178302Skmacy uint16_t state; /* entry state */ 59178302Skmacy uint16_t idx; /* entry index */ 60237263Snp uint32_t addr; /* nexthop IP address */ 61237263Snp struct ifnet *ifp; /* outgoing interface */ 62178302Skmacy uint16_t smt_idx; /* SMT index */ 63178302Skmacy uint16_t vlan; /* VLAN TCI (id: bits 0-11, prio: 13-15 */ 64178302Skmacy struct l2t_entry *first; /* start of hash chain */ 65178302Skmacy struct l2t_entry *next; /* next l2t_entry on chain */ 66178302Skmacy struct mbuf *arpq_head; /* queue of packets awaiting resolution */ 67178302Skmacy struct mbuf *arpq_tail; 68178302Skmacy struct mtx lock; 69178302Skmacy volatile uint32_t refcnt; /* entry reference count */ 70237263Snp uint8_t dmac[ETHER_ADDR_LEN]; /* nexthop's MAC address */ 71178302Skmacy}; 72178302Skmacy 73178302Skmacystruct l2t_data { 74178302Skmacy unsigned int nentries; /* number of entries */ 75178302Skmacy struct l2t_entry *rover; /* starting point for next allocation */ 76178302Skmacy volatile uint32_t nfree; /* number of free entries */ 77178302Skmacy struct rwlock lock; 78178302Skmacy struct l2t_entry l2tab[0]; 79178302Skmacy}; 80178302Skmacy 81237263Snpvoid t3_l2e_free(struct l2t_data *, struct l2t_entry *e); 82237263Snpvoid t3_l2_update(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa, 83237263Snp uint8_t *lladdr, uint16_t vtag); 84237263Snpstruct l2t_entry *t3_l2t_get(struct port_info *, struct ifnet *, 85237263Snp struct sockaddr *); 86237263Snpint t3_l2t_send_slow(struct adapter *, struct mbuf *, struct l2t_entry *); 87237263Snpstruct l2t_data *t3_init_l2t(unsigned int); 88237263Snpvoid t3_free_l2t(struct l2t_data *); 89237263Snpvoid t3_init_l2t_cpl_handlers(struct adapter *); 90178302Skmacy 91237263Snpstatic inline int 92237263Snpl2t_send(struct adapter *sc, struct mbuf *m, struct l2t_entry *e) 93178302Skmacy{ 94237263Snp if (__predict_true(e->state == L2T_STATE_VALID)) 95237263Snp return t3_offload_tx(sc, m); 96237263Snp else 97237263Snp return t3_l2t_send_slow(sc, m, e); 98178302Skmacy} 99178302Skmacy 100237263Snpstatic inline void 101237263Snpl2t_release(struct l2t_data *d, struct l2t_entry *e) 102178302Skmacy{ 103237263Snp if (atomic_fetchadd_int(&e->refcnt, -1) == 1) /* 1 -> 0 transition */ 104237263Snp atomic_add_int(&d->nfree, 1); 105178302Skmacy} 106178302Skmacy 107237263Snpstatic inline void 108237263Snpl2t_hold(struct l2t_data *d, struct l2t_entry *e) 109178302Skmacy{ 110237263Snp if (atomic_fetchadd_int(&e->refcnt, 1) == 0) /* 0 -> 1 transition */ 111237263Snp atomic_add_int(&d->nfree, -1); 112178302Skmacy} 113178302Skmacy 114178302Skmacy#endif 115