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