1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <hxge_impl.h>
28 #include <hxge_classify.h>
29 #include <hxge_pfc.h>
30 #include <hpi_pfc.h>
31 #include <sys/ethernet.h>
32
33 static uint32_t crc32_mchash(p_ether_addr_t addr);
34 static hxge_status_t hxge_pfc_load_hash_table(p_hxge_t hxgep);
35 static uint32_t hxge_get_blade_id(p_hxge_t hxgep);
36 static hxge_status_t hxge_tcam_default_add_entry(p_hxge_t hxgep,
37 tcam_class_t class);
38 static hxge_status_t hxge_tcam_default_config(p_hxge_t hxgep);
39
40 hxge_status_t
hxge_classify_init(p_hxge_t hxgep)41 hxge_classify_init(p_hxge_t hxgep)
42 {
43 hxge_status_t status = HXGE_OK;
44
45 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init"));
46
47 status = hxge_classify_init_sw(hxgep);
48 if (status != HXGE_OK)
49 return (status);
50
51 status = hxge_classify_init_hw(hxgep);
52 if (status != HXGE_OK) {
53 (void) hxge_classify_exit_sw(hxgep);
54 return (status);
55 }
56
57 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init"));
58
59 return (HXGE_OK);
60 }
61
62 hxge_status_t
hxge_classify_uninit(p_hxge_t hxgep)63 hxge_classify_uninit(p_hxge_t hxgep)
64 {
65 return (hxge_classify_exit_sw(hxgep));
66 }
67
68 static hxge_status_t
hxge_tcam_dump_entry(p_hxge_t hxgep,uint32_t location)69 hxge_tcam_dump_entry(p_hxge_t hxgep, uint32_t location)
70 {
71 hxge_tcam_entry_t tcam_rdptr;
72 uint64_t asc_ram = 0;
73 hpi_handle_t handle;
74 hpi_status_t status;
75
76 handle = hxgep->hpi_reg_handle;
77
78 /* Retrieve the saved entry */
79 bcopy((void *)&hxgep->classifier.tcam_entries[location].tce,
80 (void *)&tcam_rdptr, sizeof (hxge_tcam_entry_t));
81
82 /* Compare the entry */
83 status = hpi_pfc_tcam_entry_read(handle, location, &tcam_rdptr);
84 if (status == HPI_FAILURE) {
85 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
86 " hxge_tcam_dump_entry: tcam read failed at location %d ",
87 location));
88 return (HXGE_ERROR);
89 }
90
91 status = hpi_pfc_tcam_asc_ram_entry_read(handle, location, &asc_ram);
92
93 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "location %x\n"
94 " key: %llx %llx\n mask: %llx %llx\n ASC RAM %llx \n", location,
95 tcam_rdptr.key0, tcam_rdptr.key1,
96 tcam_rdptr.mask0, tcam_rdptr.mask1, asc_ram));
97 return (HXGE_OK);
98 }
99
100 void
hxge_get_tcam(p_hxge_t hxgep,p_mblk_t mp)101 hxge_get_tcam(p_hxge_t hxgep, p_mblk_t mp)
102 {
103 uint32_t tcam_loc;
104 uint32_t *lptr;
105 int location;
106 int start_location = 0;
107 int stop_location = hxgep->classifier.tcam_size;
108
109 lptr = (uint32_t *)mp->b_rptr;
110 location = *lptr;
111
112 if ((location >= hxgep->classifier.tcam_size) || (location < -1)) {
113 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
114 "hxge_tcam_dump: Invalid location %d \n", location));
115 return;
116 }
117 if (location == -1) {
118 start_location = 0;
119 stop_location = hxgep->classifier.tcam_size;
120 } else {
121 start_location = location;
122 stop_location = location + 1;
123 }
124 for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
125 (void) hxge_tcam_dump_entry(hxgep, tcam_loc);
126 }
127
128 /*ARGSUSED*/
129 static hxge_status_t
hxge_add_tcam_entry(p_hxge_t hxgep,flow_resource_t * flow_res)130 hxge_add_tcam_entry(p_hxge_t hxgep, flow_resource_t *flow_res)
131 {
132 return (HXGE_OK);
133 }
134
135 void
hxge_put_tcam(p_hxge_t hxgep,p_mblk_t mp)136 hxge_put_tcam(p_hxge_t hxgep, p_mblk_t mp)
137 {
138 flow_resource_t *fs;
139 fs = (flow_resource_t *)mp->b_rptr;
140
141 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
142 "hxge_put_tcam addr fs $%p type %x offset %x",
143 fs, fs->flow_spec.flow_type, fs->channel_cookie));
144
145 (void) hxge_add_tcam_entry(hxgep, fs);
146 }
147
148 static uint32_t
hxge_get_blade_id(p_hxge_t hxgep)149 hxge_get_blade_id(p_hxge_t hxgep)
150 {
151 phy_debug_training_vec_t blade_id;
152
153 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_get_blade_id"));
154 HXGE_REG_RD32(hxgep->hpi_reg_handle, PHY_DEBUG_TRAINING_VEC,
155 &blade_id.value);
156 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_get_blade_id: id = %d",
157 blade_id.bits.bld_num));
158
159 return (blade_id.bits.bld_num);
160 }
161
162 static hxge_status_t
hxge_tcam_default_add_entry(p_hxge_t hxgep,tcam_class_t class)163 hxge_tcam_default_add_entry(p_hxge_t hxgep, tcam_class_t class)
164 {
165 hpi_status_t rs = HPI_SUCCESS;
166 uint32_t location;
167 hxge_tcam_entry_t entry;
168 hxge_tcam_spread_t *key = NULL;
169 hxge_tcam_spread_t *mask = NULL;
170 hpi_handle_t handle;
171 p_hxge_hw_list_t hw_p;
172
173 if ((hw_p = hxgep->hxge_hw_p) == NULL) {
174 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
175 " hxge_tcam_default_add_entry: common hardware not set"));
176 return (HXGE_ERROR);
177 }
178
179 bzero(&entry, sizeof (hxge_tcam_entry_t));
180
181 /*
182 * The class id and blade id are common for all classes
183 * Only use the blade id for matching and the rest are wild cards.
184 * This will allow one TCAM entry to match all traffic in order
185 * to spread the traffic using source hash.
186 */
187 key = &entry.key.spread;
188 mask = &entry.mask.spread;
189
190 key->blade_id = hxge_get_blade_id(hxgep);
191
192 mask->class_code = 0xf;
193 mask->class_code_l = 0x1;
194 mask->blade_id = 0;
195 mask->wild1 = 0x7ffffff;
196 mask->wild = 0xffffffff;
197 mask->wild_l = 0xffffffff;
198
199 location = class;
200
201 handle = hxgep->hpi_reg_handle;
202
203 MUTEX_ENTER(&hw_p->hxge_tcam_lock);
204 rs = hpi_pfc_tcam_entry_write(handle, location, &entry);
205 if (rs & HPI_PFC_ERROR) {
206 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
207 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
208 " hxge_tcam_default_add_entry tcam entry write"
209 " failed for location %d", location));
210 return (HXGE_ERROR);
211 }
212
213 /* Add the associative portion */
214 entry.match_action.value = 0;
215
216 /* Use source hash to spread traffic */
217 entry.match_action.bits.channel_d = 0;
218 entry.match_action.bits.channel_c = 1;
219 entry.match_action.bits.channel_b = 2;
220 entry.match_action.bits.channel_a = 3;
221 entry.match_action.bits.source_hash = 1;
222 entry.match_action.bits.discard = 0;
223
224 rs = hpi_pfc_tcam_asc_ram_entry_write(handle,
225 location, entry.match_action.value);
226 if (rs & HPI_PFC_ERROR) {
227 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
228 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
229 " hxge_tcam_default_add_entry tcam entry write"
230 " failed for ASC RAM location %d", location));
231 return (HXGE_ERROR);
232 }
233
234 bcopy((void *) &entry,
235 (void *) &hxgep->classifier.tcam_entries[location].tce,
236 sizeof (hxge_tcam_entry_t));
237
238 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
239
240 return (HXGE_OK);
241 }
242
243 /*
244 * Configure one TCAM entry for each class and make it match
245 * everything within the class in order to spread the traffic
246 * among the DMA channels based on the source hash.
247 *
248 * This is the default for now. This may change when Crossbow is
249 * available for configuring TCAM.
250 */
251 static hxge_status_t
hxge_tcam_default_config(p_hxge_t hxgep)252 hxge_tcam_default_config(p_hxge_t hxgep)
253 {
254 uint8_t class;
255 uint32_t class_config;
256 hxge_status_t status = HXGE_OK;
257
258 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_tcam_default_config"));
259
260 /*
261 * Add TCAM and its associative ram entries
262 * A wild card will be used for the class code in order to match
263 * any classes.
264 */
265 class = 0;
266 status = hxge_tcam_default_add_entry(hxgep, class);
267 if (status != HXGE_OK) {
268 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
269 "hxge_tcam_default_config "
270 "hxge_tcam_default_add_entry failed class %d ",
271 class));
272 return (HXGE_ERROR);
273 }
274
275 /* Enable the classes */
276 for (class = TCAM_CLASS_TCP_IPV4;
277 class <= TCAM_CLASS_SCTP_IPV6; class++) {
278 /*
279 * By default, it is set to HXGE_CLASS_TCAM_LOOKUP in
280 * hxge_ndd.c. It may be overwritten in hxge.conf.
281 */
282 class_config = hxgep->class_config.class_cfg[class];
283
284 status = hxge_pfc_ip_class_config(hxgep, class, class_config);
285 if (status & HPI_PFC_ERROR) {
286 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
287 "hxge_tcam_default_config "
288 "hxge_pfc_ip_class_config failed "
289 " class %d config %x ", class, class_config));
290 return (HXGE_ERROR);
291 }
292 }
293
294 status = hxge_pfc_config_tcam_enable(hxgep);
295
296 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_tcam_default_config"));
297
298 return (status);
299 }
300
301 hxge_status_t
hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)302 hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)
303 {
304 hxge_status_t status;
305
306 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_set_default_mac_addr"));
307
308 MUTEX_ENTER(&hxgep->ouraddr_lock);
309
310 /*
311 * Set new interface local address and re-init device.
312 * This is destructive to any other streams attached
313 * to this device.
314 */
315 RW_ENTER_WRITER(&hxgep->filter_lock);
316 status = hxge_pfc_set_mac_address(hxgep,
317 HXGE_MAC_DEFAULT_ADDR_SLOT, &hxgep->ouraddr);
318 RW_EXIT(&hxgep->filter_lock);
319
320 MUTEX_EXIT(&hxgep->ouraddr_lock);
321
322 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_set_default_mac_addr"));
323 return (status);
324 }
325
326 /*
327 * Add a multicast address entry into the HW hash table
328 */
329 hxge_status_t
hxge_add_mcast_addr(p_hxge_t hxgep,struct ether_addr * addrp)330 hxge_add_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
331 {
332 uint32_t mchash;
333 p_hash_filter_t hash_filter;
334 uint16_t hash_bit;
335 boolean_t rx_init = B_FALSE;
336 uint_t j;
337 hxge_status_t status = HXGE_OK;
338
339 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_add_mcast_addr"));
340
341 RW_ENTER_WRITER(&hxgep->filter_lock);
342 mchash = crc32_mchash(addrp);
343
344 if (hxgep->hash_filter == NULL) {
345 HXGE_DEBUG_MSG((NULL, STR_CTL,
346 "Allocating hash filter storage."));
347 hxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
348 KM_SLEEP);
349 }
350
351 hash_filter = hxgep->hash_filter;
352 /*
353 * Note that mchash is an 8 bit value and thus 0 <= mchash <= 255.
354 * Consequently, 0 <= j <= 15 and 0 <= mchash % HASH_REG_WIDTH <= 15.
355 */
356 j = mchash / HASH_REG_WIDTH;
357 hash_bit = (1 << (mchash % HASH_REG_WIDTH));
358 hash_filter->hash_filter_regs[j] |= hash_bit;
359
360 hash_filter->hash_bit_ref_cnt[mchash]++;
361 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
362 hash_filter->hash_ref_cnt++;
363 rx_init = B_TRUE;
364 }
365
366 if (rx_init) {
367 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
368 (void) hxge_pfc_load_hash_table(hxgep);
369 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_TRUE);
370 }
371
372 RW_EXIT(&hxgep->filter_lock);
373
374 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_add_mcast_addr"));
375
376 return (HXGE_OK);
377 fail:
378 RW_EXIT(&hxgep->filter_lock);
379 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_add_mcast_addr: "
380 "Unable to add multicast address"));
381
382 return (status);
383 }
384
385 /*
386 * Remove a multicast address entry from the HW hash table
387 */
388 hxge_status_t
hxge_del_mcast_addr(p_hxge_t hxgep,struct ether_addr * addrp)389 hxge_del_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
390 {
391 uint32_t mchash;
392 p_hash_filter_t hash_filter;
393 uint16_t hash_bit;
394 boolean_t rx_init = B_FALSE;
395 uint_t j;
396 hxge_status_t status = HXGE_OK;
397
398 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_del_mcast_addr"));
399 RW_ENTER_WRITER(&hxgep->filter_lock);
400 mchash = crc32_mchash(addrp);
401 if (hxgep->hash_filter == NULL) {
402 HXGE_DEBUG_MSG((NULL, STR_CTL,
403 "Hash filter already de_allocated."));
404 RW_EXIT(&hxgep->filter_lock);
405 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
406 return (HXGE_OK);
407 }
408
409 hash_filter = hxgep->hash_filter;
410 hash_filter->hash_bit_ref_cnt[mchash]--;
411 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
412 j = mchash / HASH_REG_WIDTH;
413 hash_bit = (1 << (mchash % HASH_REG_WIDTH));
414 hash_filter->hash_filter_regs[j] &= ~hash_bit;
415 hash_filter->hash_ref_cnt--;
416 rx_init = B_TRUE;
417 }
418
419 if (hash_filter->hash_ref_cnt == 0) {
420 HXGE_DEBUG_MSG((NULL, STR_CTL,
421 "De-allocating hash filter storage."));
422 KMEM_FREE(hash_filter, sizeof (hash_filter_t));
423 hxgep->hash_filter = NULL;
424 }
425
426 if (rx_init) {
427 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
428 (void) hxge_pfc_load_hash_table(hxgep);
429
430 /* Enable hash only if there are any hash entries */
431 if (hxgep->hash_filter != NULL)
432 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle,
433 B_TRUE);
434 }
435
436 RW_EXIT(&hxgep->filter_lock);
437 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
438
439 return (HXGE_OK);
440 fail:
441 RW_EXIT(&hxgep->filter_lock);
442 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_del_mcast_addr: "
443 "Unable to remove multicast address"));
444
445 return (status);
446 }
447
448 hxge_status_t
hxge_pfc_clear_mac_address(p_hxge_t hxgep,uint32_t slot)449 hxge_pfc_clear_mac_address(p_hxge_t hxgep, uint32_t slot)
450 {
451 hpi_status_t status;
452
453 status = hpi_pfc_clear_mac_address(hxgep->hpi_reg_handle, slot);
454 if (status != HPI_SUCCESS)
455 return (HXGE_ERROR);
456
457 return (HXGE_OK);
458 }
459
460 hxge_status_t
hxge_pfc_set_mac_address(p_hxge_t hxgep,uint32_t slot,struct ether_addr * addrp)461 hxge_pfc_set_mac_address(p_hxge_t hxgep, uint32_t slot,
462 struct ether_addr *addrp)
463 {
464 hpi_handle_t handle;
465 uint64_t addr;
466 hpi_status_t hpi_status;
467 uint8_t *address = addrp->ether_addr_octet;
468 uint64_t tmp;
469 int i;
470
471 if (hxgep->hxge_hw_p == NULL) {
472 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
473 " hxge_pfc_set_mac_address: common hardware not set"));
474 return (HXGE_ERROR);
475 }
476
477 /*
478 * Convert a byte array to a 48 bit value.
479 * Need to check endianess if in doubt
480 */
481 addr = 0;
482 for (i = 0; i < ETHERADDRL; i++) {
483 tmp = address[i];
484 addr <<= 8;
485 addr |= tmp;
486 }
487
488 handle = hxgep->hpi_reg_handle;
489 hpi_status = hpi_pfc_set_mac_address(handle, slot, addr);
490
491 if (hpi_status != HPI_SUCCESS) {
492 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
493 " hxge_pfc_set_mac_address: failed to set address"));
494 return (HXGE_ERROR);
495 }
496
497 return (HXGE_OK);
498 }
499
500 /*ARGSUSED*/
501 hxge_status_t
hxge_pfc_num_macs_get(p_hxge_t hxgep,uint8_t * nmacs)502 hxge_pfc_num_macs_get(p_hxge_t hxgep, uint8_t *nmacs)
503 {
504 *nmacs = PFC_N_MAC_ADDRESSES;
505 return (HXGE_OK);
506 }
507
508
509 hxge_status_t
hxge_pfc_set_hash(p_hxge_t hxgep,uint32_t seed)510 hxge_pfc_set_hash(p_hxge_t hxgep, uint32_t seed)
511 {
512 hpi_status_t rs = HPI_SUCCESS;
513 hpi_handle_t handle;
514 p_hxge_class_pt_cfg_t p_class_cfgp;
515
516 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_set_hash"));
517
518 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
519 p_class_cfgp->init_hash = seed;
520 handle = hxgep->hpi_reg_handle;
521
522 rs = hpi_pfc_set_hash_seed_value(handle, seed);
523 if (rs & HPI_PFC_ERROR) {
524 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
525 " hxge_pfc_set_hash %x failed ", seed));
526 return (HXGE_ERROR | rs);
527 }
528
529 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " <== hxge_pfc_set_hash"));
530
531 return (HXGE_OK);
532 }
533
534 hxge_status_t
hxge_pfc_config_tcam_enable(p_hxge_t hxgep)535 hxge_pfc_config_tcam_enable(p_hxge_t hxgep)
536 {
537 hpi_handle_t handle;
538 boolean_t enable = B_TRUE;
539 hpi_status_t hpi_status;
540
541 handle = hxgep->hpi_reg_handle;
542 if (hxgep->hxge_hw_p == NULL) {
543 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
544 " hxge_pfc_config_tcam_enable: common hardware not set"));
545 return (HXGE_ERROR);
546 }
547
548 hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
549 if (hpi_status != HPI_SUCCESS) {
550 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
551 " hpi_pfc_set_tcam_enable: enable tcam failed"));
552 return (HXGE_ERROR);
553 }
554
555 return (HXGE_OK);
556 }
557
558 hxge_status_t
hxge_pfc_config_tcam_disable(p_hxge_t hxgep)559 hxge_pfc_config_tcam_disable(p_hxge_t hxgep)
560 {
561 hpi_handle_t handle;
562 boolean_t enable = B_FALSE;
563 hpi_status_t hpi_status;
564
565 handle = hxgep->hpi_reg_handle;
566 if (hxgep->hxge_hw_p == NULL) {
567 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
568 " hxge_pfc_config_tcam_disable: common hardware not set"));
569 return (HXGE_ERROR);
570 }
571
572 hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
573 if (hpi_status != HPI_SUCCESS) {
574 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
575 " hpi_pfc_set_tcam_enable: disable tcam failed"));
576 return (HXGE_ERROR);
577 }
578
579 return (HXGE_OK);
580 }
581
582 static hxge_status_t
hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep,tcam_class_t class,uint32_t * class_config)583 hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep, tcam_class_t class,
584 uint32_t *class_config)
585 {
586 hpi_status_t rs = HPI_SUCCESS;
587 tcam_key_cfg_t cfg;
588 hpi_handle_t handle;
589 uint32_t ccfg = 0;
590
591 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_cfg_tcam_ip_class_get"));
592
593 bzero(&cfg, sizeof (tcam_key_cfg_t));
594 handle = hxgep->hpi_reg_handle;
595
596 rs = hpi_pfc_get_l3_class_config(handle, class, &cfg);
597 if (rs & HPI_PFC_ERROR) {
598 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
599 " hxge_cfg_tcam_ip_class opt %x for class %d failed ",
600 class_config, class));
601 return (HXGE_ERROR | rs);
602 }
603 if (cfg.discard)
604 ccfg |= HXGE_CLASS_DISCARD;
605
606 if (cfg.lookup_enable)
607 ccfg |= HXGE_CLASS_TCAM_LOOKUP;
608
609 *class_config = ccfg;
610
611 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_cfg_tcam_ip_class_get %x",
612 ccfg));
613
614 return (HXGE_OK);
615 }
616
617 hxge_status_t
hxge_pfc_ip_class_config_get(p_hxge_t hxgep,tcam_class_t class,uint32_t * config)618 hxge_pfc_ip_class_config_get(p_hxge_t hxgep, tcam_class_t class,
619 uint32_t *config)
620 {
621 uint32_t t_class_config;
622 int t_status = HXGE_OK;
623
624 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config_get"));
625 t_class_config = 0;
626 t_status = hxge_cfg_tcam_ip_class_get(hxgep, class, &t_class_config);
627
628 if (t_status & HPI_PFC_ERROR) {
629 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
630 " hxge_pfc_ip_class_config_get for class %d tcam failed",
631 class));
632 return (t_status);
633 }
634
635 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " hxge_pfc_ip_class_config tcam %x",
636 t_class_config));
637
638 *config = t_class_config;
639
640 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_get"));
641 return (HXGE_OK);
642 }
643
644 static hxge_status_t
hxge_pfc_config_init(p_hxge_t hxgep)645 hxge_pfc_config_init(p_hxge_t hxgep)
646 {
647 hpi_handle_t handle;
648 block_reset_t reset_reg;
649
650 handle = hxgep->hpi_reg_handle;
651 if (hxgep->hxge_hw_p == NULL) {
652 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
653 " hxge_pfc_config_init: common hardware not set"));
654 return (HXGE_ERROR);
655 }
656
657 /* Reset PFC block from PEU to clear any previous state */
658 reset_reg.value = 0;
659 reset_reg.bits.pfc_rst = 1;
660 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value);
661 HXGE_DELAY(1000);
662
663 (void) hpi_pfc_set_tcam_enable(handle, B_FALSE);
664 (void) hpi_pfc_set_l2_hash(handle, B_FALSE);
665 (void) hpi_pfc_set_tcp_cksum(handle, B_TRUE);
666 (void) hpi_pfc_set_default_dma(handle, 0);
667 (void) hpi_pfc_mac_addr_enable(handle, 0);
668 (void) hpi_pfc_set_force_csum(handle, B_FALSE);
669
670 /* Set the drop log mask to ignore the logs */
671 (void) hpi_pfc_set_drop_log_mask(handle, 1, 1, 1, 1, 1);
672
673 /* Clear the interrupt masks to receive interrupts */
674 (void) hpi_pfc_set_interrupt_mask(handle, 0, 0, 0);
675
676 /* Clear the interrupt status */
677 (void) hpi_pfc_clear_interrupt_status(handle);
678
679 return (HXGE_OK);
680 }
681
682 static hxge_status_t
hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)683 hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)
684 {
685 hpi_status_t rs = HPI_SUCCESS;
686 hpi_handle_t handle;
687 p_hxge_hw_list_t hw_p;
688
689 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
690 "==> hxge_pfc_tcam_invalidate_all"));
691 handle = hxgep->hpi_reg_handle;
692 if ((hw_p = hxgep->hxge_hw_p) == NULL) {
693 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
694 " hxge_pfc_tcam_invalidate_all: common hardware not set"));
695 return (HXGE_ERROR);
696 }
697
698 MUTEX_ENTER(&hw_p->hxge_tcam_lock);
699 rs = hpi_pfc_tcam_invalidate_all(handle);
700 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
701
702 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_invalidate_all"));
703 if (rs != HPI_SUCCESS)
704 return (HXGE_ERROR);
705
706 return (HXGE_OK);
707 }
708
709 static hxge_status_t
hxge_pfc_tcam_init(p_hxge_t hxgep)710 hxge_pfc_tcam_init(p_hxge_t hxgep)
711 {
712 hpi_status_t rs = HPI_SUCCESS;
713 hpi_handle_t handle;
714
715 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_tcam_init"));
716 handle = hxgep->hpi_reg_handle;
717
718 if (hxgep->hxge_hw_p == NULL) {
719 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
720 " hxge_pfc_tcam_init: common hardware not set"));
721 return (HXGE_ERROR);
722 }
723
724 /*
725 * Disable the TCAM.
726 */
727 rs = hpi_pfc_set_tcam_enable(handle, B_FALSE);
728 if (rs != HPI_SUCCESS) {
729 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
730 return (HXGE_ERROR | rs);
731 }
732
733 /*
734 * Invalidate all the TCAM entries for this blade.
735 */
736 rs = hxge_pfc_tcam_invalidate_all(hxgep);
737 if (rs != HPI_SUCCESS) {
738 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
739 return (HXGE_ERROR | rs);
740 }
741
742 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_init"));
743 return (HXGE_OK);
744 }
745
746 static hxge_status_t
hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)747 hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)
748 {
749 hpi_handle_t handle;
750 hpi_status_t rs = HPI_SUCCESS;
751 p_hxge_hw_list_t hw_p;
752
753 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_vlan_tbl_clear_all "));
754
755 handle = hxgep->hpi_reg_handle;
756 if ((hw_p = hxgep->hxge_hw_p) == NULL) {
757 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
758 " hxge_pfc_vlan_tbl_clear_all: common hardware not set"));
759 return (HXGE_ERROR);
760 }
761
762 MUTEX_ENTER(&hw_p->hxge_vlan_lock);
763 rs = hpi_pfc_cfg_vlan_table_clear(handle);
764 MUTEX_EXIT(&hw_p->hxge_vlan_lock);
765
766 if (rs != HPI_SUCCESS) {
767 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
768 "failed vlan table clear\n"));
769 return (HXGE_ERROR | rs);
770 }
771
772 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_vlan_tbl_clear_all "));
773 return (HXGE_OK);
774 }
775
776 hxge_status_t
hxge_pfc_ip_class_config(p_hxge_t hxgep,tcam_class_t class,uint32_t config)777 hxge_pfc_ip_class_config(p_hxge_t hxgep, tcam_class_t class, uint32_t config)
778 {
779 uint32_t class_config;
780 p_hxge_class_pt_cfg_t p_class_cfgp;
781 tcam_key_cfg_t cfg;
782 hpi_handle_t handle;
783 hpi_status_t rs = HPI_SUCCESS;
784
785 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config"));
786 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
787 class_config = p_class_cfgp->class_cfg[class];
788
789 if (class_config != config) {
790 p_class_cfgp->class_cfg[class] = config;
791 class_config = config;
792 }
793
794 handle = hxgep->hpi_reg_handle;
795
796 if (class == TCAM_CLASS_ETYPE_1 || class == TCAM_CLASS_ETYPE_2) {
797 rs = hpi_pfc_set_l2_class_slot(handle,
798 class_config & HXGE_CLASS_ETHER_TYPE_MASK,
799 class_config & HXGE_CLASS_VALID,
800 class - TCAM_CLASS_ETYPE_1);
801 } else {
802 if (class_config & HXGE_CLASS_DISCARD)
803 cfg.discard = 1;
804 else
805 cfg.discard = 0;
806 if (class_config & HXGE_CLASS_TCAM_LOOKUP)
807 cfg.lookup_enable = 1;
808 else
809 cfg.lookup_enable = 0;
810
811 rs = hpi_pfc_set_l3_class_config(handle, class, cfg);
812 }
813
814 if (rs & HPI_PFC_ERROR) {
815 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
816 " hxge_pfc_ip_class_config %x for class %d tcam failed",
817 config, class));
818 return (HXGE_ERROR);
819 }
820
821 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config"));
822 return (HXGE_OK);
823 }
824
825 hxge_status_t
hxge_pfc_ip_class_config_all(p_hxge_t hxgep)826 hxge_pfc_ip_class_config_all(p_hxge_t hxgep)
827 {
828 uint32_t class_config;
829 tcam_class_t cl;
830 int status = HXGE_OK;
831
832 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_ip_class_config_all"));
833
834 for (cl = TCAM_CLASS_ETYPE_1; cl <= TCAM_CLASS_SCTP_IPV6; cl++) {
835 if (cl == TCAM_CLASS_RESERVED_4 ||
836 cl == TCAM_CLASS_RESERVED_5 ||
837 cl == TCAM_CLASS_RESERVED_6 ||
838 cl == TCAM_CLASS_RESERVED_7)
839 continue;
840
841 class_config = hxgep->class_config.class_cfg[cl];
842 status = hxge_pfc_ip_class_config(hxgep, cl, class_config);
843 if (status & HPI_PFC_ERROR) {
844 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
845 "hxge_pfc_ip_class_config failed "
846 " class %d config %x ", cl, class_config));
847 }
848 }
849
850 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_all"));
851 return (HXGE_OK);
852 }
853
854 static hxge_status_t
hxge_pfc_update_hw(p_hxge_t hxgep)855 hxge_pfc_update_hw(p_hxge_t hxgep)
856 {
857 hxge_status_t status = HXGE_OK;
858 hpi_handle_t handle;
859 p_hxge_param_t pa;
860 int i;
861 boolean_t parity = 0;
862 boolean_t implicit_valid = 0;
863 vlan_id_t implicit_vlan_id;
864 uint32_t vlanid_group;
865 uint64_t offset;
866 int max_vlan_groups;
867 int vlan_group_step;
868
869 p_hxge_class_pt_cfg_t p_class_cfgp;
870
871 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_update_hw"));
872 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
873 handle = hxgep->hpi_reg_handle;
874
875 status = hxge_pfc_set_hash(hxgep, p_class_cfgp->init_hash);
876 if (status != HXGE_OK) {
877 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "hxge_pfc_set_hash Failed"));
878 return (HXGE_ERROR);
879 }
880
881 /*
882 * configure vlan table to join all vlans in order for Solaris
883 * network to receive vlan packets of any acceptible VIDs.
884 * This may change when Solaris network passes VIDs down.
885 */
886 vlanid_group = 0xffffffff;
887 max_vlan_groups = 128;
888 vlan_group_step = 8;
889 for (i = 0; i < max_vlan_groups; i++) {
890 offset = PFC_VLAN_TABLE + i * vlan_group_step;
891 REG_PIO_WRITE64(handle, offset, vlanid_group);
892 }
893
894 /* Configure the vlan_ctrl register */
895 /* Let hw generate the parity bits in pfc_vlan_table */
896 parity = 0;
897
898 pa = (p_hxge_param_t)&hxgep->param_arr[param_implicit_vlan_id];
899 implicit_vlan_id = (vlan_id_t)pa->value;
900
901 /*
902 * Enable it only if there is a valid implicity vlan id either in
903 * NDD table or the .conf file.
904 */
905 if (implicit_vlan_id >= VLAN_ID_MIN && implicit_vlan_id <= VLAN_ID_MAX)
906 implicit_valid = 1;
907
908 status = hpi_pfc_cfg_vlan_control_set(handle, parity, implicit_valid,
909 implicit_vlan_id);
910 if (status != HPI_SUCCESS) {
911 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
912 "hxge_pfc_update_hw: hpi_pfc_cfg_vlan_control_set failed"));
913 return (HXGE_ERROR);
914 }
915
916 /* config MAC addresses */
917 /* Need to think about this */
918
919 /* Configure hash value and classes */
920 status = hxge_pfc_ip_class_config_all(hxgep);
921 if (status != HXGE_OK) {
922 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
923 "hxge_pfc_ip_class_config_all Failed"));
924 return (HXGE_ERROR);
925 }
926
927 return (HXGE_OK);
928 }
929
930 hxge_status_t
hxge_pfc_hw_reset(p_hxge_t hxgep)931 hxge_pfc_hw_reset(p_hxge_t hxgep)
932 {
933 hxge_status_t status = HXGE_OK;
934
935 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_hw_reset"));
936
937 status = hxge_pfc_config_init(hxgep);
938 if (status != HXGE_OK) {
939 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
940 "failed PFC config init."));
941 return (status);
942 }
943
944 status = hxge_pfc_tcam_init(hxgep);
945 if (status != HXGE_OK) {
946 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM init."));
947 return (status);
948 }
949
950 /*
951 * invalidate VLAN RDC tables
952 */
953 status = hxge_pfc_vlan_tbl_clear_all(hxgep);
954 if (status != HXGE_OK) {
955 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
956 "failed VLAN Table Invalidate. "));
957 return (status);
958 }
959 hxgep->classifier.state |= HXGE_PFC_HW_RESET;
960
961 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_hw_reset"));
962
963 return (HXGE_OK);
964 }
965
966 hxge_status_t
hxge_classify_init_hw(p_hxge_t hxgep)967 hxge_classify_init_hw(p_hxge_t hxgep)
968 {
969 hxge_status_t status = HXGE_OK;
970
971 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_hw"));
972
973 if (hxgep->classifier.state & HXGE_PFC_HW_INIT) {
974 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
975 "hxge_classify_init_hw already init"));
976 return (HXGE_OK);
977 }
978
979 /* Now do a real configuration */
980 status = hxge_pfc_update_hw(hxgep);
981 if (status != HXGE_OK) {
982 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
983 "hxge_pfc_update_hw failed"));
984 return (HXGE_ERROR);
985 }
986
987 status = hxge_tcam_default_config(hxgep);
988 if (status != HXGE_OK) {
989 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
990 "hxge_tcam_default_config failed"));
991 return (status);
992 }
993
994 hxgep->classifier.state |= HXGE_PFC_HW_INIT;
995
996 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_hw"));
997
998 return (HXGE_OK);
999 }
1000
1001 hxge_status_t
hxge_classify_init_sw(p_hxge_t hxgep)1002 hxge_classify_init_sw(p_hxge_t hxgep)
1003 {
1004 int alloc_size;
1005 hxge_classify_t *classify_ptr;
1006
1007 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_sw"));
1008 classify_ptr = &hxgep->classifier;
1009
1010 if (classify_ptr->state & HXGE_PFC_SW_INIT) {
1011 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
1012 "hxge_classify_init_sw already init"));
1013 return (HXGE_OK);
1014 }
1015
1016 /* Init SW structures */
1017 classify_ptr->tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY;
1018
1019 alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size;
1020 classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, KM_SLEEP);
1021 bzero(classify_ptr->class_usage, sizeof (classify_ptr->class_usage));
1022
1023 /* Start from the beginning of TCAM */
1024 hxgep->classifier.tcam_location = 0;
1025 classify_ptr->state |= HXGE_PFC_SW_INIT;
1026
1027 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_sw"));
1028
1029 return (HXGE_OK);
1030 }
1031
1032 hxge_status_t
hxge_classify_exit_sw(p_hxge_t hxgep)1033 hxge_classify_exit_sw(p_hxge_t hxgep)
1034 {
1035 int alloc_size;
1036 hxge_classify_t *classify_ptr;
1037 int fsize;
1038
1039 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_exit_sw"));
1040 classify_ptr = &hxgep->classifier;
1041
1042 fsize = sizeof (tcam_flow_spec_t);
1043 if (classify_ptr->tcam_entries) {
1044 alloc_size = fsize * classify_ptr->tcam_size;
1045 KMEM_FREE((void *) classify_ptr->tcam_entries, alloc_size);
1046 }
1047 hxgep->classifier.state = 0;
1048
1049 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_exit_sw"));
1050
1051 return (HXGE_OK);
1052 }
1053
1054 /*ARGSUSED*/
1055 hxge_status_t
hxge_pfc_handle_sys_errors(p_hxge_t hxgep)1056 hxge_pfc_handle_sys_errors(p_hxge_t hxgep)
1057 {
1058 return (HXGE_OK);
1059 }
1060
1061 uint_t
hxge_pfc_intr(caddr_t arg1,caddr_t arg2)1062 hxge_pfc_intr(caddr_t arg1, caddr_t arg2)
1063 {
1064 p_hxge_ldv_t ldvp = (p_hxge_ldv_t)arg1;
1065 p_hxge_t hxgep = (p_hxge_t)arg2;
1066 hpi_handle_t handle;
1067 p_hxge_pfc_stats_t statsp;
1068 pfc_int_status_t int_status;
1069 pfc_bad_cs_counter_t bad_cs_count;
1070 pfc_drop_counter_t drop_count;
1071 pfc_drop_log_t drop_log;
1072 pfc_vlan_par_err_log_t vlan_par_err_log;
1073 pfc_tcam_par_err_log_t tcam_par_err_log;
1074
1075 if (ldvp == NULL) {
1076 HXGE_DEBUG_MSG((NULL, INT_CTL,
1077 "<== hxge_pfc_intr: hxgep $%p ldvp $%p", hxgep, ldvp));
1078 return (DDI_INTR_UNCLAIMED);
1079 }
1080
1081 if (arg2 == NULL || (void *) ldvp->hxgep != arg2) {
1082 hxgep = ldvp->hxgep;
1083 }
1084
1085 handle = hxgep->hpi_reg_handle;
1086 statsp = (p_hxge_pfc_stats_t)&hxgep->statsp->pfc_stats;
1087
1088 /*
1089 * need to read the pfc interrupt status register to figure out
1090 * what is happenning
1091 */
1092 (void) hpi_pfc_get_interrupt_status(handle, &int_status);
1093
1094 if (int_status.bits.pkt_drop) {
1095 statsp->pkt_drop++;
1096 if (statsp->pkt_drop == 1)
1097 HXGE_ERROR_MSG((hxgep, INT_CTL, "PFC pkt_drop"));
1098
1099 /* Collect each individual drops */
1100 (void) hpi_pfc_get_drop_log(handle, &drop_log);
1101
1102 if (drop_log.bits.tcp_ctrl_drop)
1103 statsp->errlog.tcp_ctrl_drop++;
1104 if (drop_log.bits.l2_addr_drop)
1105 statsp->errlog.l2_addr_drop++;
1106 if (drop_log.bits.class_code_drop)
1107 statsp->errlog.class_code_drop++;
1108 if (drop_log.bits.tcam_drop)
1109 statsp->errlog.tcam_drop++;
1110 if (drop_log.bits.vlan_drop)
1111 statsp->errlog.vlan_drop++;
1112
1113 /* Collect the total drops for all kinds */
1114 (void) hpi_pfc_get_drop_counter(handle, &drop_count.value);
1115 statsp->drop_count += drop_count.bits.drop_count;
1116 }
1117
1118 if (int_status.bits.tcam_parity_err) {
1119 statsp->tcam_parity_err++;
1120
1121 (void) hpi_pfc_get_tcam_parity_log(handle, &tcam_par_err_log);
1122 statsp->errlog.tcam_par_err_log = tcam_par_err_log.bits.addr;
1123
1124 if (statsp->tcam_parity_err == 1)
1125 HXGE_ERROR_MSG((hxgep,
1126 INT_CTL, " TCAM parity error addr: 0x%x",
1127 tcam_par_err_log.bits.addr));
1128 }
1129
1130 if (int_status.bits.vlan_parity_err) {
1131 statsp->vlan_parity_err++;
1132
1133 (void) hpi_pfc_get_vlan_parity_log(handle, &vlan_par_err_log);
1134 statsp->errlog.vlan_par_err_log = vlan_par_err_log.bits.addr;
1135
1136 if (statsp->vlan_parity_err == 1)
1137 HXGE_ERROR_MSG((hxgep, INT_CTL,
1138 " vlan table parity error addr: 0x%x",
1139 vlan_par_err_log.bits.addr));
1140 }
1141
1142 (void) hpi_pfc_get_bad_csum_counter(handle, &bad_cs_count.value);
1143 statsp->bad_cs_count += bad_cs_count.bits.bad_cs_count;
1144
1145 (void) hpi_pfc_clear_interrupt_status(handle);
1146 return (DDI_INTR_CLAIMED);
1147 }
1148
1149 static void
hxge_pfc_get_next_mac_addr(uint8_t * st_mac,struct ether_addr * final_mac)1150 hxge_pfc_get_next_mac_addr(uint8_t *st_mac, struct ether_addr *final_mac)
1151 {
1152 uint64_t mac[ETHERADDRL];
1153 uint64_t mac_addr = 0;
1154 int i, j;
1155
1156 for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) {
1157 mac[j] = st_mac[i];
1158 mac_addr |= (mac[j] << (j*8));
1159 }
1160
1161 final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40;
1162 final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32;
1163 final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24;
1164 final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16;
1165 final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8;
1166 final_mac->ether_addr_octet[5] = (mac_addr & 0xff);
1167 }
1168
1169 hxge_status_t
hxge_pfc_mac_addrs_get(p_hxge_t hxgep)1170 hxge_pfc_mac_addrs_get(p_hxge_t hxgep)
1171 {
1172 hxge_status_t status = HXGE_OK;
1173 hpi_status_t hpi_status = HPI_SUCCESS;
1174 hpi_handle_t handle = HXGE_DEV_HPI_HANDLE(hxgep);
1175 uint8_t mac_addr[ETHERADDRL];
1176
1177 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_mac_addr_get"));
1178
1179 hpi_status = hpi_pfc_mac_addr_get_i(handle, mac_addr, 0);
1180 if (hpi_status != HPI_SUCCESS) {
1181 status = (HXGE_ERROR | hpi_status);
1182 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1183 "hxge_pfc_mac_addr_get: pfc_mac_addr_get_i failed"));
1184 goto exit;
1185 }
1186
1187 hxge_pfc_get_next_mac_addr(mac_addr, &hxgep->factaddr);
1188 HXGE_ERROR_MSG((hxgep, PFC_CTL, "MAC Addr(0): %x:%x:%x:%x:%x:%x\n",
1189 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
1190 mac_addr[4], mac_addr[5]));
1191
1192 exit:
1193 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_pfc_mac_addr_get, "
1194 "status [0x%x]", status));
1195 return (status);
1196 }
1197
1198 /*
1199 * Calculate the bit in the multicast address filter
1200 * that selects the given * address.
1201 * Note: For Hydra, the last 8-bits are used.
1202 */
1203 static uint32_t
crc32_mchash(p_ether_addr_t addr)1204 crc32_mchash(p_ether_addr_t addr)
1205 {
1206 uint8_t *cp;
1207 uint32_t crc;
1208 uint32_t c;
1209 int byte;
1210 int bit;
1211
1212 cp = (uint8_t *)addr;
1213 crc = (uint32_t)0xffffffff;
1214 for (byte = 0; byte < ETHERADDRL; byte++) {
1215 /* Hydra calculates the hash backwardly */
1216 c = (uint32_t)cp[ETHERADDRL - 1 - byte];
1217 for (bit = 0; bit < 8; bit++) {
1218 if ((c & 0x1) ^ (crc & 0x1))
1219 crc = (crc >> 1)^0xedb88320;
1220 else
1221 crc = (crc >> 1);
1222 c >>= 1;
1223 }
1224 }
1225 return ((~crc) >> (32 - HASH_BITS));
1226 }
1227
1228 static hxge_status_t
hxge_pfc_load_hash_table(p_hxge_t hxgep)1229 hxge_pfc_load_hash_table(p_hxge_t hxgep)
1230 {
1231 uint32_t i;
1232 uint16_t hashtab_e;
1233 p_hash_filter_t hash_filter;
1234 hpi_handle_t handle;
1235
1236 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_load_hash_table\n"));
1237 handle = hxgep->hpi_reg_handle;
1238
1239 /*
1240 * Load the multicast hash filter bits.
1241 */
1242 hash_filter = hxgep->hash_filter;
1243 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
1244 if (hash_filter != NULL) {
1245 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[i];
1246 } else {
1247 hashtab_e = 0;
1248 }
1249
1250 if (hpi_pfc_set_multicast_hash_table(handle, i,
1251 hashtab_e) != HPI_SUCCESS)
1252 return (HXGE_ERROR);
1253 }
1254
1255 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_load_hash_table\n"));
1256
1257 return (HXGE_OK);
1258 }
1259