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