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