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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <sys/conf.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/modctl.h> 32 #include <sys/byteorder.h> 33 #include <sys/sdt.h> 34 35 #include <sys/ib/clients/iser/iser.h> 36 37 /* 38 * iser_xfer.c 39 */ 40 41 int 42 iser_xfer_hello_msg(iser_chan_t *chan) 43 { 44 iser_hca_t *hca; 45 iser_wr_t *iser_wr; 46 iser_msg_t *msg; 47 ibt_send_wr_t wr; 48 iser_hello_hdr_t *hdr; 49 int status; 50 51 ASSERT(chan != NULL); 52 53 hca = (iser_hca_t *)chan->ic_hca; 54 if (hca == NULL) { 55 ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: no hca handle found"); 56 return (ISER_STATUS_FAIL); 57 } 58 59 msg = iser_msg_get(hca, 1, NULL); 60 61 if (msg == NULL) { 62 ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: iser message cache " 63 "alloc failed"); 64 return (ISER_STATUS_FAIL); 65 } 66 67 /* Send iSER Hello Message to declare iSER parameters to the target */ 68 hdr = (iser_hello_hdr_t *)(uintptr_t)msg->msg_ds.ds_va; 69 70 hdr->opcode = ISER_OPCODE_HELLO_MSG; 71 hdr->rsvd1 = 0; 72 hdr->maxver = 1; 73 hdr->minver = 1; 74 hdr->iser_ird = htons(ISER_IB_DEFAULT_IRD); 75 hdr->rsvd2[0] = 0; 76 hdr->rsvd2[1] = 0; 77 78 /* Allocate an iSER WR handle and tuck this msg into it */ 79 iser_wr = iser_wr_get(); 80 if (iser_wr == NULL) { 81 ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: unable to allocate " 82 "iser wr handle"); 83 iser_msg_free(msg); 84 return (ISER_STATUS_FAIL); 85 } 86 iser_wr->iw_msg = msg; 87 iser_wr->iw_type = ISER_WR_SEND; 88 89 /* Use the address of our generic iser_wr handle as our WRID */ 90 wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr; 91 92 /* Populate the rest of the work request */ 93 wr.wr_trans = IBT_RC_SRV; 94 wr.wr_opcode = IBT_WRC_SEND; 95 wr.wr_nds = 1; 96 wr.wr_sgl = &msg->msg_ds; 97 98 /* 99 * Avoid race condition by incrementing this channel's 100 * SQ posted count prior to calling ibt_post_send 101 */ 102 mutex_enter(&chan->ic_sq_post_lock); 103 chan->ic_sq_post_count++; 104 if (chan->ic_sq_post_count > chan->ic_sq_max_post_count) 105 chan->ic_sq_max_post_count = chan->ic_sq_post_count; 106 mutex_exit(&chan->ic_sq_post_lock); 107 108 status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL); 109 if (status != IBT_SUCCESS) { 110 ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: ibt_post_send " 111 "failure (%d)", status); 112 mutex_enter(&chan->ic_sq_post_lock); 113 chan->ic_sq_post_count--; 114 mutex_exit(&chan->ic_sq_post_lock); 115 iser_msg_free(msg); 116 iser_wr_free(iser_wr); 117 return (ISER_STATUS_FAIL); 118 } 119 120 ISER_LOG(CE_NOTE, "Posting iSER Hello message: chan (0x%p): " 121 "IP [%x to %x]", (void *)chan, chan->ic_localip.un.ip4addr, 122 chan->ic_remoteip.un.ip4addr); 123 124 return (ISER_STATUS_SUCCESS); 125 } 126 127 int 128 iser_xfer_helloreply_msg(iser_chan_t *chan) 129 { 130 iser_hca_t *hca; 131 iser_wr_t *iser_wr; 132 ibt_send_wr_t wr; 133 iser_msg_t *msg; 134 iser_helloreply_hdr_t *hdr; 135 int status; 136 137 ASSERT(chan != NULL); 138 139 hca = (iser_hca_t *)chan->ic_hca; 140 if (hca == NULL) { 141 ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: no hca handle " 142 "found"); 143 return (ISER_STATUS_FAIL); 144 } 145 146 msg = iser_msg_get(hca, 1, NULL); 147 148 if (msg == NULL) { 149 ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: iser message " 150 "cache alloc failed"); 151 return (ISER_STATUS_FAIL); 152 } 153 154 /* Use the iSER Hello Reply Message */ 155 hdr = (iser_helloreply_hdr_t *)(uintptr_t)msg->msg_ds.ds_va; 156 157 hdr->opcode = ISER_OPCODE_HELLOREPLY_MSG; 158 hdr->rsvd1 = 0; 159 hdr->flag = 0; 160 hdr->maxver = 1; 161 hdr->curver = 1; 162 hdr->iser_ord = htons(ISER_IB_DEFAULT_ORD); 163 hdr->rsvd2[0] = 0; 164 hdr->rsvd2[1] = 0; 165 166 /* Allocate an iSER WR handle and tuck this msg into it */ 167 iser_wr = iser_wr_get(); 168 if (iser_wr == NULL) { 169 ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: unable to " 170 "allocate iser wr handle"); 171 iser_msg_free(msg); 172 return (ISER_STATUS_FAIL); 173 } 174 iser_wr->iw_msg = msg; 175 iser_wr->iw_type = ISER_WR_SEND; 176 177 /* Use the address of our generic iser_wr handle as our WRID */ 178 wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr; 179 180 /* Populate the rest of the work request */ 181 wr.wr_trans = IBT_RC_SRV; 182 wr.wr_opcode = IBT_WRC_SEND; 183 wr.wr_nds = 1; 184 wr.wr_sgl = &msg->msg_ds; 185 186 mutex_enter(&chan->ic_sq_post_lock); 187 chan->ic_sq_post_count++; 188 if (chan->ic_sq_post_count > chan->ic_sq_max_post_count) 189 chan->ic_sq_max_post_count = chan->ic_sq_post_count; 190 191 mutex_exit(&chan->ic_sq_post_lock); 192 193 status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL); 194 if (status != IBT_SUCCESS) { 195 ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: ibt_post_send " 196 "failure (%d)", status); 197 mutex_enter(&chan->ic_sq_post_lock); 198 chan->ic_sq_post_count--; 199 mutex_exit(&chan->ic_sq_post_lock); 200 iser_msg_free(msg); 201 iser_wr_free(iser_wr); 202 return (ISER_STATUS_FAIL); 203 } 204 ISER_LOG(CE_NOTE, "Posting iSER HelloReply message: chan (0x%p): " 205 "IP [%x to %x]", (void *)chan, chan->ic_localip.un.ip4addr, 206 chan->ic_remoteip.un.ip4addr); 207 208 return (ISER_STATUS_SUCCESS); 209 } 210 211 /* 212 * iser_xfer_ctrlpdu 213 * 214 * This is iSER's implementation of the 'Send_control' operational primitive. 215 * This iSER layer uses the Send Message type of RCaP to transfer the iSCSI 216 * Control-type PDU. A special case is that the transfer of SCSI Data-out PDUs 217 * carrying unsolicited data are also treated as iSCSI Control-Type PDUs. The 218 * message payload contains an iSER header followed by the iSCSI Control-type 219 * the iSCSI Control-type PDU. 220 * This function is invoked by an initiator iSCSI layer requesting the transfer 221 * of a iSCSI command PDU or a target iSCSI layer requesting the transfer of a 222 * iSCSI response PDU. 223 */ 224 int 225 iser_xfer_ctrlpdu(iser_chan_t *chan, idm_pdu_t *pdu) 226 { 227 iser_hca_t *hca; 228 iser_ctrl_hdr_t *hdr; 229 iser_msg_t *msg; 230 iser_wr_t *iser_wr; 231 ibt_send_wr_t wr; 232 int status; 233 iser_mr_t *mr; 234 iscsi_data_hdr_t *bhs; 235 idm_conn_t *ic; 236 idm_task_t *idt = NULL; 237 idm_buf_t *buf; 238 239 ASSERT(chan != NULL); 240 241 mutex_enter(&chan->ic_conn->ic_lock); 242 /* Bail out if the connection is closed */ 243 if ((chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) || 244 (chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) { 245 mutex_exit(&chan->ic_conn->ic_lock); 246 return (ISER_STATUS_FAIL); 247 } 248 249 ic = chan->ic_conn->ic_idmc; 250 251 /* Pull the BHS out of the PDU handle */ 252 bhs = (iscsi_data_hdr_t *)pdu->isp_hdr; 253 254 /* 255 * All SCSI command PDU (except SCSI Read and SCSI Write) and the SCSI 256 * Response PDU are sent to the remote end using the SendSE Message. 257 * 258 * The StatSN may need to be sent (and possibly advanced) at this time 259 * for some PDUs, identified by the IDM_PDU_SET_STATSN flag. 260 */ 261 if (pdu->isp_flags & IDM_PDU_SET_STATSN) { 262 (ic->ic_conn_ops.icb_update_statsn)(NULL, pdu); 263 } 264 /* 265 * Setup a Send Message for carrying the iSCSI control-type PDU 266 * preceeded by an iSER header. 267 */ 268 hca = (iser_hca_t *)chan->ic_hca; 269 if (hca == NULL) { 270 ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: no hca handle found"); 271 mutex_exit(&chan->ic_conn->ic_lock); 272 return (ISER_STATUS_FAIL); 273 } 274 275 msg = iser_msg_get(hca, 1, NULL); 276 if (msg == NULL) { 277 ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: iser message cache " 278 "alloc failed"); 279 mutex_exit(&chan->ic_conn->ic_lock); 280 return (ISER_STATUS_FAIL); 281 } 282 283 hdr = (iser_ctrl_hdr_t *)(uintptr_t)msg->msg_ds.ds_va; 284 285 /* 286 * Initialize header assuming no transfers 287 */ 288 bzero(hdr, sizeof (*hdr)); 289 hdr->opcode = ISER_OPCODE_CTRL_TYPE_PDU; 290 291 /* 292 * On the initiator side, the task buffers will be used to identify 293 * if there are any buffers to be advertised 294 */ 295 if ((ic->ic_conn_type == CONN_TYPE_INI) && 296 ((bhs->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_CMD) && 297 ((idt = idm_task_find(ic, bhs->itt, bhs->ttt)) != NULL)) { 298 299 if (!list_is_empty(&idt->idt_inbufv)) { 300 buf = idm_buf_find(&idt->idt_inbufv, 0); 301 ASSERT(buf != NULL); 302 303 mr = (iser_mr_t *)buf->idb_reg_private; 304 ASSERT(mr != NULL); 305 306 hdr->rsv_flag = 1; 307 hdr->rstag = htonl(mr->is_mrrkey); 308 BE_OUT64(&hdr->rva, mr->is_mrva); 309 } 310 311 if (!list_is_empty(&idt->idt_outbufv)) { 312 buf = idm_buf_find(&idt->idt_outbufv, 0); 313 ASSERT(buf != NULL); 314 315 mr = (iser_mr_t *)buf->idb_reg_private; 316 ASSERT(mr != NULL); 317 318 hdr->wsv_flag = 1; 319 hdr->wstag = htonl(mr->is_mrrkey); 320 BE_OUT64(&hdr->wva, mr->is_mrva); 321 } 322 323 /* Release our reference on the task */ 324 idm_task_rele(idt); 325 } 326 327 /* Copy the BHS after the iSER header */ 328 bcopy(pdu->isp_hdr, 329 (uint8_t *)(uintptr_t)msg->msg_ds.ds_va + ISER_HEADER_LENGTH, 330 pdu->isp_hdrlen); 331 332 if (pdu->isp_datalen > 0) { 333 /* Copy the isp_data after the PDU header */ 334 bcopy(pdu->isp_data, 335 (uint8_t *)(uintptr_t)msg->msg_ds.ds_va + 336 ISER_HEADER_LENGTH + pdu->isp_hdrlen, 337 pdu->isp_datalen); 338 339 /* Set the SGE's ds_len */ 340 msg->msg_ds.ds_len = ISER_HEADER_LENGTH + pdu->isp_hdrlen + 341 pdu->isp_datalen; 342 } else { 343 /* No data, so set the SGE's ds_len to the headers length */ 344 msg->msg_ds.ds_len = ISER_HEADER_LENGTH + pdu->isp_hdrlen; 345 } 346 347 /* 348 * Build Work Request to be posted on the Send Queue. 349 */ 350 bzero(&wr, sizeof (wr)); 351 352 /* Allocate an iSER WR handle and tuck the msg and pdu into it */ 353 iser_wr = iser_wr_get(); 354 if (iser_wr == NULL) { 355 ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: unable to allocate " 356 "iser wr handle"); 357 iser_msg_free(msg); 358 mutex_exit(&chan->ic_conn->ic_lock); 359 return (ISER_STATUS_FAIL); 360 } 361 iser_wr->iw_pdu = pdu; 362 iser_wr->iw_msg = msg; 363 iser_wr->iw_type = ISER_WR_SEND; 364 365 /* 366 * Use the address of our generic iser_wr handle as our WRID 367 * and populate the rest of the work request 368 */ 369 wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr; 370 wr.wr_trans = IBT_RC_SRV; 371 wr.wr_opcode = IBT_WRC_SEND; 372 wr.wr_nds = 1; 373 wr.wr_sgl = &msg->msg_ds; 374 375 /* Increment this channel's SQ posted count */ 376 mutex_enter(&chan->ic_sq_post_lock); 377 chan->ic_sq_post_count++; 378 if (chan->ic_sq_post_count > chan->ic_sq_max_post_count) 379 chan->ic_sq_max_post_count = chan->ic_sq_post_count; 380 mutex_exit(&chan->ic_sq_post_lock); 381 382 /* Post Send Work Request on the specified channel */ 383 status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL); 384 if (status != IBT_SUCCESS) { 385 ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: ibt_post_send " 386 "failure (%d)", status); 387 iser_msg_free(msg); 388 iser_wr_free(iser_wr); 389 mutex_enter(&chan->ic_sq_post_lock); 390 chan->ic_sq_post_count--; 391 mutex_exit(&chan->ic_sq_post_lock); 392 mutex_exit(&chan->ic_conn->ic_lock); 393 return (ISER_STATUS_FAIL); 394 } 395 396 mutex_exit(&chan->ic_conn->ic_lock); 397 return (ISER_STATUS_SUCCESS); 398 } 399 400 /* 401 * iser_xfer_buf_to_ini 402 * This is iSER's implementation of the 'Put_Data' operational primitive. 403 * The iSCSI layer at the target invokes this function when it is ready to 404 * return the SCSI Read Data to the initiator. This function generates and 405 * sends an RDMA Write Message containing the read data to the initiator. 406 */ 407 int 408 iser_xfer_buf_to_ini(idm_task_t *idt, idm_buf_t *buf) 409 { 410 iser_conn_t *iser_conn; 411 iser_chan_t *iser_chan; 412 iser_buf_t *iser_buf; 413 iser_wr_t *iser_wr; 414 iser_ctrl_hdr_t *iser_hdr; 415 ibt_send_wr_t wr; 416 uint64_t reg_raddr; 417 uint32_t reg_rkey; 418 int status; 419 420 /* Grab the iSER resources from the task and buf handles */ 421 iser_conn = (iser_conn_t *)idt->idt_ic->ic_transport_private; 422 iser_chan = iser_conn->ic_chan; 423 424 mutex_enter(&iser_chan->ic_conn->ic_lock); 425 /* Bail out if the connection is closed */ 426 if ((iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) || 427 (iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) { 428 mutex_exit(&iser_chan->ic_conn->ic_lock); 429 return (ISER_STATUS_FAIL); 430 } 431 432 iser_buf = (iser_buf_t *)buf->idb_buf_private; 433 iser_hdr = (iser_ctrl_hdr_t *)idt->idt_transport_hdr; 434 435 /* Pull the Read STag data out of the iSER header in the task hdl */ 436 reg_raddr = BE_IN64(&iser_hdr->rva); 437 reg_rkey = (ntohl(iser_hdr->rstag)); 438 439 /* Set up the WR raddr and rkey based upon the Read iSER STag */ 440 bzero(&wr, sizeof (ibt_send_wr_t)); 441 wr.wr.rc.rcwr.rdma.rdma_raddr = reg_raddr + buf->idb_bufoffset; 442 wr.wr.rc.rcwr.rdma.rdma_rkey = reg_rkey; 443 444 /* Set the transfer length from the IDM buf handle */ 445 iser_buf->buf_ds.ds_len = buf->idb_xfer_len; 446 447 /* Allocate an iSER WR handle and tuck the IDM buf handle into it */ 448 iser_wr = iser_wr_get(); 449 if (iser_wr == NULL) { 450 ISER_LOG(CE_NOTE, "iser_xfer_buf_to_ini: unable to allocate " 451 "iser wr handle"); 452 mutex_exit(&iser_chan->ic_conn->ic_lock); 453 return (ISER_STATUS_FAIL); 454 } 455 iser_wr->iw_buf = buf; 456 iser_wr->iw_type = ISER_WR_RDMAW; 457 458 /* Use the address of our generic iser_wr handle as our WRID */ 459 wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr; 460 461 /* Populate the rest of the work request */ 462 wr.wr_flags = IBT_WR_SEND_SIGNAL; 463 wr.wr_trans = IBT_RC_SRV; 464 wr.wr_opcode = IBT_WRC_RDMAW; 465 wr.wr_nds = 1; 466 wr.wr_sgl = &iser_buf->buf_ds; 467 468 #ifdef DEBUG 469 bcopy(&wr, &iser_buf->buf_wr, sizeof (ibt_send_wr_t)); 470 #endif 471 472 DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic, 473 uintptr_t, buf->idb_buf, uint32_t, buf->idb_bufoffset, 474 uint64_t, reg_raddr, uint32_t, buf->idb_bufoffset, 475 uint32_t, reg_rkey, 476 uint32_t, buf->idb_xfer_len, int, XFER_BUF_TX_TO_INI); 477 478 /* Increment this channel's SQ posted count */ 479 mutex_enter(&iser_chan->ic_sq_post_lock); 480 iser_chan->ic_sq_post_count++; 481 if (iser_chan->ic_sq_post_count > iser_chan->ic_sq_max_post_count) 482 iser_chan->ic_sq_max_post_count = iser_chan->ic_sq_post_count; 483 mutex_exit(&iser_chan->ic_sq_post_lock); 484 485 status = ibt_post_send(iser_chan->ic_chanhdl, &wr, 1, NULL); 486 if (status != IBT_SUCCESS) { 487 ISER_LOG(CE_NOTE, "iser_xfer_buf_to_ini: ibt_post_send " 488 "failure (%d)", status); 489 iser_wr_free(iser_wr); 490 mutex_enter(&iser_chan->ic_sq_post_lock); 491 iser_chan->ic_sq_post_count--; 492 mutex_exit(&iser_chan->ic_sq_post_lock); 493 mutex_exit(&iser_chan->ic_conn->ic_lock); 494 return (ISER_STATUS_FAIL); 495 } 496 497 mutex_exit(&iser_chan->ic_conn->ic_lock); 498 return (ISER_STATUS_SUCCESS); 499 } 500 501 /* 502 * iser_xfer_buf_from_ini 503 * This is iSER's implementation of the 'Get_Data' operational primitive. 504 * The iSCSI layer at the target invokes this function when it is ready to 505 * receive the SCSI Write Data from the initiator. This function generates and 506 * sends an RDMA Read Message to get the data from the initiator. No R2T PDUs 507 * are generated. 508 */ 509 int 510 iser_xfer_buf_from_ini(idm_task_t *idt, idm_buf_t *buf) 511 { 512 iser_conn_t *iser_conn; 513 iser_chan_t *iser_chan; 514 iser_buf_t *iser_buf; 515 iser_wr_t *iser_wr; 516 iser_ctrl_hdr_t *iser_hdr; 517 ibt_send_wr_t wr; 518 uint64_t reg_raddr; 519 uint32_t reg_rkey; 520 int status; 521 522 /* Grab the iSER resources from the task and buf handles */ 523 iser_conn = (iser_conn_t *)idt->idt_ic->ic_transport_private; 524 iser_chan = iser_conn->ic_chan; 525 526 mutex_enter(&iser_chan->ic_conn->ic_lock); 527 /* Bail out if the connection is closed */ 528 if ((iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) || 529 (iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) { 530 mutex_exit(&iser_chan->ic_conn->ic_lock); 531 return (ISER_STATUS_FAIL); 532 } 533 534 iser_buf = (iser_buf_t *)buf->idb_buf_private; 535 iser_hdr = (iser_ctrl_hdr_t *)idt->idt_transport_hdr; 536 537 /* Pull the Write STag data out of the iSER header in the task hdl */ 538 reg_raddr = BE_IN64(&iser_hdr->wva); 539 reg_rkey = (ntohl(iser_hdr->wstag)); 540 541 /* Set up the WR raddr and rkey based upon the iSER Write STag */ 542 bzero(&wr, sizeof (ibt_send_wr_t)); 543 wr.wr.rc.rcwr.rdma.rdma_raddr = reg_raddr + buf->idb_bufoffset; 544 wr.wr.rc.rcwr.rdma.rdma_rkey = reg_rkey; 545 546 /* Set the transfer length from the IDM buf handle */ 547 iser_buf->buf_ds.ds_len = buf->idb_xfer_len; 548 549 /* Allocate an iSER WR handle and tuck the IDM buf handle into it */ 550 iser_wr = iser_wr_get(); 551 if (iser_wr == NULL) { 552 ISER_LOG(CE_NOTE, "iser_xfer_buf_from_ini: unable to allocate " 553 "iser wr handle"); 554 mutex_exit(&iser_chan->ic_conn->ic_lock); 555 return (ISER_STATUS_FAIL); 556 } 557 iser_wr->iw_buf = buf; 558 iser_wr->iw_type = ISER_WR_RDMAR; 559 560 /* Use the address of our generic iser_wr handle as our WRID */ 561 wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr; 562 563 /* Populate the rest of the work request */ 564 wr.wr_flags = IBT_WR_SEND_SIGNAL; 565 wr.wr_trans = IBT_RC_SRV; 566 wr.wr_opcode = IBT_WRC_RDMAR; 567 wr.wr_nds = 1; 568 wr.wr_sgl = &iser_buf->buf_ds; 569 570 #ifdef DEBUG 571 bcopy(&wr, &iser_buf->buf_wr, sizeof (ibt_send_wr_t)); 572 #endif 573 574 DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic, 575 uintptr_t, buf->idb_buf, uint32_t, buf->idb_bufoffset, 576 uint64_t, reg_raddr, uint32_t, buf->idb_bufoffset, 577 uint32_t, reg_rkey, 578 uint32_t, buf->idb_xfer_len, int, XFER_BUF_RX_FROM_INI); 579 580 /* Increment this channel's SQ posted count */ 581 mutex_enter(&iser_chan->ic_sq_post_lock); 582 iser_chan->ic_sq_post_count++; 583 if (iser_chan->ic_sq_post_count > iser_chan->ic_sq_max_post_count) 584 iser_chan->ic_sq_max_post_count = iser_chan->ic_sq_post_count; 585 mutex_exit(&iser_chan->ic_sq_post_lock); 586 587 status = ibt_post_send(iser_chan->ic_chanhdl, &wr, 1, NULL); 588 if (status != IBT_SUCCESS) { 589 ISER_LOG(CE_NOTE, "iser_xfer_buf_from_ini: ibt_post_send " 590 "failure (%d)", status); 591 iser_wr_free(iser_wr); 592 mutex_enter(&iser_chan->ic_sq_post_lock); 593 iser_chan->ic_sq_post_count--; 594 mutex_exit(&iser_chan->ic_sq_post_lock); 595 mutex_exit(&iser_chan->ic_conn->ic_lock); 596 return (ISER_STATUS_FAIL); 597 } 598 599 mutex_exit(&iser_chan->ic_conn->ic_lock); 600 return (ISER_STATUS_SUCCESS); 601 } 602