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 <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 nxge_status_t 39 nxge_txc_init(p_nxge_t nxgep) 40 { 41 uint8_t port; 42 npi_handle_t handle; 43 npi_status_t rs = NPI_SUCCESS; 44 45 handle = NXGE_DEV_NPI_HANDLE(nxgep); 46 port = NXGE_GET_PORT_NUM(nxgep->function_num); 47 48 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port)); 49 50 /* 51 * Enable the TXC controller. 52 */ 53 if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) { 54 goto fail; 55 } 56 57 /* Enable this port within the TXC. */ 58 if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) { 59 goto fail; 60 } 61 62 /* Bind DMA channels to this port. */ 63 if ((rs = npi_txc_port_dma_enable(handle, port, 64 TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) { 65 goto fail; 66 } 67 68 /* Unmask all TXC interrupts */ 69 npi_txc_global_imask_set(handle, port, 0); 70 71 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port)); 72 73 return (NXGE_OK); 74 fail: 75 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 76 "nxge_txc_init: Failed to initialize txc on port %d", 77 port)); 78 79 return (NXGE_ERROR | rs); 80 } 81 82 nxge_status_t 83 nxge_txc_uninit(p_nxge_t nxgep) 84 { 85 uint8_t port; 86 npi_handle_t handle; 87 npi_status_t rs = NPI_SUCCESS; 88 89 handle = NXGE_DEV_NPI_HANDLE(nxgep); 90 port = NXGE_GET_PORT_NUM(nxgep->function_num); 91 92 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port)); 93 94 /* 95 * disable the TXC controller. 96 */ 97 if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) { 98 goto fail; 99 } 100 101 /* disable this port within the TXC. */ 102 if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) { 103 goto fail; 104 } 105 106 /* unbind DMA channels to this port. */ 107 if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) { 108 goto fail; 109 } 110 111 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port)); 112 113 return (NXGE_OK); 114 fail: 115 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 116 "nxge_txc_init: Failed to initialize txc on port %d", 117 port)); 118 119 return (NXGE_ERROR | rs); 120 } 121 122 void 123 nxge_txc_regs_dump(p_nxge_t nxgep) 124 { 125 uint32_t cnt1, cnt2; 126 npi_handle_t handle; 127 txc_control_t control; 128 uint32_t bitmap = 0; 129 130 NXGE_DEBUG_MSG((nxgep, TX_CTL, "\nTXC dump: func # %d:\n", 131 nxgep->function_num)); 132 133 handle = NXGE_DEV_NPI_HANDLE(nxgep); 134 135 (void) npi_txc_control(handle, OP_GET, &control); 136 (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap); 137 138 NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port control 0x%0llx", 139 (long long)control.value)); 140 NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port bitmap 0x%x", bitmap)); 141 142 (void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num, 143 &cnt1, &cnt2); 144 NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC bytes to MAC %d " 145 "packets to MAC %d", 146 cnt1, cnt2)); 147 148 (void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num, 149 &cnt1, &cnt2); 150 NXGE_DEBUG_MSG((nxgep, TX_CTL, 151 "\n\tTXC ass packets %d reorder packets %d", 152 cnt1 & 0xffff, cnt2 & 0xffff)); 153 154 (void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1); 155 NXGE_DEBUG_MSG((nxgep, TX_CTL, 156 "\n\tTXC reorder resource %d", cnt1 & 0xff)); 157 } 158 159 nxge_status_t 160 nxge_txc_handle_sys_errors(p_nxge_t nxgep) 161 { 162 npi_handle_t handle; 163 txc_int_stat_t istatus; 164 uint32_t err_status; 165 uint8_t err_portn; 166 boolean_t my_err = B_FALSE; 167 nxge_status_t status = NXGE_OK; 168 169 handle = nxgep->npi_handle; 170 npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value); 171 switch (nxgep->mac.portnum) { 172 case 0: 173 if (istatus.bits.ldw.port0_int_status) { 174 my_err = B_TRUE; 175 err_portn = 0; 176 err_status = istatus.bits.ldw.port0_int_status; 177 } 178 break; 179 case 1: 180 if (istatus.bits.ldw.port1_int_status) { 181 my_err = B_TRUE; 182 err_portn = 1; 183 err_status = istatus.bits.ldw.port1_int_status; 184 } 185 break; 186 case 2: 187 if (istatus.bits.ldw.port2_int_status) { 188 my_err = B_TRUE; 189 err_portn = 2; 190 err_status = istatus.bits.ldw.port2_int_status; 191 } 192 break; 193 case 3: 194 if (istatus.bits.ldw.port3_int_status) { 195 my_err = B_TRUE; 196 err_portn = 3; 197 err_status = istatus.bits.ldw.port3_int_status; 198 } 199 break; 200 default: 201 return (NXGE_ERROR); 202 } 203 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 204 " nxge_txc_handle_sys_errors: errored port %d", 205 err_portn)); 206 if (my_err) { 207 status = nxge_txc_handle_port_errors(nxgep, err_status); 208 } 209 210 return (status); 211 } 212 213 static nxge_status_t 214 nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status) 215 { 216 npi_handle_t handle; 217 npi_status_t rs = NPI_SUCCESS; 218 p_nxge_txc_stats_t statsp; 219 txc_int_stat_t istatus; 220 boolean_t txport_fatal = B_FALSE; 221 uint8_t portn; 222 nxge_status_t status = NXGE_OK; 223 224 handle = nxgep->npi_handle; 225 statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats; 226 portn = nxgep->mac.portnum; 227 istatus.value = 0; 228 229 if ((err_status & TXC_INT_STAT_RO_CORR_ERR) || 230 (err_status & TXC_INT_STAT_RO_CORR_ERR) || 231 (err_status & TXC_INT_STAT_RO_UNCORR_ERR) || 232 (err_status & TXC_INT_STAT_REORDER_ERR)) { 233 if ((rs = npi_txc_ro_states_get(handle, portn, 234 &statsp->errlog.ro_st)) != NPI_SUCCESS) { 235 return (NXGE_ERROR | rs); 236 } 237 238 if (err_status & TXC_INT_STAT_RO_CORR_ERR) { 239 statsp->ro_correct_err++; 240 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 241 NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR); 242 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 243 "nxge_txc_err_evnts: " 244 "RO FIFO correctable error")); 245 } 246 if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) { 247 statsp->ro_uncorrect_err++; 248 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 249 NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR); 250 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 251 "nxge_txc_err_evnts: " 252 "RO FIFO uncorrectable error")); 253 } 254 if (err_status & TXC_INT_STAT_REORDER_ERR) { 255 statsp->reorder_err++; 256 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 257 NXGE_FM_EREPORT_TXC_REORDER_ERR); 258 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 259 "nxge_txc_err_evnts: " 260 "fatal error: Reorder error")); 261 txport_fatal = B_TRUE; 262 } 263 264 if ((err_status & TXC_INT_STAT_RO_CORR_ERR) || 265 (err_status & TXC_INT_STAT_RO_CORR_ERR) || 266 (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) { 267 268 if ((rs = npi_txc_ro_ecc_state_clr(handle, portn)) 269 != NPI_SUCCESS) 270 return (NXGE_ERROR | rs); 271 /* 272 * Making sure that error source is cleared if this is 273 * an injected error. 274 */ 275 TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG, 276 portn, 0); 277 } 278 } 279 280 if ((err_status & TXC_INT_STAT_SF_CORR_ERR) || 281 (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) { 282 if ((rs = npi_txc_sf_states_get(handle, portn, 283 &statsp->errlog.sf_st)) != NPI_SUCCESS) { 284 return (NXGE_ERROR | rs); 285 } 286 if (err_status & TXC_INT_STAT_SF_CORR_ERR) { 287 statsp->sf_correct_err++; 288 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 289 NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR); 290 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 291 "nxge_txc_err_evnts: " 292 "SF FIFO correctable error")); 293 } 294 if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) { 295 statsp->sf_uncorrect_err++; 296 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 297 NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR); 298 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 299 "nxge_txc_err_evnts: " 300 "SF FIFO uncorrectable error")); 301 } 302 if ((rs = npi_txc_sf_ecc_state_clr(handle, portn)) 303 != NPI_SUCCESS) 304 return (NXGE_ERROR | rs); 305 /* 306 * Making sure that error source is cleared if this is 307 * an injected error. 308 */ 309 TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0); 310 } 311 312 /* Clear corresponding errors */ 313 switch (portn) { 314 case 0: 315 istatus.bits.ldw.port0_int_status = err_status; 316 break; 317 case 1: 318 istatus.bits.ldw.port1_int_status = err_status; 319 break; 320 case 2: 321 istatus.bits.ldw.port2_int_status = err_status; 322 break; 323 case 3: 324 istatus.bits.ldw.port3_int_status = err_status; 325 break; 326 default: 327 return (NXGE_ERROR); 328 } 329 330 npi_txc_global_istatus_clear(handle, istatus.value); 331 332 if (txport_fatal) { 333 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 334 " nxge_txc_handle_port_errors:" 335 " fatal Error on Port#%d\n", 336 portn)); 337 status = nxge_tx_port_fatal_err_recover(nxgep); 338 if (status == NXGE_OK) { 339 FM_SERVICE_RESTORED(nxgep); 340 } 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