19162SPeter.Dunlap@Sun.COM /*
29162SPeter.Dunlap@Sun.COM * CDDL HEADER START
39162SPeter.Dunlap@Sun.COM *
49162SPeter.Dunlap@Sun.COM * The contents of this file are subject to the terms of the
59162SPeter.Dunlap@Sun.COM * Common Development and Distribution License (the "License").
69162SPeter.Dunlap@Sun.COM * You may not use this file except in compliance with the License.
79162SPeter.Dunlap@Sun.COM *
89162SPeter.Dunlap@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99162SPeter.Dunlap@Sun.COM * or http://www.opensolaris.org/os/licensing.
109162SPeter.Dunlap@Sun.COM * See the License for the specific language governing permissions
119162SPeter.Dunlap@Sun.COM * and limitations under the License.
129162SPeter.Dunlap@Sun.COM *
139162SPeter.Dunlap@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149162SPeter.Dunlap@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159162SPeter.Dunlap@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169162SPeter.Dunlap@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179162SPeter.Dunlap@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189162SPeter.Dunlap@Sun.COM *
199162SPeter.Dunlap@Sun.COM * CDDL HEADER END
209162SPeter.Dunlap@Sun.COM */
219162SPeter.Dunlap@Sun.COM /*
229162SPeter.Dunlap@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
239162SPeter.Dunlap@Sun.COM * Use is subject to license terms.
249162SPeter.Dunlap@Sun.COM */
259162SPeter.Dunlap@Sun.COM
269162SPeter.Dunlap@Sun.COM #include <sys/types.h>
279162SPeter.Dunlap@Sun.COM #include <sys/ddi.h>
289162SPeter.Dunlap@Sun.COM #include <sys/types.h>
299162SPeter.Dunlap@Sun.COM #include <sys/socket.h>
309162SPeter.Dunlap@Sun.COM #include <netinet/in.h>
319162SPeter.Dunlap@Sun.COM #include <sys/sunddi.h>
329162SPeter.Dunlap@Sun.COM #include <sys/sdt.h>
339162SPeter.Dunlap@Sun.COM #include <sys/ib/ibtl/ibti.h>
349162SPeter.Dunlap@Sun.COM #include <sys/ib/ibtl/ibtl_types.h>
359162SPeter.Dunlap@Sun.COM
369162SPeter.Dunlap@Sun.COM #include <sys/ib/clients/iser/iser.h>
379162SPeter.Dunlap@Sun.COM
389162SPeter.Dunlap@Sun.COM /*
399162SPeter.Dunlap@Sun.COM * iser_cq.c
409162SPeter.Dunlap@Sun.COM * Routines for completion queue handlers for iSER.
419162SPeter.Dunlap@Sun.COM */
429162SPeter.Dunlap@Sun.COM static void iser_msg_handle(iser_chan_t *chan, iser_msg_t *msg);
439162SPeter.Dunlap@Sun.COM int iser_iscsihdr_handle(iser_chan_t *chan, iser_msg_t *msg);
449162SPeter.Dunlap@Sun.COM static int iser_ib_poll_send_completions(ibt_cq_hdl_t cq_hdl,
459162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan);
469162SPeter.Dunlap@Sun.COM static int iser_ib_poll_recv_completions(ibt_cq_hdl_t cq_hdl,
479162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan);
489162SPeter.Dunlap@Sun.COM
499162SPeter.Dunlap@Sun.COM void
iser_ib_sendcq_handler(ibt_cq_hdl_t cq_hdl,void * arg)509162SPeter.Dunlap@Sun.COM iser_ib_sendcq_handler(ibt_cq_hdl_t cq_hdl, void *arg)
519162SPeter.Dunlap@Sun.COM {
529162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan;
539162SPeter.Dunlap@Sun.COM ibt_status_t status;
549162SPeter.Dunlap@Sun.COM
559162SPeter.Dunlap@Sun.COM iser_chan = (iser_chan_t *)arg;
569162SPeter.Dunlap@Sun.COM
57*10101SPriya.Krishnan@Sun.COM /*
58*10101SPriya.Krishnan@Sun.COM * Poll for work request completion while successful. If the
59*10101SPriya.Krishnan@Sun.COM * queue empties or otherwise becomes invalid, stop polling.
60*10101SPriya.Krishnan@Sun.COM */
619162SPeter.Dunlap@Sun.COM do {
629162SPeter.Dunlap@Sun.COM status = iser_ib_poll_send_completions(cq_hdl, iser_chan);
63*10101SPriya.Krishnan@Sun.COM } while (status == IBT_SUCCESS);
649162SPeter.Dunlap@Sun.COM
65*10101SPriya.Krishnan@Sun.COM if (status == IBT_CQ_EMPTY) {
66*10101SPriya.Krishnan@Sun.COM /* We've emptied the CQ, rearm it before we're done here */
67*10101SPriya.Krishnan@Sun.COM status = ibt_enable_cq_notify(cq_hdl, IBT_NEXT_COMPLETION);
68*10101SPriya.Krishnan@Sun.COM if (status != IBT_SUCCESS) {
69*10101SPriya.Krishnan@Sun.COM /* Unexpected error */
70*10101SPriya.Krishnan@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_sendcq_handler: "
71*10101SPriya.Krishnan@Sun.COM "ibt_enable_cq_notify error (%d)", status);
72*10101SPriya.Krishnan@Sun.COM return;
73*10101SPriya.Krishnan@Sun.COM }
74*10101SPriya.Krishnan@Sun.COM
75*10101SPriya.Krishnan@Sun.COM /* Now, check for more completions after the rearm */
76*10101SPriya.Krishnan@Sun.COM do {
77*10101SPriya.Krishnan@Sun.COM status = iser_ib_poll_send_completions(
78*10101SPriya.Krishnan@Sun.COM cq_hdl, iser_chan);
79*10101SPriya.Krishnan@Sun.COM } while (status == IBT_SUCCESS);
809162SPeter.Dunlap@Sun.COM }
819162SPeter.Dunlap@Sun.COM }
829162SPeter.Dunlap@Sun.COM
839162SPeter.Dunlap@Sun.COM static int
iser_ib_poll_send_completions(ibt_cq_hdl_t cq_hdl,iser_chan_t * iser_chan)849162SPeter.Dunlap@Sun.COM iser_ib_poll_send_completions(ibt_cq_hdl_t cq_hdl, iser_chan_t *iser_chan)
859162SPeter.Dunlap@Sun.COM {
869162SPeter.Dunlap@Sun.COM ibt_wc_t wc[ISER_IB_SCQ_POLL_MAX];
879162SPeter.Dunlap@Sun.COM ibt_wrid_t wrid;
889162SPeter.Dunlap@Sun.COM idm_buf_t *idb = NULL;
899162SPeter.Dunlap@Sun.COM idm_task_t *idt = NULL;
909162SPeter.Dunlap@Sun.COM iser_wr_t *wr = NULL;
919162SPeter.Dunlap@Sun.COM int i;
929162SPeter.Dunlap@Sun.COM uint_t npoll = 0;
939162SPeter.Dunlap@Sun.COM ibt_status_t status;
949162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
959162SPeter.Dunlap@Sun.COM idm_status_t idm_status;
969721SPriya.Krishnan@Sun.COM iser_mr_t *mr;
979162SPeter.Dunlap@Sun.COM
989162SPeter.Dunlap@Sun.COM iser_conn = iser_chan->ic_conn;
999162SPeter.Dunlap@Sun.COM
100*10101SPriya.Krishnan@Sun.COM /* Poll ISER_IB_SCQ_POLL_MAX completions from the CQ */
1019162SPeter.Dunlap@Sun.COM status = ibt_poll_cq(cq_hdl, wc, ISER_IB_SCQ_POLL_MAX, &npoll);
1029162SPeter.Dunlap@Sun.COM
1039162SPeter.Dunlap@Sun.COM if (status != IBT_SUCCESS) {
1049162SPeter.Dunlap@Sun.COM if (status != IBT_CQ_EMPTY) {
1059162SPeter.Dunlap@Sun.COM /* Unexpected error */
1069162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_sendcq_handler: ibt_poll_cq "
107*10101SPriya.Krishnan@Sun.COM "unexpected error (%d)", status);
1089162SPeter.Dunlap@Sun.COM }
1099162SPeter.Dunlap@Sun.COM /* CQ is empty. Either way, move along... */
1109162SPeter.Dunlap@Sun.COM return (status);
1119162SPeter.Dunlap@Sun.COM }
1129162SPeter.Dunlap@Sun.COM
1139162SPeter.Dunlap@Sun.COM /*
1149162SPeter.Dunlap@Sun.COM * Handle each of the completions we've polled
1159162SPeter.Dunlap@Sun.COM */
1169162SPeter.Dunlap@Sun.COM for (i = 0; i < npoll; i++) {
1179162SPeter.Dunlap@Sun.COM
1189162SPeter.Dunlap@Sun.COM DTRACE_PROBE3(iser__send__cqe, iser_chan_t *, iser_chan,
1199162SPeter.Dunlap@Sun.COM ibt_wc_t *, &wc[i], ibt_wc_status_t, wc[i].wc_status);
1209162SPeter.Dunlap@Sun.COM
1219162SPeter.Dunlap@Sun.COM /* Grab the wrid of the completion */
1229162SPeter.Dunlap@Sun.COM wrid = wc[i].wc_id;
1239162SPeter.Dunlap@Sun.COM
1249162SPeter.Dunlap@Sun.COM /* Decrement this channel's SQ posted count */
1259162SPeter.Dunlap@Sun.COM mutex_enter(&iser_chan->ic_sq_post_lock);
1269162SPeter.Dunlap@Sun.COM iser_chan->ic_sq_post_count--;
1279162SPeter.Dunlap@Sun.COM mutex_exit(&iser_chan->ic_sq_post_lock);
1289162SPeter.Dunlap@Sun.COM
1299162SPeter.Dunlap@Sun.COM /* Pull in the wr handle */
1309162SPeter.Dunlap@Sun.COM wr = (iser_wr_t *)(uintptr_t)wrid;
1319162SPeter.Dunlap@Sun.COM ASSERT(wr != NULL);
1329162SPeter.Dunlap@Sun.COM
1339162SPeter.Dunlap@Sun.COM /* Set an idm_status for return to IDM */
1349162SPeter.Dunlap@Sun.COM idm_status = (wc[i].wc_status == IBT_WC_SUCCESS) ?
1359162SPeter.Dunlap@Sun.COM IDM_STATUS_SUCCESS : IDM_STATUS_FAIL;
1369162SPeter.Dunlap@Sun.COM
1379162SPeter.Dunlap@Sun.COM /*
1389162SPeter.Dunlap@Sun.COM * A non-success status here indicates the QP went
1399162SPeter.Dunlap@Sun.COM * into an error state while this WR was being
1409162SPeter.Dunlap@Sun.COM * processed. This can also happen when the
1419162SPeter.Dunlap@Sun.COM * channel is closed on the remote end. Clean up
1429162SPeter.Dunlap@Sun.COM * the resources, then push CE_TRANSPORT_FAIL
1439162SPeter.Dunlap@Sun.COM * into IDM.
1449162SPeter.Dunlap@Sun.COM */
1459162SPeter.Dunlap@Sun.COM if (wc[i].wc_status != IBT_WC_SUCCESS) {
1469162SPeter.Dunlap@Sun.COM /*
1479162SPeter.Dunlap@Sun.COM * Free the resources attached to this
1489162SPeter.Dunlap@Sun.COM * completion.
1499162SPeter.Dunlap@Sun.COM */
1509162SPeter.Dunlap@Sun.COM if (wr->iw_msg != NULL) {
1519162SPeter.Dunlap@Sun.COM /* Free iser_msg handle */
1529162SPeter.Dunlap@Sun.COM iser_msg_free(wr->iw_msg);
1539162SPeter.Dunlap@Sun.COM }
1549162SPeter.Dunlap@Sun.COM
1559162SPeter.Dunlap@Sun.COM if (wr->iw_pdu != NULL) {
1569162SPeter.Dunlap@Sun.COM /* Complete the PDU */
1579162SPeter.Dunlap@Sun.COM idm_pdu_complete(wr->iw_pdu, idm_status);
1589162SPeter.Dunlap@Sun.COM }
1599162SPeter.Dunlap@Sun.COM
1609162SPeter.Dunlap@Sun.COM if (wr->iw_buf != NULL) {
1619162SPeter.Dunlap@Sun.COM /* Invoke buffer callback */
1629162SPeter.Dunlap@Sun.COM idb = wr->iw_buf;
1639721SPriya.Krishnan@Sun.COM mr = ((iser_buf_t *)
1649721SPriya.Krishnan@Sun.COM idb->idb_buf_private)->iser_mr;
1659162SPeter.Dunlap@Sun.COM #ifdef DEBUG
1669162SPeter.Dunlap@Sun.COM bcopy(&wc[i],
1679162SPeter.Dunlap@Sun.COM &((iser_buf_t *)idb->idb_buf_private)->
1689162SPeter.Dunlap@Sun.COM buf_wc, sizeof (ibt_wc_t));
1699162SPeter.Dunlap@Sun.COM #endif
1709162SPeter.Dunlap@Sun.COM idt = idb->idb_task_binding;
1719162SPeter.Dunlap@Sun.COM mutex_enter(&idt->idt_mutex);
1729162SPeter.Dunlap@Sun.COM if (wr->iw_type == ISER_WR_RDMAW) {
1739721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_8(xfer__done,
1749721SPriya.Krishnan@Sun.COM idm_conn_t *, idt->idt_ic,
1759721SPriya.Krishnan@Sun.COM uintptr_t, idb->idb_buf,
1769721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_bufoffset,
1779721SPriya.Krishnan@Sun.COM uint64_t, mr->is_mrva, uint32_t, 0,
1789721SPriya.Krishnan@Sun.COM uint32_t, mr->is_mrrkey,
1799721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_xfer_len,
1809721SPriya.Krishnan@Sun.COM int, XFER_BUF_TX_TO_INI);
1819162SPeter.Dunlap@Sun.COM idm_buf_tx_to_ini_done(idt, idb,
1829162SPeter.Dunlap@Sun.COM IDM_STATUS_FAIL);
1839162SPeter.Dunlap@Sun.COM } else { /* ISER_WR_RDMAR */
1849721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_8(xfer__done,
1859721SPriya.Krishnan@Sun.COM idm_conn_t *, idt->idt_ic,
1869721SPriya.Krishnan@Sun.COM uintptr_t, idb->idb_buf,
1879721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_bufoffset,
1889721SPriya.Krishnan@Sun.COM uint64_t, mr->is_mrva, uint32_t, 0,
1899721SPriya.Krishnan@Sun.COM uint32_t, mr->is_mrrkey,
1909721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_xfer_len,
1919721SPriya.Krishnan@Sun.COM int, XFER_BUF_RX_FROM_INI);
1929162SPeter.Dunlap@Sun.COM idm_buf_rx_from_ini_done(idt, idb,
1939162SPeter.Dunlap@Sun.COM IDM_STATUS_FAIL);
1949162SPeter.Dunlap@Sun.COM }
1959162SPeter.Dunlap@Sun.COM }
1969162SPeter.Dunlap@Sun.COM
1979162SPeter.Dunlap@Sun.COM /* Free the iser wr handle */
1989162SPeter.Dunlap@Sun.COM iser_wr_free(wr);
1999162SPeter.Dunlap@Sun.COM
2009162SPeter.Dunlap@Sun.COM /*
2019162SPeter.Dunlap@Sun.COM * Tell IDM that the channel has gone down,
2029162SPeter.Dunlap@Sun.COM * unless he already knows.
2039162SPeter.Dunlap@Sun.COM */
2049162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
2059162SPeter.Dunlap@Sun.COM switch (iser_conn->ic_stage) {
2069162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_DISCONNECTED:
2079162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_FREED:
2089162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSING:
2099162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSED:
2109162SPeter.Dunlap@Sun.COM break;
2119162SPeter.Dunlap@Sun.COM
2129162SPeter.Dunlap@Sun.COM default:
2139162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc,
2149162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, idm_status);
2159162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
2169162SPeter.Dunlap@Sun.COM }
2179162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
2189162SPeter.Dunlap@Sun.COM
2199162SPeter.Dunlap@Sun.COM /* Move onto the next completion */
2209162SPeter.Dunlap@Sun.COM continue;
2219162SPeter.Dunlap@Sun.COM }
2229162SPeter.Dunlap@Sun.COM
2239162SPeter.Dunlap@Sun.COM /*
2249162SPeter.Dunlap@Sun.COM * For a success status, just invoke the PDU or
2259162SPeter.Dunlap@Sun.COM * buffer completion. We use our WR handle's
2269162SPeter.Dunlap@Sun.COM * "iw_type" here so that we can properly process
2279162SPeter.Dunlap@Sun.COM * because the CQE's opcode is invalid if the status
2289162SPeter.Dunlap@Sun.COM * is failed.
2299162SPeter.Dunlap@Sun.COM */
2309162SPeter.Dunlap@Sun.COM switch (wr->iw_type) {
2319162SPeter.Dunlap@Sun.COM case ISER_WR_SEND:
2329162SPeter.Dunlap@Sun.COM /* Free the msg handle */
2339162SPeter.Dunlap@Sun.COM ASSERT(wr->iw_msg != NULL);
2349162SPeter.Dunlap@Sun.COM iser_msg_free(wr->iw_msg);
2359162SPeter.Dunlap@Sun.COM
2369162SPeter.Dunlap@Sun.COM if (wr->iw_pdu == NULL) {
2379162SPeter.Dunlap@Sun.COM /* This is a hello exchange message */
2389162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
2399162SPeter.Dunlap@Sun.COM if (iser_conn->ic_stage ==
2409162SPeter.Dunlap@Sun.COM ISER_CONN_STAGE_HELLOREPLY_SENT) {
2419162SPeter.Dunlap@Sun.COM /*
2429162SPeter.Dunlap@Sun.COM * We're on the target side,
2439162SPeter.Dunlap@Sun.COM * and have just successfully
2449162SPeter.Dunlap@Sun.COM * sent the HelloReply msg.
2459162SPeter.Dunlap@Sun.COM */
2469162SPeter.Dunlap@Sun.COM iser_conn->ic_stage =
2479162SPeter.Dunlap@Sun.COM ISER_CONN_STAGE_LOGGED_IN;
2489162SPeter.Dunlap@Sun.COM }
2499162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
2509162SPeter.Dunlap@Sun.COM } else {
2519162SPeter.Dunlap@Sun.COM /* This is a normal control message */
2529162SPeter.Dunlap@Sun.COM idm_pdu_complete(wr->iw_pdu, idm_status);
2539162SPeter.Dunlap@Sun.COM }
2549162SPeter.Dunlap@Sun.COM
2559162SPeter.Dunlap@Sun.COM /* Free the wr handle */
2569162SPeter.Dunlap@Sun.COM iser_wr_free(wr);
2579162SPeter.Dunlap@Sun.COM
2589162SPeter.Dunlap@Sun.COM break;
2599162SPeter.Dunlap@Sun.COM
2609162SPeter.Dunlap@Sun.COM case ISER_WR_RDMAW:
2619162SPeter.Dunlap@Sun.COM case ISER_WR_RDMAR:
2629162SPeter.Dunlap@Sun.COM /*
2639162SPeter.Dunlap@Sun.COM * Invoke the appropriate callback;
2649162SPeter.Dunlap@Sun.COM * the buffer will be freed there.
2659162SPeter.Dunlap@Sun.COM */
2669162SPeter.Dunlap@Sun.COM idb = wr->iw_buf;
2679721SPriya.Krishnan@Sun.COM mr = ((iser_buf_t *)idb->idb_buf_private)->iser_mr;
2689162SPeter.Dunlap@Sun.COM #ifdef DEBUG
2699162SPeter.Dunlap@Sun.COM bcopy(&wc[i],
2709162SPeter.Dunlap@Sun.COM &((iser_buf_t *)idb->idb_buf_private)->buf_wc,
2719162SPeter.Dunlap@Sun.COM sizeof (ibt_wc_t));
2729162SPeter.Dunlap@Sun.COM #endif
2739162SPeter.Dunlap@Sun.COM idt = idb->idb_task_binding;
2749162SPeter.Dunlap@Sun.COM
2759162SPeter.Dunlap@Sun.COM mutex_enter(&idt->idt_mutex);
2769162SPeter.Dunlap@Sun.COM if (wr->iw_type == ISER_WR_RDMAW) {
2779721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_8(xfer__done,
2789721SPriya.Krishnan@Sun.COM idm_conn_t *, idt->idt_ic,
2799721SPriya.Krishnan@Sun.COM uintptr_t, idb->idb_buf,
2809721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_bufoffset,
2819721SPriya.Krishnan@Sun.COM uint64_t, mr->is_mrva, uint32_t, 0,
2829721SPriya.Krishnan@Sun.COM uint32_t, mr->is_mrrkey,
2839721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_xfer_len,
2849721SPriya.Krishnan@Sun.COM int, XFER_BUF_TX_TO_INI);
2859162SPeter.Dunlap@Sun.COM idm_buf_tx_to_ini_done(idt, idb, idm_status);
2869162SPeter.Dunlap@Sun.COM } else {
2879721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_8(xfer__done,
2889721SPriya.Krishnan@Sun.COM idm_conn_t *, idt->idt_ic,
2899721SPriya.Krishnan@Sun.COM uintptr_t, idb->idb_buf,
2909721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_bufoffset,
2919721SPriya.Krishnan@Sun.COM uint64_t, mr->is_mrva, uint32_t, 0,
2929721SPriya.Krishnan@Sun.COM uint32_t, mr->is_mrrkey,
2939721SPriya.Krishnan@Sun.COM uint32_t, idb->idb_xfer_len,
2949721SPriya.Krishnan@Sun.COM int, XFER_BUF_RX_FROM_INI);
2959162SPeter.Dunlap@Sun.COM idm_buf_rx_from_ini_done(idt, idb, idm_status);
2969162SPeter.Dunlap@Sun.COM }
2979162SPeter.Dunlap@Sun.COM
2989162SPeter.Dunlap@Sun.COM /* Free the wr handle */
2999162SPeter.Dunlap@Sun.COM iser_wr_free(wr);
3009162SPeter.Dunlap@Sun.COM
3019162SPeter.Dunlap@Sun.COM break;
3029162SPeter.Dunlap@Sun.COM
3039162SPeter.Dunlap@Sun.COM default:
3049162SPeter.Dunlap@Sun.COM ASSERT(0);
3059162SPeter.Dunlap@Sun.COM break;
3069162SPeter.Dunlap@Sun.COM }
3079162SPeter.Dunlap@Sun.COM }
3089162SPeter.Dunlap@Sun.COM
3099162SPeter.Dunlap@Sun.COM return (status);
3109162SPeter.Dunlap@Sun.COM }
3119162SPeter.Dunlap@Sun.COM
3129162SPeter.Dunlap@Sun.COM void
iser_ib_recvcq_handler(ibt_cq_hdl_t cq_hdl,void * arg)3139162SPeter.Dunlap@Sun.COM iser_ib_recvcq_handler(ibt_cq_hdl_t cq_hdl, void *arg)
3149162SPeter.Dunlap@Sun.COM {
3159162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan;
3169162SPeter.Dunlap@Sun.COM ibt_status_t status;
3179162SPeter.Dunlap@Sun.COM
3189162SPeter.Dunlap@Sun.COM iser_chan = (iser_chan_t *)arg;
3199162SPeter.Dunlap@Sun.COM
320*10101SPriya.Krishnan@Sun.COM /*
321*10101SPriya.Krishnan@Sun.COM * Poll for work request completion while successful. If the
322*10101SPriya.Krishnan@Sun.COM * queue empties or otherwise becomes invalid, stop polling.
323*10101SPriya.Krishnan@Sun.COM */
3249162SPeter.Dunlap@Sun.COM do {
3259162SPeter.Dunlap@Sun.COM status = iser_ib_poll_recv_completions(cq_hdl, iser_chan);
326*10101SPriya.Krishnan@Sun.COM } while (status == IBT_SUCCESS);
3279162SPeter.Dunlap@Sun.COM
328*10101SPriya.Krishnan@Sun.COM if (status == IBT_CQ_EMPTY) {
329*10101SPriya.Krishnan@Sun.COM /* We've emptied the CQ, rearm it before we're done here */
330*10101SPriya.Krishnan@Sun.COM status = ibt_enable_cq_notify(cq_hdl, IBT_NEXT_COMPLETION);
331*10101SPriya.Krishnan@Sun.COM if (status != IBT_SUCCESS) {
332*10101SPriya.Krishnan@Sun.COM /* Unexpected error */
333*10101SPriya.Krishnan@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_recvcq_handler: "
334*10101SPriya.Krishnan@Sun.COM "ibt_enable_cq_notify error (%d)", status);
335*10101SPriya.Krishnan@Sun.COM return;
336*10101SPriya.Krishnan@Sun.COM }
337*10101SPriya.Krishnan@Sun.COM
338*10101SPriya.Krishnan@Sun.COM /* Now, check for more completions after the rearm */
339*10101SPriya.Krishnan@Sun.COM do {
340*10101SPriya.Krishnan@Sun.COM status = iser_ib_poll_recv_completions(
341*10101SPriya.Krishnan@Sun.COM cq_hdl, iser_chan);
342*10101SPriya.Krishnan@Sun.COM } while (status == IBT_SUCCESS);
3439162SPeter.Dunlap@Sun.COM }
3449162SPeter.Dunlap@Sun.COM }
3459162SPeter.Dunlap@Sun.COM
3469162SPeter.Dunlap@Sun.COM static int
iser_ib_poll_recv_completions(ibt_cq_hdl_t cq_hdl,iser_chan_t * iser_chan)3479162SPeter.Dunlap@Sun.COM iser_ib_poll_recv_completions(ibt_cq_hdl_t cq_hdl, iser_chan_t *iser_chan)
3489162SPeter.Dunlap@Sun.COM {
3499162SPeter.Dunlap@Sun.COM ibt_wc_t wc;
3509162SPeter.Dunlap@Sun.COM iser_msg_t *msg;
3519162SPeter.Dunlap@Sun.COM iser_qp_t *iser_qp;
3529162SPeter.Dunlap@Sun.COM int status;
3539162SPeter.Dunlap@Sun.COM
3549162SPeter.Dunlap@Sun.COM iser_qp = &(iser_chan->ic_qp);
3559162SPeter.Dunlap@Sun.COM
3569162SPeter.Dunlap@Sun.COM bzero(&wc, sizeof (ibt_wc_t));
3579162SPeter.Dunlap@Sun.COM status = ibt_poll_cq(cq_hdl, &wc, 1, NULL);
3589162SPeter.Dunlap@Sun.COM if (status == IBT_CQ_EMPTY) {
3599162SPeter.Dunlap@Sun.COM /* CQ is empty, return */
3609162SPeter.Dunlap@Sun.COM return (status);
3619162SPeter.Dunlap@Sun.COM }
3629162SPeter.Dunlap@Sun.COM
3639162SPeter.Dunlap@Sun.COM if (status != IBT_SUCCESS) {
3649162SPeter.Dunlap@Sun.COM /* Unexpected error */
3659162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_poll_recv_completions: "
3669162SPeter.Dunlap@Sun.COM "ibt_poll_cq error (%d)", status);
3679162SPeter.Dunlap@Sun.COM mutex_enter(&iser_qp->qp_lock);
3689162SPeter.Dunlap@Sun.COM iser_qp->rq_level--;
3699162SPeter.Dunlap@Sun.COM mutex_exit(&iser_qp->qp_lock);
3709162SPeter.Dunlap@Sun.COM /* Free the msg handle (if we got it back) */
3719162SPeter.Dunlap@Sun.COM if ((msg = (iser_msg_t *)(uintptr_t)wc.wc_id) != NULL) {
3729162SPeter.Dunlap@Sun.COM iser_msg_free(msg);
3739162SPeter.Dunlap@Sun.COM }
3749162SPeter.Dunlap@Sun.COM return (status);
3759162SPeter.Dunlap@Sun.COM }
3769162SPeter.Dunlap@Sun.COM
3779162SPeter.Dunlap@Sun.COM /* Retrieve the iSER msg handle */
3789162SPeter.Dunlap@Sun.COM msg = (iser_msg_t *)(uintptr_t)wc.wc_id;
3799162SPeter.Dunlap@Sun.COM ASSERT(msg != NULL);
3809162SPeter.Dunlap@Sun.COM
3819162SPeter.Dunlap@Sun.COM /*
3829162SPeter.Dunlap@Sun.COM * Decrement the posted level in the RQ, then check
3839162SPeter.Dunlap@Sun.COM * to see if we need to fill the RQ back up (or if
3849162SPeter.Dunlap@Sun.COM * we are already on the taskq).
3859162SPeter.Dunlap@Sun.COM */
3869247SPeter.Dunlap@Sun.COM mutex_enter(&iser_chan->ic_conn->ic_lock);
3879162SPeter.Dunlap@Sun.COM mutex_enter(&iser_qp->qp_lock);
3889162SPeter.Dunlap@Sun.COM iser_qp->rq_level--;
3899162SPeter.Dunlap@Sun.COM
3909162SPeter.Dunlap@Sun.COM if ((iser_qp->rq_taskqpending == B_FALSE) &&
3919586SPeter.Dunlap@Sun.COM (iser_qp->rq_level <= iser_qp->rq_lwm) &&
3929586SPeter.Dunlap@Sun.COM (iser_chan->ic_conn->ic_stage >= ISER_CONN_STAGE_IC_CONNECTED) &&
3939586SPeter.Dunlap@Sun.COM (iser_chan->ic_conn->ic_stage <= ISER_CONN_STAGE_LOGGED_IN)) {
3949162SPeter.Dunlap@Sun.COM /* Set the pending flag and fire off a post_recv */
3959162SPeter.Dunlap@Sun.COM iser_qp->rq_taskqpending = B_TRUE;
3969162SPeter.Dunlap@Sun.COM mutex_exit(&iser_qp->qp_lock);
3979162SPeter.Dunlap@Sun.COM
3989247SPeter.Dunlap@Sun.COM status = iser_ib_post_recv_async(iser_chan->ic_chanhdl);
3999162SPeter.Dunlap@Sun.COM
4009162SPeter.Dunlap@Sun.COM if (status != DDI_SUCCESS) {
4019162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_poll_recv_completions: "
4029162SPeter.Dunlap@Sun.COM "task dispatch failed");
4039162SPeter.Dunlap@Sun.COM /* Failure to launch, unset the pending flag */
4049162SPeter.Dunlap@Sun.COM mutex_enter(&iser_qp->qp_lock);
4059162SPeter.Dunlap@Sun.COM iser_qp->rq_taskqpending = B_FALSE;
4069162SPeter.Dunlap@Sun.COM mutex_exit(&iser_qp->qp_lock);
4079162SPeter.Dunlap@Sun.COM }
4089162SPeter.Dunlap@Sun.COM } else {
4099162SPeter.Dunlap@Sun.COM mutex_exit(&iser_qp->qp_lock);
4109162SPeter.Dunlap@Sun.COM }
4119162SPeter.Dunlap@Sun.COM
4129162SPeter.Dunlap@Sun.COM DTRACE_PROBE3(iser__recv__cqe, iser_chan_t *, iser_chan,
4139162SPeter.Dunlap@Sun.COM ibt_wc_t *, &wc, ibt_wc_status_t, wc.wc_status);
4149162SPeter.Dunlap@Sun.COM if (wc.wc_status != IBT_WC_SUCCESS) {
4159162SPeter.Dunlap@Sun.COM /*
4169162SPeter.Dunlap@Sun.COM * Tell IDM that the channel has gone down,
4179162SPeter.Dunlap@Sun.COM * unless he already knows.
4189162SPeter.Dunlap@Sun.COM */
4199162SPeter.Dunlap@Sun.COM switch (iser_chan->ic_conn->ic_stage) {
4209162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_DISCONNECTED:
4219162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_FREED:
4229162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSING:
4239162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSED:
4249162SPeter.Dunlap@Sun.COM break;
4259162SPeter.Dunlap@Sun.COM
4269162SPeter.Dunlap@Sun.COM default:
4279162SPeter.Dunlap@Sun.COM idm_conn_event(iser_chan->ic_conn->ic_idmc,
4289162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, IDM_STATUS_FAIL);
4299162SPeter.Dunlap@Sun.COM iser_chan->ic_conn->ic_stage =
4309162SPeter.Dunlap@Sun.COM ISER_CONN_STAGE_CLOSING;
4319162SPeter.Dunlap@Sun.COM }
4329162SPeter.Dunlap@Sun.COM mutex_exit(&iser_chan->ic_conn->ic_lock);
4339162SPeter.Dunlap@Sun.COM
4349162SPeter.Dunlap@Sun.COM iser_msg_free(msg);
4359162SPeter.Dunlap@Sun.COM return (DDI_SUCCESS);
4369162SPeter.Dunlap@Sun.COM } else {
4379586SPeter.Dunlap@Sun.COM mutex_exit(&iser_chan->ic_conn->ic_lock);
4389586SPeter.Dunlap@Sun.COM
4399162SPeter.Dunlap@Sun.COM /*
4409162SPeter.Dunlap@Sun.COM * We have an iSER message in, let's handle it.
4419162SPeter.Dunlap@Sun.COM * We will free the iser_msg_t later in this path,
4429162SPeter.Dunlap@Sun.COM * depending upon the action required.
4439162SPeter.Dunlap@Sun.COM */
4449162SPeter.Dunlap@Sun.COM iser_msg_handle(iser_chan, msg);
4459162SPeter.Dunlap@Sun.COM return (DDI_SUCCESS);
4469162SPeter.Dunlap@Sun.COM }
4479162SPeter.Dunlap@Sun.COM }
4489162SPeter.Dunlap@Sun.COM
4499162SPeter.Dunlap@Sun.COM static void
iser_msg_handle(iser_chan_t * chan,iser_msg_t * msg)4509162SPeter.Dunlap@Sun.COM iser_msg_handle(iser_chan_t *chan, iser_msg_t *msg)
4519162SPeter.Dunlap@Sun.COM {
4529162SPeter.Dunlap@Sun.COM int opcode;
4539162SPeter.Dunlap@Sun.COM iser_ctrl_hdr_t *hdr = NULL;
4549162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn = chan->ic_conn;
4559162SPeter.Dunlap@Sun.COM int status;
4569162SPeter.Dunlap@Sun.COM
4579162SPeter.Dunlap@Sun.COM hdr = (iser_ctrl_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
4589162SPeter.Dunlap@Sun.COM ASSERT(hdr != NULL);
4599162SPeter.Dunlap@Sun.COM
4609162SPeter.Dunlap@Sun.COM opcode = hdr->opcode;
4619162SPeter.Dunlap@Sun.COM if (opcode == ISER_OPCODE_CTRL_TYPE_PDU) {
4629162SPeter.Dunlap@Sun.COM /*
4639162SPeter.Dunlap@Sun.COM * Handle an iSCSI Control PDU iSER message.
4649162SPeter.Dunlap@Sun.COM * Note we'll free the msg handle in the PDU callback.
4659162SPeter.Dunlap@Sun.COM */
4669162SPeter.Dunlap@Sun.COM status = iser_iscsihdr_handle(chan, msg);
4679162SPeter.Dunlap@Sun.COM if (status != DDI_SUCCESS) {
4689162SPeter.Dunlap@Sun.COM /*
4699162SPeter.Dunlap@Sun.COM * We are unable to handle this message, and
4709162SPeter.Dunlap@Sun.COM * have no way to recover from this. Fail the
4719162SPeter.Dunlap@Sun.COM * transport.
4729162SPeter.Dunlap@Sun.COM */
4739162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_msg_handle: failed "
4749162SPeter.Dunlap@Sun.COM "iser_iscsihdr_handle");
4759162SPeter.Dunlap@Sun.COM iser_msg_free(msg);
4769162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc,
4779162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, IDM_STATUS_FAIL);
4789162SPeter.Dunlap@Sun.COM }
4799162SPeter.Dunlap@Sun.COM } else if (opcode == ISER_OPCODE_HELLO_MSG) { /* at the target */
4809162SPeter.Dunlap@Sun.COM /*
4819162SPeter.Dunlap@Sun.COM * We are currently not supporting Hello Exchange,
4829162SPeter.Dunlap@Sun.COM * since OFED iSER does not. May be revisited.
4839162SPeter.Dunlap@Sun.COM */
4849162SPeter.Dunlap@Sun.COM ASSERT(opcode != ISER_OPCODE_HELLO_MSG);
4859162SPeter.Dunlap@Sun.COM
4869162SPeter.Dunlap@Sun.COM if (iser_conn->ic_type != ISER_CONN_TYPE_TGT) {
4879162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc,
4889162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, IDM_STATUS_FAIL);
4899162SPeter.Dunlap@Sun.COM }
4909162SPeter.Dunlap@Sun.COM
4919162SPeter.Dunlap@Sun.COM iser_hello_hdr_t *hello_hdr = (iser_hello_hdr_t *)hdr;
4929162SPeter.Dunlap@Sun.COM
4939162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "received Hello message: opcode[%d], "
4949162SPeter.Dunlap@Sun.COM "maxver[%d], minver[%d], iser_ird[%d], msg (0x%p)",
4959162SPeter.Dunlap@Sun.COM hello_hdr->opcode, hello_hdr->maxver, hello_hdr->minver,
4969162SPeter.Dunlap@Sun.COM ntohs(hello_hdr->iser_ird), (void *)msg);
4979162SPeter.Dunlap@Sun.COM
4989162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
4999162SPeter.Dunlap@Sun.COM
5009162SPeter.Dunlap@Sun.COM if (iser_conn->ic_stage != ISER_CONN_STAGE_HELLO_WAIT) {
5019162SPeter.Dunlap@Sun.COM /* target is not expected to receive a Hello */
5029162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc,
5039162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, IDM_STATUS_FAIL);
5049162SPeter.Dunlap@Sun.COM }
5059162SPeter.Dunlap@Sun.COM
5069162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_HELLOREPLY_SENT;
5079162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
5089162SPeter.Dunlap@Sun.COM
5099162SPeter.Dunlap@Sun.COM /* Prepare and send a HelloReply message */
5109162SPeter.Dunlap@Sun.COM status = iser_xfer_helloreply_msg(chan);
5119162SPeter.Dunlap@Sun.COM if (status != ISER_STATUS_SUCCESS) {
5129162SPeter.Dunlap@Sun.COM
5139162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
5149162SPeter.Dunlap@Sun.COM iser_conn->ic_stage =
5159162SPeter.Dunlap@Sun.COM ISER_CONN_STAGE_HELLOREPLY_SENT_FAIL;
5169162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
5179162SPeter.Dunlap@Sun.COM
5189162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc,
5199162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, status);
5209162SPeter.Dunlap@Sun.COM }
5219162SPeter.Dunlap@Sun.COM
5229162SPeter.Dunlap@Sun.COM /* Free this msg handle */
5239162SPeter.Dunlap@Sun.COM iser_msg_free(msg);
5249162SPeter.Dunlap@Sun.COM
5259162SPeter.Dunlap@Sun.COM } else if (opcode == ISER_OPCODE_HELLOREPLY_MSG) { /* at initiator */
5269162SPeter.Dunlap@Sun.COM
5279162SPeter.Dunlap@Sun.COM /*
5289162SPeter.Dunlap@Sun.COM * We are currently not supporting Hello Exchange,
5299162SPeter.Dunlap@Sun.COM * since OFED iSER does not. May be revisited.
5309162SPeter.Dunlap@Sun.COM */
5319162SPeter.Dunlap@Sun.COM ASSERT(opcode != ISER_OPCODE_HELLOREPLY_MSG);
5329162SPeter.Dunlap@Sun.COM
5339162SPeter.Dunlap@Sun.COM if (iser_conn->ic_type != ISER_CONN_TYPE_INI) {
5349162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc,
5359162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, status);
5369162SPeter.Dunlap@Sun.COM }
5379162SPeter.Dunlap@Sun.COM
5389162SPeter.Dunlap@Sun.COM iser_helloreply_hdr_t *hello_hdr = (iser_helloreply_hdr_t *)hdr;
5399162SPeter.Dunlap@Sun.COM
5409162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "received Hello Reply message: opcode[%d], "
5419162SPeter.Dunlap@Sun.COM "maxver[%d], curver[%d], iser_ord[%d], msg (0x%p)",
5429162SPeter.Dunlap@Sun.COM hello_hdr->opcode, hello_hdr->maxver, hello_hdr->curver,
5439162SPeter.Dunlap@Sun.COM ntohs(hello_hdr->iser_ord), (void *)msg);
5449162SPeter.Dunlap@Sun.COM
5459162SPeter.Dunlap@Sun.COM /* Free this msg handle */
5469162SPeter.Dunlap@Sun.COM iser_msg_free(msg);
5479162SPeter.Dunlap@Sun.COM
5489162SPeter.Dunlap@Sun.COM /*
5499162SPeter.Dunlap@Sun.COM * Signal the receipt of HelloReply to the waiting thread
5509162SPeter.Dunlap@Sun.COM * so that the initiator can proceed to the Full Feature
5519162SPeter.Dunlap@Sun.COM * Phase.
5529162SPeter.Dunlap@Sun.COM */
5539162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
5549162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_HELLOREPLY_RCV;
5559162SPeter.Dunlap@Sun.COM cv_signal(&iser_conn->ic_stage_cv);
5569162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
5579162SPeter.Dunlap@Sun.COM } else {
5589162SPeter.Dunlap@Sun.COM /* Protocol error: free the msg handle and fail the session */
5599162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_msg_handle: unsupported opcode (0x%x): "
5609162SPeter.Dunlap@Sun.COM "terminating session on IDM handle (0x%p)", opcode,
5619162SPeter.Dunlap@Sun.COM (void *) iser_conn->ic_idmc);
5629162SPeter.Dunlap@Sun.COM
5639162SPeter.Dunlap@Sun.COM iser_msg_free(msg);
5649162SPeter.Dunlap@Sun.COM idm_conn_event(iser_conn->ic_idmc, CE_TRANSPORT_FAIL,
5659162SPeter.Dunlap@Sun.COM IDM_STATUS_FAIL);
5669162SPeter.Dunlap@Sun.COM }
5679162SPeter.Dunlap@Sun.COM }
5689162SPeter.Dunlap@Sun.COM
5699162SPeter.Dunlap@Sun.COM #define IDM_PDU_OPCODE(PDU) \
5709162SPeter.Dunlap@Sun.COM ((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK)
5719162SPeter.Dunlap@Sun.COM
5729162SPeter.Dunlap@Sun.COM /* network to host translation for 24b integers */
5739162SPeter.Dunlap@Sun.COM static uint32_t
n2h24(uchar_t * ptr)5749162SPeter.Dunlap@Sun.COM n2h24(uchar_t *ptr)
5759162SPeter.Dunlap@Sun.COM {
5769162SPeter.Dunlap@Sun.COM return ((ptr[0] << 16) | (ptr[1] << 8) | ptr[2]);
5779162SPeter.Dunlap@Sun.COM }
5789162SPeter.Dunlap@Sun.COM
5799162SPeter.Dunlap@Sun.COM /* ARGSUSED */
5809162SPeter.Dunlap@Sun.COM static void
iser_rx_pdu_cb(idm_pdu_t * pdu,idm_status_t status)5819162SPeter.Dunlap@Sun.COM iser_rx_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
5829162SPeter.Dunlap@Sun.COM {
5839162SPeter.Dunlap@Sun.COM /* Free the iser msg handle and the PDU handle */
5849162SPeter.Dunlap@Sun.COM iser_msg_free((iser_msg_t *)pdu->isp_transport_private);
5859162SPeter.Dunlap@Sun.COM idm_pdu_free(pdu);
5869162SPeter.Dunlap@Sun.COM }
5879162SPeter.Dunlap@Sun.COM
5889162SPeter.Dunlap@Sun.COM int
iser_iscsihdr_handle(iser_chan_t * chan,iser_msg_t * msg)5899162SPeter.Dunlap@Sun.COM iser_iscsihdr_handle(iser_chan_t *chan, iser_msg_t *msg)
5909162SPeter.Dunlap@Sun.COM {
5919162SPeter.Dunlap@Sun.COM idm_pdu_t *pdu;
5929162SPeter.Dunlap@Sun.COM uint8_t *iser_hdrp;
5939162SPeter.Dunlap@Sun.COM uint8_t *iscsi_hdrp;
5949162SPeter.Dunlap@Sun.COM iscsi_hdr_t *bhs;
5959162SPeter.Dunlap@Sun.COM
5969162SPeter.Dunlap@Sun.COM pdu = idm_pdu_alloc_nosleep(sizeof (iscsi_hdr_t), 0);
5979162SPeter.Dunlap@Sun.COM pdu->isp_ic = chan->ic_conn->ic_idmc;
5989162SPeter.Dunlap@Sun.COM ASSERT(pdu->isp_ic != NULL);
5999162SPeter.Dunlap@Sun.COM
6009162SPeter.Dunlap@Sun.COM /* Set the iser_msg handle into the transport-private field */
6019162SPeter.Dunlap@Sun.COM pdu->isp_transport_private = (void *)msg;
6029162SPeter.Dunlap@Sun.COM
6039162SPeter.Dunlap@Sun.COM /* Set up a pointer in the pdu handle to the iSER header */
6049162SPeter.Dunlap@Sun.COM iser_hdrp = (uint8_t *)(uintptr_t)msg->msg_ds.ds_va;
6059162SPeter.Dunlap@Sun.COM if (iser_hdrp == NULL) {
6069162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_iscsihdr_handle: iser_hdrp is NULL");
6079162SPeter.Dunlap@Sun.COM idm_pdu_free(pdu);
6089162SPeter.Dunlap@Sun.COM return (ISER_STATUS_FAIL);
6099162SPeter.Dunlap@Sun.COM }
6109162SPeter.Dunlap@Sun.COM pdu->isp_transport_hdr = (void *)iser_hdrp;
6119162SPeter.Dunlap@Sun.COM pdu->isp_transport_hdrlen = ISER_HEADER_LENGTH;
6129162SPeter.Dunlap@Sun.COM
6139162SPeter.Dunlap@Sun.COM /*
6149162SPeter.Dunlap@Sun.COM * Set up a pointer to the iSCSI header, which is directly
6159162SPeter.Dunlap@Sun.COM * after the iSER header in the message.
6169162SPeter.Dunlap@Sun.COM */
6179162SPeter.Dunlap@Sun.COM iscsi_hdrp = ((uint8_t *)(uintptr_t)msg->msg_ds.ds_va) +
6189162SPeter.Dunlap@Sun.COM ISER_HEADER_LENGTH;
6199162SPeter.Dunlap@Sun.COM if (iscsi_hdrp == NULL) {
6209162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_iscsihdr_handle: iscsi_hdrp is NULL");
6219162SPeter.Dunlap@Sun.COM idm_pdu_free(pdu);
6229162SPeter.Dunlap@Sun.COM return (ISER_STATUS_FAIL);
6239162SPeter.Dunlap@Sun.COM }
6249162SPeter.Dunlap@Sun.COM pdu->isp_hdr = (iscsi_hdr_t *)(uintptr_t)iscsi_hdrp;
6259162SPeter.Dunlap@Sun.COM
6269162SPeter.Dunlap@Sun.COM /* Fill in the BHS */
6279162SPeter.Dunlap@Sun.COM bhs = pdu->isp_hdr;
6289162SPeter.Dunlap@Sun.COM pdu->isp_hdrlen = sizeof (iscsi_hdr_t) +
6299162SPeter.Dunlap@Sun.COM (bhs->hlength * sizeof (uint32_t));
6309162SPeter.Dunlap@Sun.COM pdu->isp_datalen = n2h24(bhs->dlength);
6319162SPeter.Dunlap@Sun.COM pdu->isp_callback = iser_rx_pdu_cb;
6329162SPeter.Dunlap@Sun.COM
6339162SPeter.Dunlap@Sun.COM /*
6349162SPeter.Dunlap@Sun.COM * If datalen > 0, then non-scsi data may be present. Allocate
6359162SPeter.Dunlap@Sun.COM * space in the PDU handle and set a pointer to the data.
6369162SPeter.Dunlap@Sun.COM */
6379162SPeter.Dunlap@Sun.COM if (pdu->isp_datalen) {
6389162SPeter.Dunlap@Sun.COM pdu->isp_data = ((uint8_t *)(uintptr_t)pdu->isp_hdr) +
6399162SPeter.Dunlap@Sun.COM pdu->isp_hdrlen;
6409162SPeter.Dunlap@Sun.COM }
6419162SPeter.Dunlap@Sun.COM
6429162SPeter.Dunlap@Sun.COM /* Process RX PDU */
6439162SPeter.Dunlap@Sun.COM idm_pdu_rx(pdu->isp_ic, pdu);
6449162SPeter.Dunlap@Sun.COM
6459162SPeter.Dunlap@Sun.COM return (DDI_SUCCESS);
6469162SPeter.Dunlap@Sun.COM }
647