1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * CDDL HEADER START
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The contents of this file are subject to the terms of the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Common Development and Distribution License (the "License").
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * You may not use this file except in compliance with the License.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * See the License for the specific language governing permissions
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and limitations under the License.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * When distributing Covered Code, include this CDDL HEADER in each
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If applicable, add the following below this CDDL HEADER, with the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * fields enclosed by brackets "[]" replaced with your own identifying
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * information: Portions Copyright [yyyy] [name of copyright owner]
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * CDDL HEADER END
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * SCSI Target Port I/F for Solaris SCSI RDMA Protocol Target (SRP)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * port provider module for the COMSTAR framework.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * STMF LPort Interface Prototypes
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic stmf_status_t srpt_stp_xfer_data(struct scsi_task *task,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstmf_status_t srpt_stp_send_status(struct scsi_task *task,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_stp_task_free(struct scsi_task *task);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic stmf_status_t srpt_stp_abort(struct stmf_local_port *lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_stp_task_poll(struct scsi_task *task);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_stp_ctl(struct stmf_local_port *lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson struct stmf_local_port *lport, void *arg, uint8_t *buf,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_stp_event_handler(struct stmf_local_port *lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_format_login_rsp(srp_login_req_t *req,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_format_login_rej(srp_login_req_t *req,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic scsi_devid_desc_t *srpt_stp_alloc_scsi_devid_desc(uint64_t guid);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_stp_free_scsi_devid_desc(scsi_devid_desc_t *sdd);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_start_srp() - Start SRP service
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Enable the SRP service for the specified SCSI Target Port.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_start_srp, NULL SCSI target port");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_start_srp, SCSI target port NULL"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " IOC pointer");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_start_srp, register SRP service for"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " svc_id (%016llx)", (u_longlong_t)tgt->tp_ibt_svc_id);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_register_service(srpt_ctxt->sc_ibt_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_start_srp, SRP service creation err (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Bind the service associated with the SCSI target port to
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * each active port of the I/O Controller.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (port = 0; port < ioc->ioc_attr.hca_nports; port++) {
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson /* don't online if we have no active ports */
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson SRPT_DPRINTF_L2("start_srp, no ports active for svc_id %016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Calculate the new I/O Controller profile and either update the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * profile if previously registered or register it with the IB
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Device Management Agent.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("start_srp, update I/O Controller profile (%016llx)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ctxt->sc_ibdma_ops.ibdma_register(ioc->ioc_guid,
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson " I/O Profile for svc_id %016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ctxt->sc_ibdma_ops.ibdma_update(ioc->ioc_ibdma_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("start_srp, Unable to update I/O"
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson " Profile for svc_id %016llxi (%d)",
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_deregister_service(srpt_ctxt->sc_ibt_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_stop_srp() - Stop SRP service.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Disable the SRP service on the specified SCSI Target Port.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_stop_srp, NULL SCSI Target Port"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " specified");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_stop_srp, bad Target, IOC NULL");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Update the I/O Controller profile to remove the SRP service
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * for this SCSI target port.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_stop_srp, update I/O Controller"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " profile (%016llx)", (u_longlong_t)ioc->ioc_guid);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ioc->ioc_profile.ioc_service_entries == 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_stop_srp, no services active"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " unregister IOC profile");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson dma_status = srpt_ctxt->sc_ibdma_ops.ibdma_update(
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Unbind the SRP service associated with the SCSI target port
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * from all of the I/O Controller physical ports.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_stop_srp, unbind and de-register service"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_deregister_service(srpt_ctxt->sc_ibt_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_stop_srp, de-register service"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * SRP service is now off-line for this SCSI Target Port.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We force a disconnect (i.e. SRP Target Logout) for any
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * active SRP logins.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_stop_srp, disconnect ch(%p)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * wait for all sessions to terminate before returning
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_wait(&tgt->tp_sess_complete, &tgt->tp_sess_list_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_alloc_port() - Allocate SCSI Target Port
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_alloc_port(srpt_ioc_t *ioc, ib_guid_t guid)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_alloc_port, NULL I/O Controller");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_alloc_port, allocate STMF local port");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson lport = stmf_alloc(STMF_STRUCT_STMF_LOCAL_PORT, sizeof (*tgt), 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("tgt_alloc_port, stmf_alloc failed");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_init(&tgt->tp_lock, NULL, MUTEX_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_init(&tgt->tp_ch_list_lock, NULL, MUTEX_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_init(&tgt->tp_offline_complete, NULL, CV_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson list_create(&tgt->tp_ch_list, sizeof (srpt_channel_t),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_init(&tgt->tp_sess_list_lock, NULL, MUTEX_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_init(&tgt->tp_sess_complete, NULL, CV_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson list_create(&tgt->tp_sess_list, sizeof (srpt_session_t),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tgt->tp_ibt_svc_desc.sd_flags = IBT_SRV_NO_FLAGS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson kmem_zalloc(sizeof (srpt_hw_port_t) * tgt->tp_nports, KM_SLEEP);
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson tgt->tp_requested_state = SRPT_TGT_STATE_OFFLINE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tgt->tp_scsi_devid = srpt_stp_alloc_scsi_devid_desc(tgt->tp_ibt_svc_id);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson lport->lport_send_status = &srpt_stp_send_status;
2d361592ba6a66373470f9586a66dac706951772Sue Gleeson lport->lport_abort_timeout = 300; /* 5 minutes */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson lport->lport_event_handler = &srpt_stp_event_handler;
cd36db67f9470c74ed7f5bbd57ec6eeb84f71fcdJohn Forte /* set up as alua participating port */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_alloc_port, register STMF LPORT");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_alloc_port, LPORT successfully"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " registered");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * This is only done on an administrative thread of
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * execution so it is ok to take a while.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_alloc_port, STMF register local port err(0x%llx)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_alloc_port, free STMF local port");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_free_scsi_devid_desc(tgt->tp_scsi_devid);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_free_port() - Free SCSI Target Port
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_free_port, free STMF local port");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_free_scsi_devid_desc(tgt->tp_scsi_devid);
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson * srpt_stp_destroy_port()
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson SRPT_DPRINTF_L3("stp_destroy_port, de-register STMF LPORT");
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson /* already being destroyed, get out now - should not happen */
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson SRPT_DPRINTF_L2("stp_destroy_port: unbind and de-register"
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson " services for GUID(%016llx)", (u_longlong_t)guid);
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson status = stmf_ctl(STMF_CMD_LPORT_OFFLINE, tgt->tp_lport, &cstatus);
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson * Wait for asynchronous target off-line operation
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson * to complete and then deregister the target
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson while (tgt->tp_state != SRPT_TGT_STATE_OFFLINE) {
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson cv_wait(&tgt->tp_offline_complete, &tgt->tp_lock);
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson SRPT_DPRINTF_L3("stp_destroy_port: IOC (0x%016llx) Target"
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson /* loop waiting for all I/O to drain */
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson status = stmf_deregister_local_port(tgt->tp_lport);
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson SRPT_DPRINTF_L3("stp_destroy_port, LPORT de-register"
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson " complete");
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson * Something other than a BUSY error, this should not happen.
c3a558e7c77127215b010652905be7916ec5a080Sue Gleeson "stp_destroy_port, de-register STMF error(0x%llx)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_xfer_data()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/* ARGSUSED */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_xfer_data(struct scsi_task *task, struct stmf_data_buf *dbuf,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_xfer_data, invoked task (%p), dbuf (%p)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We should use iu->iu_ch->ch_swqe_posted to throttle
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * send wqe posting. This is very unlikely because we limit
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the maximum number of initiator descriptors per IU (impact
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * of fragmentation of intiator buffer space) but it could occur
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * if the back-end (STMF) were to use too many small buffers. In
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * that case we would want to return STMF_BUSY.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("stp_xfer_data, dbuf->db_flags (0x%x)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("stp_xfer_data, dbuf->db_data_size (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("stp_xfer_data, dbuf->db_relative_offset (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT((dbuf->db_flags & (DB_DIRECTION_TO_RPORT |
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson DB_DIRECTION_FROM_RPORT)) != (DB_DIRECTION_TO_RPORT |
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Check to see if request will overflow the remote buffer; if so
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * return a bad status and let STMF abort the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if ((dbuf->db_relative_offset + dbuf->db_data_size) >
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_xfer_data, overflow of remote buffer");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_opcode = (dbuf->db_flags & DB_DIRECTION_TO_RPORT) ?
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We know that the data transfer is within the bounds described
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * by our list of remote buffer descriptors. Find the starting
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * point based on the offset for the transfer, then perform the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * RDMA operations required of this transfer.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while ((base_offset + desc->dd_len) < dbuf->db_relative_offset) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson desc_offset = dbuf->db_relative_offset - base_offset;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If the channel is no longer connected then return an
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * error and do not initiate I/O. STMF should abort the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (iu->iu_ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while (xfer_len > 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We only generate completion entries on the last IB
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * operation associated with any STMF buffer.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr.rc.rcwr.rdma.rdma_raddr = desc->dd_vaddr + desc_offset;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("stp_xfer_data, post RDMA operation");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If this task is being aborted or has been aborted,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * do not post additional I/O.
191c289b86668766245f78ec1f87557319bc46a1Charles Ting uint32_t, wr.wr_opcode == IBT_WRC_RDMAR ? 0 : 1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_IU_STMF_ABORTING | SRPT_IU_ABORTED)) != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If a non-error CQE will be requested, add a reference to
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the IU and initialize the work request appropriately.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_post_send(iu->iu_ch->ch_chan_hdl, &wr, 1, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Could not post to IB transport, report to STMF and
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and let it initiate an abort of the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_send_mgmt_response() - Return SRP task managment response IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_send_mgmt_response(srpt_iu_t *iu, uint8_t srp_rsp,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson bzero(rsp, SRP_RSP_SIZE + sizeof (srp_rsp_data_t));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Report ULP credits we have added since last response sent
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * over this channel.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson h2b32(atomic_swap_32(&iu->iu_ch->ch_req_lim_delta, 0));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* srp_rsp_t is padded out, so use explicit size here */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rsp->rsp_data_len = h2b32(sizeof (srp_rsp_data_t));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("stp_send_mgmt_response, sending on ch(%p),"
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_4(task__response, srpt_channel_t, iu->iu_ch,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting srp_rsp_t, iu->iu_buf, scsi_task_t, iu->iu_stmf_task,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_ch_post_send(iu->iu_ch, iu, rsp_length, fence);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_send_response() - Send SRP command response IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_send_response(srpt_iu_t *iu, uint8_t scsi_status,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint8_t flags, uint32_t resid, uint16_t sense_length,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Report ULP credits we have added since last response sent
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * over this channel.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson h2b32(atomic_swap_32(&iu->iu_ch->ch_req_lim_delta, 0));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("stp_send_reponse, sending on ch(%p),"
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_4(task__response, srpt_channel_t, iu->iu_ch,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting srp_rsp_t, iu->iu_buf, scsi_task_t, iu->iu_stmf_task,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_ch_post_send(iu->iu_ch, iu, rsp_length, fence);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_send_response, post response err(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_send_status()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/* ARGSUSED */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_send_status(struct scsi_task *task, uint32_t ioflags)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_send_status, invoked task (%p)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ", task_completion_status (%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ", task_resid (%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ", task_status_ctrl (%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ", task_scsi_status (%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ", task_sense_length (%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ", task_sense_data (%p)",
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_4(scsi__response, srpt_channel_t, iu->iu_ch,
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson SRPT_IU_SRP_ABORTING | SRPT_IU_ABORTED)) != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Indicate future aborts can not be initiated (although
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * we will handle any that have been requested since the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * last I/O completed and before we are sending status).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Send SRP command response or SRP task mgmt response.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (task->task_status_ctrl == TASK_SCTRL_OVER) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "stp_send_status, data out overrun");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "stp_send_status, data in overrun");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "stp_send_status, data out underrun");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "stp_send_status, data in underrun");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson task->task_sense_length, task->task_sense_data, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If we have an error posting the response return bad status
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * to STMF and let it initiate an abort for the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_send_status, post response err(%d)",
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson /* clear the response sent flag since it never went out */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_task_free() - STMF call-back.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_task_free, invoked task (%p)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Do not hold IU lock while task is being removed from
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the session list - possible deadlock if cleaning up
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * channel when this is called.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_abort() - STMF call-back.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/* ARGSUSED */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_abort(struct stmf_local_port *lport, int abort_cmd,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_abort, invoked lport (%p), arg (%p)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If no I/O is outstanding then immediately transition to
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson * aborted state. If any I/O is in progress OR we've sent the
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson * completion response, then indicate that an STMF abort has been
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson * requested and ask STMF to call us back later to complete the abort.
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson SRPT_DPRINTF_L3("stp_abort, deferring abort request. "
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson "%d outstanding I/O for IU %p",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_abort, no outstanding I/O for %p",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* Synchronous abort - STMF will call task_free */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_task_poll() - STMF call-back
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_task_poll, invoked, task (%p)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_ctl() - STMF call-back
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_ctl(struct stmf_local_port *lport, int cmd, void *arg)
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, invoked for LPORT (0x%016llx), cmd (%d), "
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson "info (%s)", (u_longlong_t)tgt->tp_ibt_svc_id, cmd, why);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, LPORT_ONLINE command,"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " st_rflags(0x%llx)", (u_longlong_t)sc_info->st_rflags);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If the SCSI Target Port is not enabled by the driver,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * don't start and instead return busy. This is a
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * creation/destruction transitional state and the will
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * either go away or become enabled.
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson tgt->tp_requested_state = SRPT_TGT_STATE_ONLINE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_ctl, set LPORT_ONLINE failed - "
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "LPORT (0x%016llx) BUSY",
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson } else if ((tgt->tp_state == SRPT_TGT_STATE_ONLINE) ||
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else if (tgt->tp_state != SRPT_TGT_STATE_OFFLINE) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cstatus.st_completion_status = STMF_INVALID_ARG;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cstatus.st_completion_status = STMF_INVALID_ARG;
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson "stp_ctl, no ports active "
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson "for HCA 0x%016llx. Target will "
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson "not be placed online.",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_ctl, (0x%016llx) LPORT_ONLINE command"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " status (0x%llx)", (u_longlong_t)tgt->tp_ibt_svc_id,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_ctl, ONLINE_COMPLETE returned"
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, LPORT_OFFLINE command,"
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson " st_rflags(0x%llx)", (u_longlong_t)sc_info->st_rflags);
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson * Only keep persistent state if explicitly requested by user
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson * action, such as stmfadm offline-target or
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson * svcadm disable stmf.
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson * If not requested by the user, this was likely triggered by
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson * not having any HCA ports active.
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson if (sc_info->st_rflags & STMF_RFLAG_USER_REQUEST) {
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson tgt->tp_requested_state = SRPT_TGT_STATE_OFFLINE;
3baa0db47b1b400bbbd8b7ae9ccb32bfdd1ad865Sue Gleeson if ((tgt->tp_state == SRPT_TGT_STATE_OFFLINE) ||
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else if (tgt->tp_state != SRPT_TGT_STATE_ONLINE) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cstatus.st_completion_status = STMF_INVALID_ARG;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("stp_ctl, notify STMF OFFLINE complete"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " (0x%016llx)", (u_longlong_t)tgt->tp_ibt_svc_id);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_ctl, OFFLINE_COMPLETE returned"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, LPORT_ONLINE_COMPLETE ACK from"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, LPORT not on-lining");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, LPORT_OFFLINE_COMPLETE ACK from"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (tgt->tp_state == SRPT_TGT_STATE_OFFLINING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, LPORT not off-lining");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_ctl, cmd (%d) not handled",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_info() - STMF call-back
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/* ARGSUSED */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_info(uint32_t cmd, struct stmf_local_port *lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_event_handler() - STMF call-back
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/* ARGSUSED */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_event_handler(struct stmf_local_port *lport, int eventid,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_alloc_scsi_devid_desc()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Allocate and initialize a SCSI device ID descriptor for
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the SRP protocol. Names are eui.GUID format.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Both extension and guid are passed in host order.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson sdd = kmem_zalloc(sizeof (*sdd) + SRPT_EUI_ID_LEN + 1, KM_SLEEP);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void) sprintf((char *)sdd->ident, "eui.%016llX", (u_longlong_t)guid);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_free_scsi_devid_desc()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Free a SRPT SCSI device ID descriptor previously allocated via
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_alloc_scsi_devid_desc().
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_free_scsi_devid_desc(scsi_devid_desc_t *sdd)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson kmem_free(sdd, sizeof (*sdd) + SRPT_EUI_ID_LEN + 1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_alloc_session()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " returned NULL");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson list_create(&ss->ss_task_list, sizeof (srpt_iu_t),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_ss->ss_rport_id = srpt_stp_alloc_scsi_devid_desc(i_guid);
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan /* Setup remote port transport id */
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan stmf_ss->ss_rport = stmf_remote_port_alloc(
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan stmf_ss->ss_rport->rport_tptid->protocol_id = PROTOCOL_SRP;
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan stmf_ss->ss_rport->rport_tptid->format_code = 0;
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan srptpd = (scsi_srp_transport_id_t *)stmf_ss->ss_rport->rport_tptid;
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan bcopy(i_id, srptpd->srp_name, SRP_PORT_ID_LEN);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Set the alias to include the initiator extension, this will enable
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the administrator to identify multiple unique sessions originating
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * from the same initiator.
191c289b86668766245f78ec1f87557319bc46a1Charles Ting (void) strlcpy(ss->ss_i_gid, remote_gid, SRPT_ALIAS_LEN);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting (void) strlcpy(ss->ss_t_gid, local_gid, SRPT_ALIAS_LEN);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting EUI_STR(ss->ss_i_name, BE_IN64(&ss->ss_i_id[8]));
191c289b86668766245f78ec1f87557319bc46a1Charles Ting EUI_STR(ss->ss_t_name, BE_IN64(&ss->ss_t_id[0]));
191c289b86668766245f78ec1f87557319bc46a1Charles Ting ALIAS_STR(ss->ss_i_alias, BE_IN64(&ss->ss_i_id[0]),
191c289b86668766245f78ec1f87557319bc46a1Charles Ting ALIAS_STR(ss->ss_t_alias, BE_IN64(&ss->ss_t_id[0]),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = stmf_register_scsi_session(tgt->tp_lport, stmf_ss);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_alloc_session, STMF register session"
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan srpt_stp_free_scsi_devid_desc(stmf_ss->ss_rport_id);
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan stmf_remote_port_free(stmf_ss->ss_rport);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_free_session()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_deregister_scsi_session(tgt->tp_lport, stmf_ss);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_free_scsi_devid_desc(stmf_ss->ss_rport_id);
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan stmf_remote_port_free(stmf_ss->ss_rport);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_login() - SRP SCSI Target port login
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_login(srpt_target_port_t *tgt, srp_login_req_t *login,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srp_login_rsp_t *login_rsp, srp_login_rej_t *login_rej,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting uint8_t login_port, char *local_gid, char *remote_gid)
191c289b86668766245f78ec1f87557319bc46a1Charles Ting /* Store the string representation of connection info */
191c289b86668766245f78ec1f87557319bc46a1Charles Ting /* for Dtrace probes */
191c289b86668766245f78ec1f87557319bc46a1Charles Ting (void) strlcpy(sess.ss_i_gid, remote_gid, SRPT_ALIAS_LEN);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting (void) strlcpy(sess.ss_t_gid, local_gid, SRPT_ALIAS_LEN);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_2(login__command, srpt_session_t, &sess,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The target lock taken here serializes logins to this target
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and prevents an STMF target port from starting a control
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * operation to transition the target state while a login is
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * being processed.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("stp_login, NULL I/O Controller");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson reason = SRP_LOGIN_REJ_UNABLE_TO_ASSOCIATE_I_T_NEXUS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Validate that the SRP Target ID in the login request specifies
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * this I/O Controller SCSI Target Port.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (memcmp(login->lreq_target_port_id, tgt->tp_srp_port_id,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, SRP CM SVC target ID mismatch."
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " Incoming TgtID 0x%016llx:0x%016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)BE_IN64(&login->lreq_target_port_id[0]),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)BE_IN64(&login->lreq_target_port_id[8]));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson reason = SRP_LOGIN_REJ_UNABLE_TO_ASSOCIATE_I_T_NEXUS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, SRP Login target not on-line");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson reason = SRP_LOGIN_REJ_UNABLE_TO_ASSOCIATE_I_T_NEXUS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Initiator requested IU size must be as large as the specification
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * minimum and no greater than what we chose to support.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson req_it_ui_len = b2h32(login->lreq_req_it_iu_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, requested iu size = %d", req_it_ui_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, SRP Login IU size (%d) too large",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson reason = SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, SRP Login IU size (%d) too small",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, login req InitID 0x%016llx:0x%016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)BE_IN64(&login->lreq_initiator_port_id[0]),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)BE_IN64(&login->lreq_initiator_port_id[8]));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, login req TgtID 0x%016llx:0x%016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)BE_IN64(&login->lreq_target_port_id[0]),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)BE_IN64(&login->lreq_target_port_id[8]));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Processing is based on either single channel or multi-channel
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * operation. In single channel, all current logins for this
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * same I_T_Nexus should be logged out. In multi-channel
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * mode we would add an additional channel to an existing
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * I_T_Nexus if one currently exists (i.e. reference the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * same SCSI session).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson switch (login->lreq_req_flags & SRP_LOGIN_MULTI_CH_MASK) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Only a single channel may be associated with a I_T_Nexus.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Disconnect any channel with the same SRP Initiator and
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * SRP target IDs.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " channel not active");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " I_ID 0x%016llx:0x%016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " T_ID 0x%016llx:0x%016llx",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * if a session is in the process of connecting,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * reject subsequent equivalent requests.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " existing login");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* Create the new session for this SRP login */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson reason = SRP_LOGIN_REJ_UNABLE_TO_ASSOCIATE_I_T_NEXUS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, multichannel not supported yet");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* break via goto */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, invalid multichannel field (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson login->lreq_req_flags & SRP_LOGIN_MULTI_CH_MASK);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* break via goto */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Create new RDMA channel for this SRP login request.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The channel is returned with a single reference which
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * represents the reference held by the CM.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("stp_login, unable to alloc RDMA channel");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson reason = SRP_LOGIN_REJ_INSUFFICIENT_CH_RESOURCES;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_ti_iu_len = b2h32(login->lreq_req_it_iu_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Add another reference to the channel which represents
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * a reference placed by the target port and add it to
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the store of channels logged in for this target port.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_format_login_rsp(login, login_rsp, rsp_flags);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_3(login__response, srpt_session_t, &sess,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting srp_login_rsp_t, login_rsp, srp_login_rej_t, login_rej)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_format_login_rej(login, login_rej, reason);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_3(login__response, srpt_session_t, &sess,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting srp_login_rsp_t, login_rsp, srp_login_rej_t, login_rej);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_logout() - SRP logout
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Logout is not normally initiated in-band, but is so, just
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * initiate a disconnect.
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_1(logout__command, srpt_channel_t, ch);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting SRPT_DPRINTF_L2("stp_logout, invoked for ch (%p)", (void *)ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_format_login_rej() - Format login reject IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_format_login_rej(srp_login_req_t *req, srp_login_rej_t *rej,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson h2b16(SRP_DIRECT_BUFR_DESC | SRP_INDIRECT_BUFR_DESC);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_format_login_rsp() - Format login response IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_format_login_rsp(srp_login_req_t *req, srp_login_rsp_t *rsp,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rsp->lrsp_req_limit_delta = h2b32((uint32_t)srpt_send_msg_depth);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rsp->lrsp_max_it_iu_len = req->lreq_req_it_iu_len;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* by def. > min T_IU_LEN */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rsp->lrsp_max_ti_iu_len = req->lreq_req_it_iu_len;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson h2b16(SRP_DIRECT_BUFR_DESC | SRP_INDIRECT_BUFR_DESC);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_add_task()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_stp_add_task(srpt_session_t *session, srpt_iu_t *iu)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_stp_remove_task()