/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* Solaris SCSI RDMA Protocol Target (SRP) transport port provider
* module for the COMSTAR framework.
*/
#include <sys/sysmacros.h>
#include <sys/stmf_ioctl.h>
#include "srp.h"
#include "srpt_impl.h"
#include "srpt_ioc.h"
#include "srpt_stp.h"
#include "srpt_cm.h"
#include "srpt_ioctl.h"
#include "srpt_common.h"
/*
* srpt_enable_by_default - configurable parameter that
* determines whether targets are created automatically for
* all HCAs when the service is enabled.
*
* B_TRUE is the legacy default as srpt originally shipped
* this way. Changing it to false is highly desirable.
*/
/*
* srpt_send_msg_depth - Tunable parameter that specifies the
* maximum messages that could be in flight for a channel.
*/
/*
* srpt_errlevel -- determine which error conditions are logged
*/
/*
* srpt_iu_size -- must be a multiple of 64 as it is registered
* size of 32, the size must be at not less than 960. To support
* be at least 4160 bytes.
*/
/*
* DDI entry points.
*/
/* helper functions */
static int srpt_disable_srp_services(void);
static int srpt_enable_srp_services(void);
static int srpt_ibdma_ops_load(srpt_ibdma_ops_t *);
static void srpt_ibdma_ops_unload(srpt_ibdma_ops_t *);
extern struct mod_ops mod_miscops;
srpt_drv_open, /* cb_open */
srpt_drv_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
srpt_drv_ioctl, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
NULL, /* cb_streamtab */
D_MP, /* cb_flag */
CB_REV, /* cb_rev */
nodev, /* cb_aread */
nodev, /* cb_awrite */
};
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
srpt_drv_getinfo, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
srpt_drv_attach, /* devo_attach */
srpt_drv_detach, /* devo_detach */
nodev, /* devo_reset */
&srpt_cb_ops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
ddi_quiesce_not_needed, /* quiesce */
};
};
&modldrv,
NULL,
};
/*
* Prototypes
*/
/*
* _init()
*/
int
_init(void)
{
int status;
/*
* Global one time initialization.
*/
/* Start-up state is DISABLED. SMF will tell us if we should enable. */
if (status != DDI_SUCCESS) {
}
return (status);
}
/*
* _info()
*/
int
{
}
/*
* _fini()
*/
int
_fini(void)
{
int status;
if (status != DDI_SUCCESS) {
return (status);
}
return (status);
}
/*
* DDI entry points.
*/
/*
* srpt_getinfo()
*/
/* ARGSUSED */
static int
{
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
return (DDI_SUCCESS);
case DDI_INFO_DEVT2INSTANCE:
return (DDI_SUCCESS);
default:
break;
}
return (DDI_FAILURE);
}
/*
* srpt_drv_attach()
*/
static int
{
int status;
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
/*
* We only allow a single instance.
*/
if (ddi_get_instance(dip) != 0) {
SRPT_DPRINTF_L1("drv_attach, error non-zero instance");
return (DDI_FAILURE);
}
/*
* Create minor node that might ultimately be used to create
* targets outside of srpt.
*/
S_IFCHR, 0, DDI_PSEUDO, 0);
if (status != DDI_SUCCESS) {
SRPT_DPRINTF_L1("drv_attach, minor node creation error (%d)",
status);
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* srpt_enable_srp_services()
*
* Caller must be holding the sc_rwlock as RW_WRITER.
*/
static int
srpt_enable_srp_services(void)
{
int status;
SRPT_DPRINTF_L3("srpt_enable_srp_services");
/* Register the port provider */
stmf_alloc(STMF_STRUCT_PORT_PROVIDER, 0, 0);
if (status != STMF_SUCCESS) {
SRPT_DPRINTF_L1("enable_srp: SRP port_provider registration"
" failed(%d)", status);
goto err_exit_1;
}
/*
* Initialize IB resources, creating a list of SRP I/O Controllers
* and for each controller, register the SCSI Target Port with STMF
* and prepare profile and services.
*/
status = srpt_ioc_attach();
if (status != DDI_SUCCESS) {
SRPT_DPRINTF_L1("enable_srp: error attach I/O"
" Controllers (%d)", status);
goto err_exit_2;
}
/*
* No configured controllers is not a fatal error. This can happen
* if all HCAs are currently disabled for use by SRP. The service
* should remain running in case the user changes their mind and
* enables an HCA for SRP services.
*/
if (srpt_ctxt->sc_num_iocs == 0) {
SRPT_DPRINTF_L2("enable_srp: no IB I/O Controllers found");
return (DDI_SUCCESS);
}
return (DDI_SUCCESS);
return (status);
}
/*
* srpt_drv_detach()
*
* Refuse the detach request if we have channels open on
* any IOC. Users should use 'svcadm disable' to shutdown
* active targets.
*/
/*ARGSUSED*/
static int
{
switch (cmd) {
case DDI_DETACH:
return (DDI_FAILURE);
}
}
break;
case DDI_SUSPEND:
return (DDI_FAILURE);
default:
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* srpt_disable_srp_services()
*
* Offlines all targets, deregisters all IOCs. Caller must hold
* the srpt_ctxt->sc_rwlock as RW_WRITER.
*/
static int
{
int ret_status = 0;
/*
* For each I/O Controller remove all SRP services and de-register
* with the associated I/O Unit's IB Device Management Agent.
*/
if (stmf_status == STMF_SUCCESS) {
(void) srpt_stp_free_port(tgt);
} else {
break;
}
}
}
/* don't release IOCs until all ports are deregistered */
if (ret_status != 0) {
return (ret_status);
}
/*
* Release I/O Controller(s) resources and detach.
*/
/* De-register ourselves as an STMF port provider */
return (0);
}
/*
* srpt_drv_open()
*/
/* ARGSUSED */
static int
{
SRPT_DPRINTF_L3("drv_open, invoked");
return (0);
}
/*
* srpt_drv_close()
*/
/* ARGSUSED */
static int
{
SRPT_DPRINTF_L3("drv_close, invoked");
return (0);
}
/*
* srpt_drv_ioctl()
*/
/* ARGSUSED */
static int
int *retval)
{
int ret = 0;
return (EPERM);
}
switch (cmd) {
case SRPT_IOC_ENABLE_SVC:
break;
}
if (ret != 0) {
break;
}
if (ret == 0) {
}
break;
case SRPT_IOC_DISABLE_SVC:
break;
}
if (ret == 0) {
}
break;
default:
break;
}
return (ret);
}
/*
* srpt_pp_cb()
*/
/* ARGSUSED */
static void
{
int ret;
if (cmd != STMF_PROVIDER_DATA_UPDATED) {
return;
}
/*
* If STMF_PCB_PREG_COMPLETE is set in the flags, we're being
* called back during provider registration with STMF.
* (while we're calling stmf_register_port_provider()).
* srpt_enable_service() already holds the sc_wrlock, and will
* make sure the configuration is activated, so we just need to
* set the config and get out. If this function is called at any
* time other than SRPT service start, need to grab the sc_wrlock
* as WRITER.
*/
if (!(flags & STMF_PCB_PREG_COMPLETE)) {
"srpt_pp_cb: called after registration");
} else {
"srpt_pp_cb: called as part of registration");
}
/* copy nvlist */
if (ret != 0) {
"srpt_pp_cb: Could not read hca config, err=%d",
ret);
return;
}
if (ret != 0) {
"srpt_pp_cb: Could not copy hca config, err=%d",
ret);
return;
}
SRPT_PROP_DEFAULT_ENABLED, &defaultEnabled) == 0) {
/* set whether targets are created by default */
"srpt_pp_cb: setting default enabled = %d\n",
(int)defaultEnabled);
}
} else {
"srpt_pp_cb: null config received");
}
/* put list in ctxt and set default state */
/* set new config, NULL is valid */
/* free the old nvlist */
}
if (called_by_reg) {
return;
}
/* Update the HCA based on the new config */
}
static int
{
int ibdma_err = 0;
SRPT_DPRINTF_L0("failed to open ibdma driver, error = %d",
return (ibdma_err);
}
"ibdma_ioc_register", &ibdma_err);
"failed to modsym ibdma_ioc_register, error = %d",
goto done;
}
"ibdma_ioc_unregister", &ibdma_err);
"failed to modsym ibdma_ioc_unregister, error = %d",
goto done;
}
"ibdma_ioc_update", &ibdma_err);
"failed to modsym ibdma_ioc_update, error = %d",
}
done:
if (ibdma_err != 0) {
}
return (ibdma_err);
}
static void
{
}
}
}