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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <nxge_impl.h> 29 #include <nxge_zcp.h> 30 #include <nxge_ipp.h> 31 32 nxge_status_t 33 nxge_zcp_init(p_nxge_t nxgep) 34 { 35 uint8_t portn; 36 npi_handle_t handle; 37 zcp_iconfig_t istatus; 38 npi_status_t rs = NPI_SUCCESS; 39 int i; 40 zcp_ram_unit_t w_data; 41 zcp_ram_unit_t r_data; 42 uint32_t cfifo_depth; 43 44 handle = nxgep->npi_handle; 45 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 46 47 if (nxgep->niu_type == N2_NIU) { 48 cfifo_depth = ZCP_NIU_CFIFO_DEPTH; 49 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep->niu_type)) { 50 if (portn < 2) 51 cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH; 52 else 53 cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH; 54 } else { 55 goto fail; 56 } 57 58 /* Clean up CFIFO */ 59 w_data.w0 = 0; 60 w_data.w1 = 0; 61 w_data.w2 = 0; 62 w_data.w3 = 0; 63 w_data.w4 = 0; 64 65 for (i = 0; i < cfifo_depth; i++) { 66 if (npi_zcp_tt_cfifo_entry(handle, OP_SET, 67 portn, i, &w_data) != NPI_SUCCESS) 68 goto fail; 69 if (npi_zcp_tt_cfifo_entry(handle, OP_GET, 70 portn, i, &r_data) != NPI_SUCCESS) 71 goto fail; 72 } 73 74 if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS) 75 goto fail; 76 77 /* 78 * Making sure that error source is cleared if this is an injected 79 * error. 80 */ 81 switch (portn) { 82 case 0: 83 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0); 84 break; 85 case 1: 86 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0); 87 break; 88 case 2: 89 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0); 90 break; 91 case 3: 92 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0); 93 break; 94 } 95 96 if ((rs = npi_zcp_clear_istatus(handle)) != NPI_SUCCESS) 97 return (NXGE_ERROR | rs); 98 if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS) 99 return (NXGE_ERROR | rs); 100 if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS) 101 goto fail; 102 103 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn)); 104 return (NXGE_OK); 105 106 fail: 107 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 108 "nxge_zcp_init: Fail to initialize ZCP Port #%d\n", portn)); 109 return (NXGE_ERROR | rs); 110 } 111 112 nxge_status_t 113 nxge_zcp_handle_sys_errors(p_nxge_t nxgep) 114 { 115 npi_handle_t handle; 116 npi_status_t rs = NPI_SUCCESS; 117 p_nxge_zcp_stats_t statsp; 118 uint8_t portn; 119 zcp_iconfig_t istatus; 120 boolean_t rxport_fatal = B_FALSE; 121 nxge_status_t status = NXGE_OK; 122 123 handle = nxgep->npi_handle; 124 statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats; 125 portn = nxgep->mac.portnum; 126 127 if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS) 128 return (NXGE_ERROR | rs); 129 130 if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) { 131 statsp->rrfifo_underrun++; 132 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 133 NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN); 134 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 135 "nxge_zcp_err_evnts: rrfifo_underrun")); 136 } 137 138 if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) { 139 statsp->rrfifo_overrun++; 140 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 141 NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN); 142 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 143 "nxge_zcp_err_evnts: buf_rrfifo_overrun")); 144 } 145 146 if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) { 147 statsp->rspfifo_uncorr_err++; 148 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 149 NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR); 150 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 151 "nxge_zcp_err_evnts: rspfifo_uncorr_err")); 152 } 153 154 if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) { 155 statsp->buffer_overflow++; 156 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 157 NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW); 158 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 159 "nxge_zcp_err_evnts: buffer_overflow")); 160 rxport_fatal = B_TRUE; 161 } 162 163 if (istatus & ICFG_ZCP_STAT_TBL_PERR) { 164 statsp->stat_tbl_perr++; 165 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 166 NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR); 167 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 168 "nxge_zcp_err_evnts: stat_tbl_perr")); 169 } 170 171 if (istatus & ICFG_ZCP_DYN_TBL_PERR) { 172 statsp->dyn_tbl_perr++; 173 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 174 NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR); 175 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 176 "nxge_zcp_err_evnts: dyn_tbl_perr")); 177 } 178 179 if (istatus & ICFG_ZCP_BUF_TBL_PERR) { 180 statsp->buf_tbl_perr++; 181 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 182 NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR); 183 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 184 "nxge_zcp_err_evnts: buf_tbl_perr")); 185 } 186 187 if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) { 188 statsp->tt_program_err++; 189 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 190 NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR); 191 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 192 "nxge_zcp_err_evnts: tt_program_err")); 193 } 194 195 if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) { 196 statsp->rsp_tt_index_err++; 197 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 198 NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR); 199 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 200 "nxge_zcp_err_evnts: rsp_tt_index_err")); 201 } 202 203 if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) { 204 statsp->slv_tt_index_err++; 205 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 206 NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR); 207 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 208 "nxge_zcp_err_evnts: slv_tt_index_err")); 209 } 210 211 if (istatus & ICFG_ZCP_TT_INDEX_ERR) { 212 statsp->zcp_tt_index_err++; 213 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 214 NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR); 215 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 216 "nxge_zcp_err_evnts: tt_index_err")); 217 } 218 219 if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) || 220 ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) || 221 ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) || 222 ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) { 223 boolean_t ue_ecc_valid; 224 225 if ((status = nxge_ipp_eccue_valid_check(nxgep, 226 &ue_ecc_valid)) != NXGE_OK) 227 return (status); 228 229 if (ue_ecc_valid) { 230 statsp->cfifo_ecc++; 231 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 232 NXGE_FM_EREPORT_ZCP_CFIFO_ECC); 233 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 234 "nxge_zcp_err_evnts: port%d buf_cfifo_ecc", 235 portn)); 236 rxport_fatal = B_TRUE; 237 } 238 } 239 240 /* 241 * Making sure that error source is cleared if this is an injected 242 * error. 243 */ 244 switch (portn) { 245 case 0: 246 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0); 247 break; 248 case 1: 249 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0); 250 break; 251 case 2: 252 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0); 253 break; 254 case 3: 255 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0); 256 break; 257 } 258 259 (void) npi_zcp_clear_istatus(handle); 260 261 if (rxport_fatal) { 262 NXGE_DEBUG_MSG((nxgep, IPP_CTL, 263 " nxge_zcp_handle_sys_errors:" 264 " fatal Error on Port #%d\n", portn)); 265 status = nxge_zcp_fatal_err_recover(nxgep); 266 if (status == NXGE_OK) { 267 FM_SERVICE_RESTORED(nxgep); 268 } 269 } 270 return (status); 271 } 272 273 void 274 nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id) 275 { 276 zcp_int_stat_reg_t zcps; 277 uint8_t portn = nxgep->mac.portnum; 278 zcp_ecc_ctrl_t ecc_ctrl; 279 280 switch (err_id) { 281 case NXGE_FM_EREPORT_ZCP_CFIFO_ECC: 282 ecc_ctrl.value = 0; 283 ecc_ctrl.bits.w0.cor_dbl = 1; 284 ecc_ctrl.bits.w0.cor_lst = 1; 285 ecc_ctrl.bits.w0.cor_all = 0; 286 switch (portn) { 287 case 0: 288 cmn_err(CE_NOTE, 289 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 290 (unsigned long long) ecc_ctrl.value, portn); 291 NXGE_REG_WR64(nxgep->npi_handle, 292 ZCP_CFIFO_ECC_PORT0_REG, 293 ecc_ctrl.value); 294 break; 295 case 1: 296 cmn_err(CE_NOTE, 297 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 298 (unsigned long long) ecc_ctrl.value, portn); 299 NXGE_REG_WR64(nxgep->npi_handle, 300 ZCP_CFIFO_ECC_PORT1_REG, 301 ecc_ctrl.value); 302 break; 303 case 2: 304 cmn_err(CE_NOTE, 305 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 306 (unsigned long long) ecc_ctrl.value, portn); 307 NXGE_REG_WR64(nxgep->npi_handle, 308 ZCP_CFIFO_ECC_PORT2_REG, 309 ecc_ctrl.value); 310 break; 311 case 3: 312 cmn_err(CE_NOTE, 313 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 314 (unsigned long long) ecc_ctrl.value, portn); 315 NXGE_REG_WR64(nxgep->npi_handle, 316 ZCP_CFIFO_ECC_PORT3_REG, 317 ecc_ctrl.value); 318 break; 319 } 320 break; 321 322 case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN: 323 case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR: 324 case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR: 325 case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR: 326 case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR: 327 case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN: 328 case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW: 329 case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR: 330 case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR: 331 case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR: 332 case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR: 333 NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG, 334 &zcps.value); 335 if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN) 336 zcps.bits.ldw.rrfifo_urun = 1; 337 if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR) 338 zcps.bits.ldw.rspfifo_uc_err = 1; 339 if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR) 340 zcps.bits.ldw.stat_tbl_perr = 1; 341 if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR) 342 zcps.bits.ldw.dyn_tbl_perr = 1; 343 if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR) 344 zcps.bits.ldw.buf_tbl_perr = 1; 345 if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) { 346 switch (portn) { 347 case 0: 348 zcps.bits.ldw.cfifo_ecc0 = 1; 349 break; 350 case 1: 351 zcps.bits.ldw.cfifo_ecc1 = 1; 352 break; 353 case 2: 354 zcps.bits.ldw.cfifo_ecc2 = 1; 355 break; 356 case 3: 357 zcps.bits.ldw.cfifo_ecc3 = 1; 358 break; 359 } 360 } 361 362 default: 363 if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN) 364 zcps.bits.ldw.rrfifo_orun = 1; 365 if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW) 366 zcps.bits.ldw.buf_overflow = 1; 367 if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR) 368 zcps.bits.ldw.tt_tbl_perr = 1; 369 if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR) 370 zcps.bits.ldw.rsp_tt_index_err = 1; 371 if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR) 372 zcps.bits.ldw.slv_tt_index_err = 1; 373 if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR) 374 zcps.bits.ldw.zcp_tt_index_err = 1; 375 cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n", 376 zcps.value); 377 NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG, 378 zcps.value); 379 break; 380 } 381 } 382 383 nxge_status_t 384 nxge_zcp_fatal_err_recover(p_nxge_t nxgep) 385 { 386 npi_handle_t handle; 387 npi_status_t rs = NPI_SUCCESS; 388 nxge_status_t status = NXGE_OK; 389 uint8_t portn; 390 zcp_ram_unit_t w_data; 391 zcp_ram_unit_t r_data; 392 uint32_t cfifo_depth; 393 int i; 394 395 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover")); 396 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 397 "Recovering from RxPort error...")); 398 399 handle = nxgep->npi_handle; 400 portn = nxgep->mac.portnum; 401 402 /* Disable RxMAC */ 403 if (nxge_rx_mac_disable(nxgep) != NXGE_OK) 404 goto fail; 405 406 /* Make sure source is clear if this is an injected error */ 407 switch (portn) { 408 case 0: 409 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0); 410 break; 411 case 1: 412 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0); 413 break; 414 case 2: 415 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0); 416 break; 417 case 3: 418 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0); 419 break; 420 } 421 422 /* Clear up CFIFO */ 423 if (nxgep->niu_type == N2_NIU) { 424 cfifo_depth = ZCP_NIU_CFIFO_DEPTH; 425 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep->niu_type)) { 426 if (portn < 2) 427 cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH; 428 else 429 cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH; 430 } else { 431 goto fail; 432 } 433 434 w_data.w0 = 0; 435 w_data.w1 = 0; 436 w_data.w2 = 0; 437 w_data.w3 = 0; 438 w_data.w4 = 0; 439 440 for (i = 0; i < cfifo_depth; i++) { 441 if (npi_zcp_tt_cfifo_entry(handle, OP_SET, 442 portn, i, &w_data) != NPI_SUCCESS) 443 goto fail; 444 if (npi_zcp_tt_cfifo_entry(handle, OP_GET, 445 portn, i, &r_data) != NPI_SUCCESS) 446 goto fail; 447 } 448 449 /* When recovering from ZCP, RxDMA channel resets are not necessary */ 450 /* Reset ZCP CFIFO */ 451 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn)); 452 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 453 goto fail; 454 455 /* Reset IPP */ 456 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn)); 457 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 458 goto fail; 459 460 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn)); 461 if (nxge_rx_mac_reset(nxgep) != NXGE_OK) 462 goto fail; 463 464 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn)); 465 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 466 goto fail; 467 468 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn)); 469 if (nxge_rx_mac_enable(nxgep) != NXGE_OK) 470 goto fail; 471 472 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 473 "Recovery Sucessful, RxPort Restored")); 474 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover")); 475 return (NXGE_OK); 476 fail: 477 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 478 return (status | rs); 479 } 480