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