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