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 2006 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 <sys/nxge/nxge_impl.h> 29 #include <sys/nxge/nxge_txc.h> 30 31 static nxge_status_t 32 nxge_txc_handle_port_errors(p_nxge_t, uint32_t); 33 static void 34 nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *, 35 uint8_t istats); 36 extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t); 37 38 39 nxge_status_t 40 nxge_txc_init(p_nxge_t nxgep) 41 { 42 uint8_t port; 43 npi_handle_t handle; 44 npi_status_t rs = NPI_SUCCESS; 45 46 handle = NXGE_DEV_NPI_HANDLE(nxgep); 47 port = NXGE_GET_PORT_NUM(nxgep->function_num); 48 49 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port)); 50 51 /* 52 * Enable the TXC controller. 53 */ 54 if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) { 55 goto fail; 56 } 57 58 /* Enable this port within the TXC. */ 59 if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) { 60 goto fail; 61 } 62 63 /* Bind DMA channels to this port. */ 64 if ((rs = npi_txc_port_dma_enable(handle, port, 65 TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) { 66 goto fail; 67 } 68 69 /* Unmask all TXC interrupts */ 70 npi_txc_global_imask_set(handle, port, 0); 71 72 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port)); 73 74 return (NXGE_OK); 75 fail: 76 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 77 "nxge_txc_init: Failed to initialize txc on port %d", 78 port)); 79 80 return (NXGE_ERROR | rs); 81 } 82 83 nxge_status_t 84 nxge_txc_uninit(p_nxge_t nxgep) 85 { 86 uint8_t port; 87 npi_handle_t handle; 88 npi_status_t rs = NPI_SUCCESS; 89 90 handle = NXGE_DEV_NPI_HANDLE(nxgep); 91 port = NXGE_GET_PORT_NUM(nxgep->function_num); 92 93 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port)); 94 95 /* 96 * disable the TXC controller. 97 */ 98 if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) { 99 goto fail; 100 } 101 102 /* disable this port within the TXC. */ 103 if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) { 104 goto fail; 105 } 106 107 /* unbind DMA channels to this port. */ 108 if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) { 109 goto fail; 110 } 111 112 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port)); 113 114 return (NXGE_OK); 115 fail: 116 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 117 "nxge_txc_init: Failed to initialize txc on port %d", 118 port)); 119 120 return (NXGE_ERROR | rs); 121 } 122 123 void 124 nxge_txc_regs_dump(p_nxge_t nxgep) 125 { 126 uint32_t cnt1, cnt2; 127 npi_handle_t handle; 128 txc_control_t control; 129 uint32_t bitmap = 0; 130 131 printf("\nTXC dump: func # %d:\n", 132 nxgep->function_num); 133 134 handle = NXGE_DEV_NPI_HANDLE(nxgep); 135 136 (void) npi_txc_control(handle, OP_GET, &control); 137 (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap); 138 139 printf("\n\tTXC port control 0x%0llx", 140 (long long)control.value); 141 printf("\n\tTXC port bitmap 0x%x", bitmap); 142 143 (void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num, 144 &cnt1, &cnt2); 145 printf("\n\tTXC bytes to MAC %d packets to MAC %d", 146 cnt1, cnt2); 147 148 (void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num, 149 &cnt1, &cnt2); 150 printf("\n\tTXC ass packets %d reorder packets %d", 151 cnt1 & 0xffff, cnt2 & 0xffff); 152 153 (void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1); 154 printf("\n\tTXC reorder resource %d", cnt1 & 0xff); 155 } 156 157 nxge_status_t 158 nxge_txc_handle_sys_errors(p_nxge_t nxgep) 159 { 160 npi_handle_t handle; 161 txc_int_stat_t istatus; 162 uint32_t err_status; 163 uint8_t err_portn; 164 boolean_t my_err = B_FALSE; 165 nxge_status_t status = NXGE_OK; 166 167 handle = nxgep->npi_handle; 168 npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value); 169 switch (nxgep->mac.portnum) { 170 case 0: 171 if (istatus.bits.ldw.port0_int_status) { 172 my_err = B_TRUE; 173 err_portn = 0; 174 err_status = istatus.bits.ldw.port0_int_status; 175 } 176 break; 177 case 1: 178 if (istatus.bits.ldw.port1_int_status) { 179 my_err = B_TRUE; 180 err_portn = 1; 181 err_status = istatus.bits.ldw.port1_int_status; 182 } 183 break; 184 case 2: 185 if (istatus.bits.ldw.port2_int_status) { 186 my_err = B_TRUE; 187 err_portn = 2; 188 err_status = istatus.bits.ldw.port2_int_status; 189 } 190 break; 191 case 3: 192 if (istatus.bits.ldw.port3_int_status) { 193 my_err = B_TRUE; 194 err_portn = 3; 195 err_status = istatus.bits.ldw.port3_int_status; 196 } 197 break; 198 default: 199 return (NXGE_ERROR); 200 } 201 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 202 " nxge_txc_handle_sys_erors: errored port %d", 203 err_portn)); 204 if (my_err) { 205 status = nxge_txc_handle_port_errors(nxgep, err_status); 206 } 207 208 return (status); 209 } 210 211 static nxge_status_t 212 nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status) 213 { 214 npi_handle_t handle; 215 npi_status_t rs = NPI_SUCCESS; 216 p_nxge_txc_stats_t statsp; 217 txc_int_stat_t istatus; 218 boolean_t txport_fatal = B_FALSE; 219 uint8_t portn; 220 nxge_status_t status = NXGE_OK; 221 222 handle = nxgep->npi_handle; 223 statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats; 224 portn = nxgep->mac.portnum; 225 istatus.value = 0; 226 227 if ((err_status & TXC_INT_STAT_RO_CORR_ERR) || 228 (err_status & TXC_INT_STAT_RO_CORR_ERR) || 229 (err_status & TXC_INT_STAT_RO_UNCORR_ERR) || 230 (err_status & TXC_INT_STAT_REORDER_ERR)) { 231 if ((rs = npi_txc_ro_states_get(handle, portn, 232 &statsp->errlog.ro_st)) != NPI_SUCCESS) { 233 return (NXGE_ERROR | rs); 234 } 235 236 if (err_status & TXC_INT_STAT_RO_CORR_ERR) { 237 statsp->ro_correct_err++; 238 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 239 NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR); 240 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 241 "nxge_txc_err_evnts: " 242 "RO FIFO correctable error")); 243 } 244 if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) { 245 statsp->ro_uncorrect_err++; 246 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 247 NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR); 248 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 249 "nxge_txc_err_evnts: " 250 "RO FIFO uncorrectable error")); 251 } 252 if (err_status & TXC_INT_STAT_REORDER_ERR) { 253 statsp->reorder_err++; 254 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 255 NXGE_FM_EREPORT_TXC_REORDER_ERR); 256 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 257 "nxge_txc_err_evnts: " 258 "fatal error: Reorder error")); 259 txport_fatal = B_TRUE; 260 } 261 262 if ((err_status & TXC_INT_STAT_RO_CORR_ERR) || 263 (err_status & TXC_INT_STAT_RO_CORR_ERR) || 264 (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) { 265 266 if ((rs = npi_txc_ro_ecc_state_clr(handle, portn)) 267 != NPI_SUCCESS) 268 return (NXGE_ERROR | rs); 269 /* 270 * Making sure that error source is cleared if this is 271 * an injected error. 272 */ 273 TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG, 274 portn, 0); 275 } 276 } 277 278 if ((err_status & TXC_INT_STAT_SF_CORR_ERR) || 279 (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) { 280 if ((rs = npi_txc_sf_states_get(handle, portn, 281 &statsp->errlog.sf_st)) != NPI_SUCCESS) { 282 return (NXGE_ERROR | rs); 283 } 284 if (err_status & TXC_INT_STAT_SF_CORR_ERR) { 285 statsp->sf_correct_err++; 286 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 287 NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR); 288 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 289 "nxge_txc_err_evnts: " 290 "SF FIFO correctable error")); 291 } 292 if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) { 293 statsp->sf_uncorrect_err++; 294 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 295 NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR); 296 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 297 "nxge_txc_err_evnts: " 298 "SF FIFO uncorrectable error")); 299 } 300 if ((rs = npi_txc_sf_ecc_state_clr(handle, portn)) 301 != NPI_SUCCESS) 302 return (NXGE_ERROR | rs); 303 /* 304 * Making sure that error source is cleared if this is 305 * an injected error. 306 */ 307 TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0); 308 } 309 310 /* Clear corresponding errors */ 311 switch (portn) { 312 case 0: 313 istatus.bits.ldw.port0_int_status = err_status; 314 break; 315 case 1: 316 istatus.bits.ldw.port1_int_status = err_status; 317 break; 318 case 2: 319 istatus.bits.ldw.port2_int_status = err_status; 320 break; 321 case 3: 322 istatus.bits.ldw.port3_int_status = err_status; 323 break; 324 default: 325 return (NXGE_ERROR); 326 } 327 328 npi_txc_global_istatus_clear(handle, istatus.value); 329 330 if (txport_fatal) { 331 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 332 " nxge_txc_handle_sys_errors:" 333 " fatal Error on Port#%d\n", 334 portn)); 335 status = nxge_tx_port_fatal_err_recover(nxgep); 336 #ifdef NXGE_FM 337 if (status == NXGE_OK) { 338 FM_SERVICE_RESTORED(nxgep); 339 } 340 #endif 341 } 342 343 return (status); 344 } 345 346 void 347 nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id) 348 { 349 txc_int_stat_dbg_t txcs; 350 txc_roecc_ctl_t ro_ecc_ctl; 351 txc_sfecc_ctl_t sf_ecc_ctl; 352 uint8_t portn = nxgep->mac.portnum; 353 354 cmn_err(CE_NOTE, "!TXC error Inject\n"); 355 switch (err_id) { 356 case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR: 357 case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR: 358 ro_ecc_ctl.value = 0; 359 ro_ecc_ctl.bits.ldw.all_pkts = 1; 360 ro_ecc_ctl.bits.ldw.second_line_pkt = 1; 361 if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR) 362 ro_ecc_ctl.bits.ldw.single_bit_err = 1; 363 else 364 ro_ecc_ctl.bits.ldw.double_bit_err = 1; 365 cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n", 366 ro_ecc_ctl.value); 367 TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG, 368 portn, ro_ecc_ctl.value); 369 break; 370 case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR: 371 case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR: 372 sf_ecc_ctl.value = 0; 373 sf_ecc_ctl.bits.ldw.all_pkts = 1; 374 sf_ecc_ctl.bits.ldw.second_line_pkt = 1; 375 if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR) 376 sf_ecc_ctl.bits.ldw.single_bit_err = 1; 377 else 378 sf_ecc_ctl.bits.ldw.double_bit_err = 1; 379 cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n", 380 sf_ecc_ctl.value); 381 TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG, 382 portn, sf_ecc_ctl.value); 383 break; 384 case NXGE_FM_EREPORT_TXC_REORDER_ERR: 385 NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG, 386 &txcs.value); 387 nxge_txc_inject_port_err(portn, &txcs, 388 TXC_INT_STAT_REORDER_ERR); 389 cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n", 390 txcs.value); 391 NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG, 392 txcs.value); 393 break; 394 default: 395 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 396 "nxge_txc_inject_err: Unknown err_id")); 397 } 398 } 399 400 static void 401 nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs, 402 uint8_t istats) 403 { 404 switch (portn) { 405 case 0: 406 txcs->bits.ldw.port0_int_status |= istats; 407 break; 408 case 1: 409 txcs->bits.ldw.port1_int_status |= istats; 410 break; 411 case 2: 412 txcs->bits.ldw.port2_int_status |= istats; 413 break; 414 case 3: 415 txcs->bits.ldw.port3_int_status |= istats; 416 break; 417 default: 418 ; 419 } 420 } 421