xref: /illumos-gate/usr/src/uts/common/io/cxgbe/t4nex/t4_l2t.c (revision 694256dd32d74a4f9f88eebe42e3e7f9f7576c48)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source. A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * This file is part of the Chelsio T4 support code.
14  *
15  * Copyright (C) 2010-2013 Chelsio Communications.  All rights reserved.
16  *
17  * This program is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
20  * release for licensing terms and conditions.
21  */
22 
23 #include <sys/ddi.h>
24 #include <sys/sunddi.h>
25 #include <sys/sunndi.h>
26 #include <sys/atomic.h>
27 #include <sys/dlpi.h>
28 #include <sys/pattr.h>
29 #include <sys/strsubr.h>
30 #include <sys/stream.h>
31 #include <sys/strsun.h>
32 #include <sys/ethernet.h>
33 #include <sys/containerof.h>
34 #include <inet/ip.h>
35 #include <inet/ipclassifier.h>
36 #include <inet/tcp.h>
37 
38 #include "common/common.h"
39 #include "common/t4_msg.h"
40 #include "common/t4_regs.h"
41 #include "common/t4_regs_values.h"
42 #include "t4_l2t.h"
43 
44 /* identifies sync vs async L2T_WRITE_REQs */
45 #define	S_SYNC_WR	12
46 #define	V_SYNC_WR(x)	((x) << S_SYNC_WR)
47 #define	F_SYNC_WR	V_SYNC_WR(1)
48 #define	VLAN_NONE	0xfff
49 
50 /*
51  * jhash.h: Jenkins hash support.
52  *
53  * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
54  *
55  * http://burtleburtle.net/bob/hash/
56  *
57  * These are the credits from Bob's sources:
58  *
59  * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
60  * hash(), hash2(), hash3, and mix() are externally useful functions.
61  * Routines to test the hash are included if SELF_TEST is defined.
62  * You can use this free for any purpose.  It has no warranty.
63  */
64 
65 /* NOTE: Arguments are modified. */
66 #define	__jhash_mix(a, b, c) \
67 { \
68 	a -= b; a -= c; a ^= (c>>13); \
69 	b -= c; b -= a; b ^= (a<<8); \
70 	c -= a; c -= b; c ^= (b>>13); \
71 	a -= b; a -= c; a ^= (c>>12);  \
72 	b -= c; b -= a; b ^= (a<<16); \
73 	c -= a; c -= b; c ^= (b>>5); \
74 	a -= b; a -= c; a ^= (c>>3);  \
75 	b -= c; b -= a; b ^= (a<<10); \
76 	c -= a; c -= b; c ^= (b>>15); \
77 }
78 
79 /* The golden ration: an arbitrary value */
80 #define	JHASH_GOLDEN_RATIO	0x9e3779b9
81 
82 /*
83  * A special ultra-optimized versions that knows they are hashing exactly
84  * 3, 2 or 1 word(s).
85  *
86  * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
87  *	 done at the end is not done here.
88  */
89 static inline u32
90 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
91 {
92 	a += JHASH_GOLDEN_RATIO;
93 	b += JHASH_GOLDEN_RATIO;
94 	c += initval;
95 
96 	__jhash_mix(a, b, c);
97 
98 	return (c);
99 }
100 
101 static inline u32
102 jhash_2words(u32 a, u32 b, u32 initval)
103 {
104 	return (jhash_3words(a, b, 0, initval));
105 }
106 
107 #if defined(__GNUC__)
108 #define	likely(x)	__builtin_expect((x), 1)
109 #define	unlikely(x)	__builtin_expect((x), 0)
110 #else
111 #define	likely(x)	(x)
112 #define	unlikely(x)	(x)
113 #endif /* defined(__GNUC__) */
114 
115 enum {
116 	L2T_STATE_VALID,	/* entry is up to date */
117 	L2T_STATE_STALE,	/* entry may be used but needs revalidation */
118 	L2T_STATE_RESOLVING,	/* entry needs address resolution */
119 	L2T_STATE_SYNC_WRITE,	/* synchronous write of entry underway */
120 
121 	/* when state is one of the below the entry is not hashed */
122 	L2T_STATE_SWITCHING,	/* entry is being used by a switching filter */
123 	L2T_STATE_UNUSED	/* entry not in use */
124 };
125 
126 struct l2t_data {
127 	krwlock_t lock;
128 	u_int l2t_size;
129 	volatile uint_t nfree;	 /* number of free entries */
130 	struct l2t_entry *rover; /* starting point for next allocation */
131 	struct l2t_entry l2tab[];
132 };
133 
134 #define	VLAN_NONE	0xfff
135 #define	SA(x)		((struct sockaddr *)(x))
136 #define	SIN(x)		((struct sockaddr_in *)(x))
137 #define	SINADDR(x)	(SIN(x)->sin_addr.s_addr)
138 #define	atomic_read(x) atomic_add_int_nv(x, 0)
139 
140 struct l2t_data *
141 t4_init_l2t(struct adapter *sc)
142 {
143 	int i, l2t_size;
144 	struct l2t_data *d;
145 
146 	l2t_size = sc->vres.l2t.size;
147 	if(l2t_size < 1)
148 		return (NULL);
149 
150 	d = kmem_zalloc(sizeof(*d) + l2t_size * sizeof (struct l2t_entry), KM_SLEEP);
151 	if (!d)
152 		return (NULL);
153 
154 	d->l2t_size = l2t_size;
155 
156 	d->rover = d->l2tab;
157 	(void) atomic_swap_uint(&d->nfree, l2t_size);
158 	rw_init(&d->lock, NULL, RW_DRIVER, NULL);
159 
160 	for (i = 0; i < l2t_size; i++) {
161 		/* LINTED: E_ASSIGN_NARROW_CONV */
162 		d->l2tab[i].idx = i;
163 		d->l2tab[i].state = L2T_STATE_UNUSED;
164 		mutex_init(&d->l2tab[i].lock, NULL, MUTEX_DRIVER, NULL);
165 		(void) atomic_swap_uint(&d->l2tab[i].refcnt, 0);
166 	}
167 
168 	return (d);
169 }
170 
171 int
172 t4_free_l2t(struct l2t_data *d)
173 {
174 	int i;
175 
176 	for (i = 0; i < L2T_SIZE; i++)
177 		mutex_destroy(&d->l2tab[i].lock);
178 	rw_destroy(&d->lock);
179 	kmem_free(d, sizeof (*d));
180 
181 	return (0);
182 }
183