enx_main.c revision b494511a9cf72b1fc4eb13a0e593f55c624ab829
/*
* 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
*/
/*
*/
/*
* The Ethernet Over Infiniband Nexus driver is a bus nexus driver
* that enumerates all the EoIB nodes.
*/
/*
* Global per-instance EoIB Nexus data. Only one instance
* of EoIB Nexus is supported
*/
/*
* Static function declarations
*/
void *, void *);
void (*)(dev_info_t *, ddi_eventcookie_t, void *, void *),
void *, ddi_callback_id_t *);
ddi_eventcookie_t, void *);
void *, dev_info_t **);
void *);
static int eibnx_config_all_children(dev_info_t *);
static void eibnx_unconfig_all_children(dev_info_t *);
static int eibnx_config_child(char *, dev_info_t **);
static int eibnx_unconfig_child(char *);
/*
* Cbops
*/
static struct cb_ops enx_cb_ops = {
eibnx_devctl_open, /* cb_open */
eibnx_devctl_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
eibnx_devctl_ioctl, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
NULL, /* cb_str */
D_MP, /* cb_flag */
CB_REV, /* cb_rev */
nodev, /* cb_aread */
nodev /* cb_awrite */
};
/*
* Busops
*/
static struct bus_ops enx_bus_ops = {
nullbusmap, /* bus_map */
NULL, /* bus_get_intrspec */
NULL, /* bus_add_intrspec */
NULL, /* bus_remove_intrspec */
i_ddi_map_fault, /* bus_map_fault */
ddi_no_dma_map, /* bus_dma_map */
NULL, /* bus_dma_allochdl */
NULL, /* bus_dma_freehdl */
NULL, /* bus_dma_bindhdl */
NULL, /* bus_dma_unbindhdl */
NULL, /* bus_dma_flush */
NULL, /* bus_dma_win */
NULL, /* bus_dma_ctl */
eibnx_bus_ctl, /* bus_ctl */
ddi_bus_prop_op, /* bus_prop_op */
eibnx_get_eventcookie, /* bus_get_eventcookie */
eibnx_add_eventcall, /* bus_add_eventcall */
eibnx_remove_eventcall, /* bus_remove_eventcall */
eibnx_post_event, /* bus_post_event */
NULL, /* bus_intr_ctl */
eibnx_bus_config, /* bus_config */
eibnx_bus_unconfig, /* bus_unconfig */
};
/*
* Nexus ops
*/
DEVO_REV, /* devo_rev, */
0, /* devo_refcnt */
eibnx_getinfo, /* devo_info */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
eibnx_attach, /* devo_attach */
eibnx_detach, /* devo_detach */
nodev, /* devo_reset */
&enx_cb_ops, /* devo_cb_ops */
&enx_bus_ops, /* devo_bus_ops */
nulldev, /* devo_power */
ddi_quiesce_not_needed /* devo_quiesce */
};
/*
* Module linkage information for the kernel
*/
static struct modldrv enx_modldrv = {
&mod_driverops, /* Driver module */
"EoIB Nexus", /* Driver name and version */
&enx_ops, /* Driver ops */
};
static struct modlinkage enx_modlinkage = {
};
/*
* EoIB NDI events
*/
static ndi_event_definition_t enx_ndi_event_defs[] = {
};
#define ENX_NUM_NDI_EVENTS \
(sizeof (enx_ndi_event_defs) / sizeof (enx_ndi_event_defs[0]))
static ndi_event_set_t enx_ndi_events = {
};
/*
* Common loadable module entry points _init, _fini, _info
*/
int
_init(void)
{
int ret;
return (ret);
}
int
_fini(void)
{
int ret;
return (ret);
}
int
{
}
/*
* Autoconfiguration entry points: attach, detach, getinfo
*/
static int
{
int instance;
if (cmd == DDI_RESUME)
return (DDI_SUCCESS);
else if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
/*
* Don't allow more than one instance to attach
*/
if (enx_global_ss)
return (DDI_FAILURE);
/*
* Alloc this instance's softstate
*/
enx_global_ss = ss;
/*
* Allocate our NDI event handle and bind our event set
*/
NDI_SLEEP) != NDI_SUCCESS) {
ENX_DPRINTF_ERR("ndi_event_alloc_hdl(dip=0x%llx) "
"failed", dip);
return (DDI_FAILURE);
}
NDI_SLEEP) != NDI_SUCCESS) {
ENX_DPRINTF_ERR("ndi_event_bind_set(ndi_event_hdl=0x%llx) "
"failed", enx_ndi_event_hdl);
(void) ndi_event_free_hdl(enx_ndi_event_hdl);
return (DDI_FAILURE);
}
/*
* Create "devctl" minor node for general ioctl interface to the
* eoib nexus. If we cannot, it isn't fatal - we'll operate without
* the support for devctl (but issue a warning).
*/
DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
ENX_DPRINTF_WARN("could not create devctl minor node "
"for instance %d", instance);
}
/*
* Do IBTF related initializations. If we fail, we cannot operate,
* so fail the attach.
*/
(void) ndi_event_free_hdl(enx_ndi_event_hdl);
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
{
if (cmd == DDI_SUSPEND)
return (DDI_SUCCESS);
else if (cmd != DDI_DETACH)
return (DDI_FAILURE);
/*
* If there's no instance of eibnx attached, fail
*/
return (DDI_FAILURE);
/*
* Before we do anything, we need to stop the port monitors
* we may have started earlier.
*/
/*
* If eibnx_ibt_fini() fails, it could be because one of the
* HCA's pd could not be freed, the hca could not be closed
* or the IBTF detach wasn't successful. If this is the case,
* we have to return failure, but cannot do much about the
* port monitors we've already terminated.
*/
return (DDI_FAILURE);
/*
* Cleanup any devctl minor node we may have created, unbind and
* free ndi event handle and free the instance softstate.
*/
(void) ndi_event_free_hdl(enx_ndi_event_hdl);
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
{
int ret;
if (cmd == DDI_INFO_DEVT2DEVINFO) {
} else if (cmd == DDI_INFO_DEVT2INSTANCE) {
*resultp = 0;
ret = DDI_SUCCESS;
} else {
ret = DDI_FAILURE;
}
return (ret);
}
/*
* Busops: bus_ctl, bus_config, bus_unconfig
*/
/*ARGSUSED*/
static int
{
int ret;
char name[MAXNAMELEN];
switch (ctlop) {
case DDI_CTLOPS_REPORTDEV:
ENX_DPRINTF_DEBUG("EoIB device: %s@%s, %s%d",
/*FALLTHROUGH*/
case DDI_CTLOPS_ATTACH:
case DDI_CTLOPS_DETACH:
case DDI_CTLOPS_POWER:
case DDI_CTLOPS_SIDDEV:
case DDI_CTLOPS_IOMIN:
ret = DDI_SUCCESS;
break;
case DDI_CTLOPS_INITCHILD:
sizeof (name))) == DDI_SUCCESS) {
}
break;
case DDI_CTLOPS_UNINITCHILD:
ret = DDI_SUCCESS;
break;
default:
break;
}
return (ret);
}
/*ARGSUSED*/
static int
{
int ret = NDI_SUCCESS;
switch (op) {
case BUS_CONFIG_ONE:
break;
case BUS_CONFIG_ALL:
case BUS_CONFIG_DRIVER:
if (ret == NDI_SUCCESS)
}
break;
default:
ret = NDI_FAILURE;
}
if (ret == NDI_SUCCESS)
return (ret);
}
static int
{
int ret;
if (ret != NDI_SUCCESS)
return (ret);
switch (op) {
case BUS_UNCONFIG_ONE:
else {
ENX_DPRINTF_DEBUG("eibnx_bus_config: "
"unconfig child %s failed", (char *)arg);
}
}
break;
case BUS_UNCONFIG_ALL:
case BUS_UNCONFIG_DRIVER:
}
break;
default:
break;
}
return (ret);
}
/*
* Event Handling: bus_get_eventcookie, bus_add_eventcall, bus_remove_eventcall
* and bus_post_event
*/
/*ARGSUSED*/
static int
{
}
/*ARGSUSED*/
static int
void *cb_arg, void *cb_impl_data),
{
}
/*ARGSUSED*/
static int
{
}
/*ARGSUSED*/
static int
{
impl_data));
}
/*
* Routines to configure/unconfigure EoIB node(s) on a system.
*/
/*ARGSUSED*/
static int
{
/*
* Go through each port of each hca and create a thread to solicit,
* monitor, receive advertisements, create eoib nodes and attach eoib
* driver instances.
*/
if (!ss->nx_monitors_up) {
if (ti_tail) {
} else {
}
}
}
return (NDI_SUCCESS);
}
return (NDI_SUCCESS);
}
/*
* Routine to unconfigure all the EoIB nodes on a system. This terminates
* all the per-port monitor threads and releases any resources allocated.
*/
/*ARGSUSED*/
static void
{
}
}
}
/*ARGSUSED*/
static int
{
ENX_DPRINTF_DEBUG("eibnx_config_child: invalid eoib "
"nodename %s, no such address", devname);
return (ENX_E_FAILURE);
}
}
/*ARGSUSED*/
static int
eibnx_unconfig_child(char *devname)
{
ENX_DPRINTF_DEBUG("eibnx_unconfig_child: invalid eoib "
"nodename %s, no such address", devname);
return (ENX_E_FAILURE);
}
}