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