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 9 * http://www.opensource.org/licenses/cddl1.txt. 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 (c) 2004-2011 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <emlxs.h> 28 29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 30 EMLXS_MSG_DEF(EMLXS_IP_C); 31 32 33 extern int32_t 34 emlxs_ip_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 35 { 36 emlxs_port_t *port = &PPORT; 37 IOCB *cmd; 38 emlxs_buf_t *sbp; 39 NODELIST *ndlp; 40 41 cmd = &iocbq->iocb; 42 43 HBASTATS.IpEvent++; 44 45 sbp = (emlxs_buf_t *)iocbq->sbp; 46 47 if (!sbp) { 48 HBASTATS.IpStray++; 49 50 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ip_completion_msg, 51 "cmd=0x%x iotag=0x%x status=0x%x perr=0x%x", 52 (uint32_t)cmd->ULPCOMMAND, (uint32_t)cmd->ULPIOTAG, 53 cmd->ULPSTATUS, cmd->un.ulpWord[4]); 54 55 return (EIO); 56 } 57 58 if (cp->channelno != hba->channel_ip) { 59 HBASTATS.IpStray++; 60 61 return (0); 62 } 63 64 port = sbp->iocbq.port; 65 66 switch (cmd->ULPCOMMAND) { 67 /* 68 * Error: Abnormal BCAST command completion (Local error) 69 */ 70 case CMD_XMIT_BCAST_CN: 71 case CMD_XMIT_BCAST64_CN: 72 73 HBASTATS.IpBcastCompleted++; 74 HBASTATS.IpBcastError++; 75 76 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 77 "XMIT BCAST completion error cmd=0x%x status=0x%x " 78 "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS, 79 cmd->un.ulpWord[4], cmd->un.ulpWord[5]); 80 81 emlxs_pkt_complete(sbp, cmd->ULPSTATUS, 82 cmd->un.grsp.perr.statLocalError, 1); 83 84 break; 85 86 /* 87 * Error: Abnormal XMIT SEQUENCE command completion 88 * (Local error) 89 */ 90 case CMD_XMIT_SEQUENCE_CR: 91 case CMD_XMIT_SEQUENCE64_CR: 92 93 HBASTATS.IpSeqCompleted++; 94 HBASTATS.IpSeqError++; 95 96 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 97 "XMIT SEQUENCE CR completion error: cmd=%x status=0x%x " 98 "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS, 99 cmd->un.ulpWord[4], cmd->un.ulpWord[5]); 100 101 emlxs_pkt_complete(sbp, cmd->ULPSTATUS, 102 cmd->un.grsp.perr.statLocalError, 1); 103 104 break; 105 106 /* 107 * Normal BCAST completion 108 */ 109 case CMD_XMIT_BCAST_CX: 110 case CMD_XMIT_BCAST64_CX: 111 112 HBASTATS.IpBcastCompleted++; 113 HBASTATS.IpBcastGood++; 114 115 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 116 "XMIT BCAST CN completion: cmd=%x status=0x%x [%08x,%08x]", 117 cmd->ULPCOMMAND, cmd->ULPSTATUS, cmd->un.ulpWord[4], 118 cmd->un.ulpWord[5]); 119 120 emlxs_pkt_complete(sbp, cmd->ULPSTATUS, 121 cmd->un.grsp.perr.statLocalError, 1); 122 123 break; 124 125 /* 126 * Normal XMIT SEQUENCE completion 127 */ 128 case CMD_XMIT_SEQUENCE_CX: 129 case CMD_XMIT_SEQUENCE64_CX: 130 131 HBASTATS.IpSeqCompleted++; 132 133 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 134 "XMIT SEQUENCE CR completion: cmd=%x status=0x%x" 135 "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS, 136 cmd->un.ulpWord[4], cmd->un.ulpWord[5]); 137 138 if (cmd->ULPSTATUS) { 139 HBASTATS.IpSeqError++; 140 141 if ((cmd->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 142 ((cmd->un.ulpWord[4] & 0xff) == IOERR_NO_XRI)) { 143 ndlp = (NODELIST *)sbp->node; 144 if ((cmd->ULPCONTEXT == ndlp->nlp_Xri) && 145 !(ndlp->nlp_flag[hba->channel_ip] & 146 NLP_RPI_XRI)) { 147 ndlp->nlp_Xri = 0; 148 (void) emlxs_create_xri(port, cp, ndlp); 149 } 150 } 151 } else { 152 HBASTATS.IpSeqGood++; 153 } 154 155 emlxs_pkt_complete(sbp, cmd->ULPSTATUS, 156 cmd->un.grsp.perr.statLocalError, 1); 157 158 break; 159 160 default: 161 162 HBASTATS.IpStray++; 163 164 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ip_msg, 165 "Invalid iocb: cmd=0x%x", cmd->ULPCOMMAND); 166 167 break; 168 169 } /* switch(cmd->ULPCOMMAND) */ 170 171 172 return (0); 173 174 } /* emlxs_ip_handle_event() */ 175 176 177 extern int32_t 178 emlxs_ip_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 179 MATCHMAP *mp, uint32_t size) 180 { 181 emlxs_hba_t *hba = HBA; 182 fc_unsol_buf_t *ubp; 183 IOCB *cmd; 184 NETHDR *nd; 185 NODELIST *ndlp; 186 uint8_t *mac; 187 emlxs_ub_priv_t *ub_priv; 188 uint32_t sid; 189 uint32_t i; 190 uint32_t IpDropped = 1; 191 uint32_t IpBcastReceived = 0; 192 uint32_t IpSeqReceived = 0; 193 194 cmd = &iocbq->iocb; 195 ubp = NULL; 196 197 for (i = 0; i < MAX_VPORTS; i++) { 198 port = &VPORT(i); 199 200 if (!(port->flag & EMLXS_INI_BOUND) || 201 !(port->flag & EMLXS_PORT_IP_UP)) { 202 continue; 203 } 204 205 ubp = 206 (fc_unsol_buf_t *)emlxs_ub_get(port, size, 207 FC_TYPE_IS8802_SNAP, 0); 208 209 if (!ubp) { 210 /* Theoretically we should never get here. */ 211 /* There should be one DMA buffer for every ub */ 212 /* buffer. If we are out of ub buffers */ 213 /* then some how this matching has been corrupted */ 214 215 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ip_dropped_msg, 216 "Buffer not found. paddr=%lx", 217 PADDR(cmd->un.cont64[0].addrHigh, 218 cmd->un.cont64[0].addrLow)); 219 220 continue; 221 } 222 223 bcopy(mp->virt, ubp->ub_buffer, size); 224 225 ub_priv = ubp->ub_fca_private; 226 nd = (NETHDR *)ubp->ub_buffer; 227 mac = nd->fc_srcname.IEEE; 228 ndlp = emlxs_node_find_mac(port, mac); 229 230 if (ndlp) { 231 sid = ndlp->nlp_DID; 232 233 if ((ndlp->nlp_Xri == 0) && 234 !(ndlp->nlp_flag[hba->channel_ip] & NLP_RPI_XRI)) { 235 (void) emlxs_create_xri(port, cp, ndlp); 236 } 237 } 238 239 /* 240 * If no node is found, then check if this is a 241 * broadcast frame 242 */ 243 else if (cmd->un.xrseq.w5.hcsw.Fctl & BC) { 244 sid = cmd->un.ulpWord[4] & 0x00ffffff; 245 } 246 247 else { 248 /* We have to drop this frame because we do not have */ 249 /* the S_ID of the request */ 250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ip_dropped_msg, 251 "Node not found. mac=%02x%02x%02x%02x%02x%02x", 252 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 253 254 (void) emlxs_fca_ub_release((opaque_t)port, 1, 255 &ubp->ub_token); 256 257 continue; 258 } 259 260 if (cmd->un.xrseq.w5.hcsw.Fctl & BC) { 261 IpBcastReceived++; 262 } else { 263 IpSeqReceived++; 264 } 265 266 /* 267 * Setup frame header 268 */ 269 ubp->ub_frame.r_ctl = cmd->un.xrseq.w5.hcsw.Rctl; 270 ubp->ub_frame.type = cmd->un.xrseq.w5.hcsw.Type; 271 ubp->ub_frame.s_id = sid; 272 ubp->ub_frame.ox_id = ub_priv->token; 273 ubp->ub_frame.rx_id = cmd->ULPCONTEXT; 274 ubp->ub_class = FC_TRAN_CLASS3; 275 276 emlxs_ub_callback(port, ubp); 277 IpDropped = 0; 278 } 279 port = &PPORT; 280 281 out: 282 283 if (IpDropped) { 284 HBASTATS.IpDropped++; 285 } 286 287 if (IpBcastReceived) { 288 HBASTATS.IpBcastReceived++; 289 } 290 291 if (IpSeqReceived) { 292 HBASTATS.IpSeqReceived++; 293 } 294 295 return (0); 296 297 } /* emlxs_ip_handle_unsol_req() */ 298 299 300 extern int32_t 301 emlxs_ip_handle_rcv_seq_list(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 302 { 303 emlxs_port_t *port = &PPORT; 304 IOCB *cmd; 305 uint64_t bdeAddr; 306 MATCHMAP *mp = NULL; 307 HBQE_t *hbqE; 308 uint32_t hbq_id; 309 uint32_t hbqe_tag; 310 RING *rp; 311 312 /* 313 * No action required for now. 314 */ 315 cmd = &iocbq->iocb; 316 rp = &hba->sli.sli3.ring[cp->channelno]; 317 318 HBASTATS.IpRcvEvent++; 319 320 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 321 "Receive sequence list: cmd=0x%x iotag=0x%x status=0x%x " 322 "w4=0x%x channelno=0x%x", cmd->ULPCOMMAND, cmd->ULPIOTAG, 323 cmd->ULPSTATUS, cmd->un.ulpWord[4], cp->channelno); 324 325 if (cmd->ULPSTATUS) { 326 goto out; 327 } 328 329 hbqE = (HBQE_t *)&iocbq->iocb; 330 hbq_id = hbqE->unt.ext.HBQ_tag; 331 hbqe_tag = hbqE->unt.ext.HBQE_tag; 332 333 if (hba->flag & FC_HBQ_ENABLED) { 334 HBQ_INIT_t *hbq; 335 336 hbq = &hba->sli.sli3.hbq_table[hbq_id]; 337 338 HBASTATS.IpUbPosted--; 339 340 if (hbqe_tag >= hbq->HBQ_numEntries) { 341 mp = NULL; 342 } else { 343 mp = hba->sli.sli3.hbq_table 344 [hbq_id].HBQ_PostBufs[hbqe_tag]; 345 } 346 } else { 347 /* Check for valid buffer */ 348 if (!(cmd->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID)) { 349 bdeAddr = 350 PADDR(cmd->un.cont64[0].addrHigh, 351 cmd->un.cont64[0].addrLow); 352 mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr); 353 } 354 } 355 356 out: 357 358 if (hba->flag & FC_HBQ_ENABLED) { 359 emlxs_update_HBQ_index(hba, hbq_id); 360 } else { 361 if (mp) { 362 emlxs_mem_put(hba, MEM_IPBUF, (void *)mp); 363 } 364 (void) emlxs_post_buffer(hba, rp, 1); 365 } 366 367 HBASTATS.IpDropped++; 368 369 return (0); 370 371 } /* emlxs_ip_handle_rcv_seq_list() */ 372 373 374 375 /* 376 * Process a create_xri command completion. 377 */ 378 extern int32_t 379 emlxs_handle_create_xri(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 380 { 381 emlxs_port_t *port = &PPORT; 382 IOCB *cmd; 383 NODELIST *ndlp; 384 fc_packet_t *pkt; 385 emlxs_buf_t *sbp; 386 int32_t rval = 0; 387 388 cmd = &iocbq->iocb; 389 390 sbp = (emlxs_buf_t *)iocbq->sbp; 391 392 if (!sbp) { 393 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ip_completion_msg, 394 "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x. " 395 "NULL sbp found.", 396 cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS, 397 cmd->un.ulpWord[4]); 398 399 return (EIO); 400 } 401 402 /* check for first xmit completion in sequence */ 403 ndlp = (NODELIST *)sbp->node; 404 405 if (!ndlp) { 406 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_bad_ip_completion_msg, 407 "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x. " 408 "NULL node found.", 409 cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS, 410 cmd->un.ulpWord[4]); 411 412 rval = EIO; 413 goto done; 414 } 415 416 if (cmd->ULPSTATUS) { 417 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_bad_ip_completion_msg, 418 "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x. " 419 "Completion error.", 420 cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS, 421 cmd->un.ulpWord[4]); 422 423 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 424 ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI; 425 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 426 427 rval = EIO; 428 goto done; 429 } 430 431 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 432 ndlp->nlp_Xri = cmd->ULPCONTEXT; 433 ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI; 434 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 435 436 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 437 "create_xri completed: DID=0x%x Xri=0x%x iotag=0x%x", 438 ndlp->nlp_DID, ndlp->nlp_Xri, cmd->ULPIOTAG); 439 440 done: 441 pkt = sbp->pkt; 442 if (pkt) { 443 emlxs_pkt_free(pkt); 444 } 445 446 return (rval); 447 448 } /* emlxs_handle_create_xri() */ 449 450 451 /* 452 * Issue an iocb command to create an exchange with the remote Nport 453 * specified by the NODELIST entry. 454 */ 455 extern int32_t 456 emlxs_create_xri(emlxs_port_t *port, CHANNEL *cp, NODELIST *ndlp) 457 { 458 emlxs_hba_t *hba = HBA; 459 IOCB *icmd; 460 IOCBQ *iocbq; 461 fc_packet_t *pkt; 462 emlxs_buf_t *sbp; 463 uint16_t iotag; 464 465 /* Check if an XRI has already been requested */ 466 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 467 if (ndlp->nlp_Xri != 0 || 468 (ndlp->nlp_flag[cp->channelno] & NLP_RPI_XRI)) { 469 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 470 return (0); 471 } 472 ndlp->nlp_flag[cp->channelno] |= NLP_RPI_XRI; 473 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 474 475 if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) { 476 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 477 "create_xri failed: Unable to allocate pkt. did=0x%x", 478 ndlp->nlp_DID); 479 480 goto fail; 481 } 482 483 sbp = (emlxs_buf_t *)pkt->pkt_fca_private; 484 iocbq = &sbp->iocbq; 485 486 /* Clear the PACKET_ULP_OWNED flag */ 487 sbp->pkt_flags &= ~PACKET_ULP_OWNED; 488 489 /* Get the iotag by registering the packet */ 490 iotag = emlxs_register_pkt(cp, sbp); 491 492 if (!iotag) { 493 /* 494 * No more command slots available, retry later 495 */ 496 emlxs_pkt_free(pkt); 497 498 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 499 "create_xri failed: Unable to allocate IOTAG. did=0x%x", 500 ndlp->nlp_DID); 501 502 goto fail; 503 } 504 505 icmd = &iocbq->iocb; 506 icmd->ULPIOTAG = iotag; 507 icmd->ULPCONTEXT = ndlp->nlp_Rpi; 508 icmd->ULPLE = 1; 509 icmd->ULPCOMMAND = CMD_CREATE_XRI_CR; 510 icmd->ULPOWNER = OWN_CHIP; 511 512 /* Initalize iocbq */ 513 iocbq->port = (void *)port; 514 iocbq->node = (void *)ndlp; 515 iocbq->channel = (void *)cp; 516 517 mutex_enter(&sbp->mtx); 518 sbp->node = (void *)ndlp; 519 sbp->channel = cp; 520 mutex_exit(&sbp->mtx); 521 522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg, 523 "create_xri sent: DID=0x%x Xri=0x%x iotag=0x%x", ndlp->nlp_DID, 524 ndlp->nlp_Xri, iotag); 525 526 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 527 528 return (0); 529 530 fail: 531 532 /* Clear the XRI flag */ 533 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 534 ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI; 535 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 536 537 return (1); 538 539 } /* emlxs_create_xri() */ 540