1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER START
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The contents of this file are subject to the terms of the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Common Development and Distribution License (the "License").
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You may not use this file except in compliance with the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * or http://www.opensolaris.org/os/licensing.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * See the License for the specific language governing permissions
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and limitations under the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * When distributing Covered Code, include this CDDL HEADER in each
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If applicable, add the following below this CDDL HEADER, with the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fields enclosed by brackets "[]" replaced with your own identifying
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * information: Portions Copyright [yyyy] [name of copyright owner]
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER END
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Use is subject to license terms.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/types.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/file.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/errno.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/uio.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/open.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/cred.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/kmem.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/conf.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/cmn_err.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ksynch.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/modctl.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/stat.h> /* needed for S_IFBLK and S_IFCHR */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/debug.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/sysmacros.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/types.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/cred.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/promif.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ddi.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/sunddi.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/cyclic.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/note.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mach_descrip.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mdeg.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ldc.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/vldc_impl.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Function prototypes.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* DDI entrypoints */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_open(dev_t *devp, int flag, int otyp, cred_t *cred);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_close(dev_t dev, int flag, int otyp, cred_t *cred);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cred_t *credp, int *rvalp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_read(dev_t dev, struct uio *uiop, cred_t *credp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_write(dev_t dev, struct uio *uiop, cred_t *credp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vldc_chpoll(dev_t dev, short events, int anyyet,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo short *reventsp, struct pollhead **phpp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Internal functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint_t i_vldc_cb(uint64_t event, caddr_t arg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int i_vldc_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int i_vldc_mdeg_register(vldc_t *vldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int i_vldc_mdeg_unregister(vldc_t *vldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int i_vldc_add_port(vldc_t *vldcp, md_t *mdp, mde_cookie_t node);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int i_vldc_remove_port(vldc_t *vldcp, uint_t portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int i_vldc_close_port(vldc_t *vldcp, uint_t portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* soft state structure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void *vldc_ssp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Matching criteria passed to the MDEG to register interest
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in changes to 'virtual-device-port' nodes identified by their
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * 'id' property.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic md_prop_match_t vport_prop_match[] = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_PROP_VAL, "id" },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_LIST_END, NULL }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mdeg_node_match_t vport_match = { "virtual-device-port",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport_prop_match };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Specification of an MD node passed to the MDEG to filter any
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * 'virtual-device-port' nodes that do not belong to the specified
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * node. This template is copied for each vldc instance and filled
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in with the appropriate 'name' and 'cfg-handle' values before
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * being passed to the MDEG.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mdeg_prop_spec_t vldc_prop_template[] = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_PROP_STR, "name", NULL },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_PROP_VAL, "cfg-handle", NULL },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_LIST_END, NULL, NULL }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define VLDC_MDEG_PROP_NAME(specp) ((specp)[0].ps_str)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define VLDC_SET_MDEG_PROP_NAME(specp, name) ((specp)[0].ps_str = (name))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define VLDC_SET_MDEG_PROP_INST(specp, inst) ((specp)[1].ps_val = (inst))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic struct cb_ops vldc_cb_ops = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_open, /* open */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_close, /* close */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nodev, /* strategy */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nodev, /* print */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nodev, /* dump */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_read, /* read */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_write, /* write */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_ioctl, /* ioctl */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nodev, /* devmap */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nodev, /* mmap */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_segmap, /* segmap */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_chpoll, /* chpoll */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_prop_op, /* prop_op */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo NULL, /* stream */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D_NEW | D_MP /* flag */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic struct dev_ops vldc_ops = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DEVO_REV, /* rev */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 0, /* ref count */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_getinfo_1to1, /* getinfo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nulldev, /* identify */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nulldev, /* probe */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_attach, /* attach */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_detach, /* detach */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nodev, /* reset */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &vldc_cb_ops, /* cb_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct bus_ops *)NULL, /* bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoextern struct mod_ops mod_driverops;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic struct modldrv md = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &mod_driverops, /* Type - it is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "sun4v Virtual LDC Driver", /* Name of the module */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &vldc_ops, /* driver specific ops */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic struct modlinkage ml = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo MODREV_1,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &md,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo NULL
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* maximum MTU and cookie size tunables */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint32_t vldc_max_mtu = VLDC_MAX_MTU;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint64_t vldc_max_cookie = VLDC_MAX_COOKIE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm/*
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * when ldc_close() returns EAGAIN, it is retried with a wait
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * of 'vldc_close_delay' between each retry.
cb112a141f667f84bf442a77589d1705a2336dbelm */
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sgstatic clock_t vldc_close_delay = VLDC_CLOSE_DELAY;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Print debug messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * set vldcdbg to 0x7 to enable all messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * 0x4 - Warnings
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * 0x2 - All debug messages (most verbose)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * 0x1 - Minimal debug messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint vldcdbg = 0x0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldcdebug(const char *fmt, ...)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char buf[512];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo va_list ap;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo va_start(ap, fmt);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vsnprintf(buf, sizeof (buf), fmt, ap);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo va_end(ap);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "?%s", buf);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define D1 if (vldcdbg & 0x01) vldcdebug
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define D2 if (vldcdbg & 0x02) vldcdebug
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DWARN if (vldcdbg & 0x04) vldcdebug
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#else /* not DEBUG */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define D1 if (0) printf
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define D2 if (0) printf
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DWARN if (0) printf
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif /* not DEBUG */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* _init(9E): initialize the loadable module */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo_init(void)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int error;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* init the soft state structure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = ddi_soft_state_init(&vldc_ssp, sizeof (vldc_t), 1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (error);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Link the driver into the system */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = mod_install(&ml);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (error);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* _info(9E): return information about the loadable module */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo_info(struct modinfo *modinfop)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Report status of the dynamically loadable driver module */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (mod_info(&ml, modinfop));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* _fini(9E): prepare the module for unloading. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo_fini(void)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int error;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Unlink the driver module from the system */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((error = mod_remove(&ml)) == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We have successfully "removed" the driver.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * destroy soft state
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_soft_state_fini(&vldc_ssp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (error);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ldc callback */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint_t
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_cb(uint64_t event, caddr_t arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan int rv;
3af08d828975d7e2581b6829e0eecff14d87a483lm vldc_port_t *vport = (vldc_port_t *)arg;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan ldc_status_t old_status;
3af08d828975d7e2581b6829e0eecff14d87a483lm short pollevents = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(vport != NULL);
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(vport->minorp != NULL);
cb112a141f667f84bf442a77589d1705a2336dbelm
3af08d828975d7e2581b6829e0eecff14d87a483lm D1("i_vldc_cb: vldc@%d:%d callback invoked, channel=0x%lx, "
3af08d828975d7e2581b6829e0eecff14d87a483lm "event=0x%lx\n", vport->inst, vport->number, vport->ldc_id, event);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm /* ensure the port can't be destroyed while we are handling the cb */
cb112a141f667f84bf442a77589d1705a2336dbelm mutex_enter(&vport->minorp->lock);
cb112a141f667f84bf442a77589d1705a2336dbelm
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg if (vport->status == VLDC_PORT_CLOSED) {
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg return (LDC_SUCCESS);
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg }
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan old_status = vport->ldc_status;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan rv = ldc_status(vport->ldc_handle, &vport->ldc_status);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan if (rv != 0) {
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan DWARN("i_vldc_cb: vldc@%d:%d could not get ldc status, "
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan "rv=%d\n", vport->inst, vport->number, rv);
cb112a141f667f84bf442a77589d1705a2336dbelm mutex_exit(&vport->minorp->lock);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan return (LDC_SUCCESS);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan }
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (event & LDC_EVT_UP) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pollevents |= POLLOUT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->hanged_up = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm } else if (event & LDC_EVT_RESET) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan * Mark the port in reset, if it is not CLOSED and
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan * the channel was previously in LDC_UP state. This
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan * implies that the port cannot be used until it has
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan * been closed and reopened.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg if (old_status == LDC_UP) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vport->status = VLDC_PORT_RESET;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan vport->hanged_up = B_TRUE;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan pollevents = POLLHUP;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan } else {
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan rv = ldc_up(vport->ldc_handle);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan if (rv) {
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan DWARN("i_vldc_cb: vldc@%d:%d cannot bring "
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan "channel UP rv=%d\n", vport->inst,
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan vport->number, rv);
cb112a141f667f84bf442a77589d1705a2336dbelm mutex_exit(&vport->minorp->lock);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan return (LDC_SUCCESS);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan }
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan rv = ldc_status(vport->ldc_handle, &vport->ldc_status);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan if (rv != 0) {
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan DWARN("i_vldc_cb: vldc@%d:%d could not get "
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan "ldc status, rv=%d\n", vport->inst,
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan vport->number, rv);
cb112a141f667f84bf442a77589d1705a2336dbelm mutex_exit(&vport->minorp->lock);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan return (LDC_SUCCESS);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan }
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan if (vport->ldc_status == LDC_UP) {
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan pollevents |= POLLOUT;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan vport->hanged_up = B_FALSE;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan }
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (event & LDC_EVT_DOWN) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan * The other side went away - mark port in RESET state
3af08d828975d7e2581b6829e0eecff14d87a483lm */
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan vport->status = VLDC_PORT_RESET;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->hanged_up = B_TRUE;
3af08d828975d7e2581b6829e0eecff14d87a483lm pollevents = POLLHUP;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (event & LDC_EVT_READ)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pollevents |= POLLIN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm mutex_exit(&vport->minorp->lock);
cb112a141f667f84bf442a77589d1705a2336dbelm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (pollevents != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_cb: port@%d pollwakeup=0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->number, pollevents);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pollwakeup(&vport->poll, pollevents);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (LDC_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* mdeg callback */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_mdeg_cb(void *cb_argp, mdeg_result_t *resp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo md_t *mdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mde_cookie_t node;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (resp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_cb: no result returned\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = (vldc_t *)cb_argp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp->detaching == B_TRUE) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_cb: detach in progress\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_cb: added=%d, removed=%d, matched=%d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->added.nelem, resp->removed.nelem, resp->match_prev.nelem);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* process added ports */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (idx = 0; idx < resp->added.nelem; idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdp = resp->added.mdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo node = resp->added.mdep[idx];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_cb: processing added node 0x%lx\n", node);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* attempt to add a port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((rv = i_vldc_add_port(vldcp, mdp, node)) != MDEG_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_mdeg_cb: unable to add port, "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "err = %d", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* process removed ports */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (idx = 0; idx < resp->removed.nelem; idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdp = resp->removed.mdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo node = resp->removed.mdep[idx];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_cb: processing removed node 0x%lx\n", node);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read in the port's id property */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, node, "id", &portno)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_mdeg_cb: node 0x%lx of "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "removed list has no 'id' property", node);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo continue;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* attempt to remove a port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((rv = i_vldc_remove_port(vldcp, portno)) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_mdeg_cb: unable to remove "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "port %lu, err %d", portno, rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Currently no support for updating already active ports. So, ignore
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the match_curr and match_prev arrays for now.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* register callback to mdeg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_mdeg_register(vldc_t *vldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdeg_prop_spec_t *pspecp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdeg_node_spec_t *inst_specp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdeg_handle_t mdeg_hdl;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t templatesz;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int inst;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char *name;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t namesz;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char *nameprop;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get the unique vldc instance assigned by the LDom manager */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo inst = ddi_prop_get_int(DDI_DEV_T_ANY, vldcp->dip,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DDI_PROP_DONTPASS, "reg", -1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (inst == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?vldc%d has no 'reg' property",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_get_instance(vldcp->dip));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get the name of the vldc instance */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ddi_prop_lookup_string(DDI_DEV_T_ANY, vldcp->dip,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DDI_PROP_DONTPASS, "name", &nameprop);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != DDI_PROP_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?vldc%d has no 'name' property",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_get_instance(vldcp->dip));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_register: name=%s, instance=%d\n", nameprop, inst);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Allocate and initialize a per-instance copy
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * of the global property spec array that will
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * uniquely identify this vldc instance.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo templatesz = sizeof (vldc_prop_template);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pspecp = kmem_alloc(templatesz, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(vldc_prop_template, pspecp, templatesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* copy in the name property */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo namesz = strlen(nameprop) + 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo name = kmem_alloc(namesz, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(nameprop, name, namesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VLDC_SET_MDEG_PROP_NAME(pspecp, name);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ddi_prop_free(nameprop);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* copy in the instance property */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VLDC_SET_MDEG_PROP_INST(pspecp, inst);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize the complete prop spec structure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo inst_specp = kmem_alloc(sizeof (mdeg_node_spec_t), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo inst_specp->namep = "virtual-device";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo inst_specp->specp = pspecp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* perform the registration */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = mdeg_register(inst_specp, &vport_match, i_vldc_mdeg_cb,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp, &mdeg_hdl);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != MDEG_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_mdeg_register: mdeg_register "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "failed, err = %d", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(name, namesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(pspecp, templatesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(inst_specp, sizeof (mdeg_node_spec_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save off data that will be needed later */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->inst_spec = inst_specp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->mdeg_hdl = mdeg_hdl;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* unregister callback from mdeg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_mdeg_unregister(vldc_t *vldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char *name;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_mdeg_unregister: hdl=0x%lx\n", vldcp->mdeg_hdl);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = mdeg_unregister(vldcp->mdeg_hdl);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != MDEG_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Clean up cached MDEG data
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo name = VLDC_MDEG_PROP_NAME(vldcp->inst_spec->specp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (name != NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(name, strlen(name) + 1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vldcp->inst_spec->specp, sizeof (vldc_prop_template));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->inst_spec->specp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vldcp->inst_spec, sizeof (mdeg_node_spec_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->inst_spec = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_get_port_channel(md_t *mdp, mde_cookie_t node, uint64_t *ldc_id)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int num_nodes, nchan;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t listsz;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mde_cookie_t *listp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Find the channel-endpoint node(s) (which should be under this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * port node) which contain the channel id(s).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((num_nodes = md_node_count(mdp)) <= 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_get_port_channel: invalid number of "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "channel-endpoint nodes found (%d)", num_nodes);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (-1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate space for node list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo listsz = num_nodes * sizeof (mde_cookie_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo listp = kmem_alloc(listsz, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nchan = md_scan_dag(mdp, node, md_find_name(mdp, "channel-endpoint"),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo md_find_name(mdp, "fwd"), listp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (nchan <= 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_get_port_channel: no channel-endpoint"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " nodes found");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (-1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("i_vldc_get_port_channel: %d channel-endpoint nodes found", nchan);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* use property from first node found */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, listp[0], "id", ldc_id)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_get_port_channel: channel-endpoint "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "has no 'id' property");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (-1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* add a vldc port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_add_port(vldc_t *vldcp, md_t *mdp, mde_cookie_t node)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char *sname;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int vldc_inst;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int minor_idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo boolean_t new_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(MUTEX_HELD(&vldcp->lock));
cb112a141f667f84bf442a77589d1705a2336dbelm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read in the port's id property */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, node, "id", &portno)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_add_port: node 0x%lx of added "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "list has no 'id' property", node);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno >= VLDC_MAX_PORTS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_add_port: found port number (%lu) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "larger than maximum supported number of ports", portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->minorp != NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_add_port: trying to add a port (%lu)"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " which is already bound", portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->number = portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get all channels for this device (currently only one) */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (i_vldc_get_port_channel(mdp, node, &vport->ldc_id) == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set the default MTU */
d1a9c4c143aaef0b57cf9531ab060cc86dddaf09jm vport->mtu = VLDC_DEFAULT_MTU;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get the service being exported by this port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_str(mdp, node, "vldc-svc-name", &sname)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_add_port: vdevice has no "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "'vldc-svc-name' property");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* minor number look up */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (minor_idx = 0; minor_idx < vldcp->minors_assigned;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (strcmp(vldcp->minor_tbl[minor_idx].sname, sname) == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* found previously assigned minor number */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo new_minor = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (minor_idx == vldcp->minors_assigned) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* end of lookup - assign new minor number */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp->minors_assigned == VLDC_MAX_MINORS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_add_port: too many minor "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "nodes (%d)", minor_idx);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) strlcpy(vldcp->minor_tbl[minor_idx].sname,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sname, MAXPATHLEN);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->minors_assigned++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo new_minor = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm if (vldcp->minor_tbl[minor_idx].portno != VLDC_INVALID_PORTNO) {
cb112a141f667f84bf442a77589d1705a2336dbelm cmn_err(CE_NOTE, "?i_vldc_add_port: trying to add a port (%lu)"
cb112a141f667f84bf442a77589d1705a2336dbelm " which has a minor number in use by port (%u)",
cb112a141f667f84bf442a77589d1705a2336dbelm portno, vldcp->minor_tbl[minor_idx].portno);
cb112a141f667f84bf442a77589d1705a2336dbelm return (MDEG_FAILURE);
cb112a141f667f84bf442a77589d1705a2336dbelm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm vldc_inst = ddi_get_instance(vldcp->dip);
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm vport->inst = vldc_inst;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->minorp = &vldcp->minor_tbl[minor_idx];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->minor_tbl[minor_idx].portno = portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->minor_tbl[minor_idx].in_use = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm D1("i_vldc_add_port: vldc@%d:%d mtu=%d, ldc=%ld, service=%s\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm vport->inst, vport->number, vport->mtu, vport->ldc_id, sname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Create a minor node. The minor number is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * (vldc_inst << VLDC_INST_SHIFT) | minor_idx
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = (vldc_inst << VLDC_INST_SHIFT) | (minor_idx);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ddi_create_minor_node(vldcp->dip, sname, S_IFCHR,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor, DDI_NT_SERIAL, 0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != DDI_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_add_port: failed to create minor"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "node (%u), err = %d", minor, rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->minor_tbl[minor_idx].portno = VLDC_INVALID_PORTNO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (new_minor) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->minors_assigned--;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The port is now bound to a minor node and is initially in the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * closed state.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->status = VLDC_PORT_CLOSED;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_add_port: port %lu initialized\n", portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* remove a vldc port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_remove_port(vldc_t *vldcp, uint_t portno)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(vldcp != NULL);
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(MUTEX_HELD(&vldcp->lock));
cb112a141f667f84bf442a77589d1705a2336dbelm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = vport->minorp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vminor == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_NOTE, "?i_vldc_remove_port: trying to remove a "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "port (%u) which is not bound", portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Make sure that all new attempts to open or use the minor node
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * associated with the port will fail.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor->portno = VLDC_INVALID_PORTNO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send hangup to anyone polling */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pollwakeup(&vport->poll, POLLHUP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Now wait for all current users of the minor node to finish. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (vminor->in_use > 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cv_wait(&vminor->cv, &vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm if (vport->status != VLDC_PORT_CLOSED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* close the port before it is torn down */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) i_vldc_close_port(vldcp, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* remove minor node */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_remove_minor_node(vldcp->dip, vport->minorp->sname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->minorp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("i_vldc_remove_port: removed vldc port %u\n", portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
cb112a141f667f84bf442a77589d1705a2336dbelm/*
cb112a141f667f84bf442a77589d1705a2336dbelm * Close and destroy the ldc channel associated with the port 'vport'
cb112a141f667f84bf442a77589d1705a2336dbelm *
cb112a141f667f84bf442a77589d1705a2336dbelm * NOTE It may not be possible close and destroy the channel if resources
cb112a141f667f84bf442a77589d1705a2336dbelm * are still in use so the fucntion may exit before all the teardown
cb112a141f667f84bf442a77589d1705a2336dbelm * operations are completed and would have to be called again by the
cb112a141f667f84bf442a77589d1705a2336dbelm * vldc framework.
cb112a141f667f84bf442a77589d1705a2336dbelm *
cb112a141f667f84bf442a77589d1705a2336dbelm * This function needs to be able to handle the case where it is called
cb112a141f667f84bf442a77589d1705a2336dbelm * more than once and has to pick up from where it left off.
cb112a141f667f84bf442a77589d1705a2336dbelm */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_ldc_close(vldc_port_t *vport)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
cb112a141f667f84bf442a77589d1705a2336dbelm int err = 0;
cb112a141f667f84bf442a77589d1705a2336dbelm
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(MUTEX_HELD(&vport->minorp->lock));
cb112a141f667f84bf442a77589d1705a2336dbelm
cb112a141f667f84bf442a77589d1705a2336dbelm /*
cb112a141f667f84bf442a77589d1705a2336dbelm * If ldc_close() succeeded or if the channel was already closed[*]
cb112a141f667f84bf442a77589d1705a2336dbelm * (possibly by a previously unsuccessful call to this function)
cb112a141f667f84bf442a77589d1705a2336dbelm * we keep going and try to teardown the rest of the LDC state,
cb112a141f667f84bf442a77589d1705a2336dbelm * otherwise we bail out.
cb112a141f667f84bf442a77589d1705a2336dbelm *
cb112a141f667f84bf442a77589d1705a2336dbelm * [*] indicated by ldc_close() returning a value of EFAULT
cb112a141f667f84bf442a77589d1705a2336dbelm */
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg err = ldc_close(vport->ldc_handle);
cb112a141f667f84bf442a77589d1705a2336dbelm if ((err != 0) && (err != EFAULT))
cb112a141f667f84bf442a77589d1705a2336dbelm return (err);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo err = ldc_unreg_callback(vport->ldc_handle);
cb112a141f667f84bf442a77589d1705a2336dbelm if (err != 0)
cb112a141f667f84bf442a77589d1705a2336dbelm return (err);
cb112a141f667f84bf442a77589d1705a2336dbelm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo err = ldc_fini(vport->ldc_handle);
cb112a141f667f84bf442a77589d1705a2336dbelm if (err != 0)
cb112a141f667f84bf442a77589d1705a2336dbelm return (err);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm vport->status = VLDC_PORT_OPEN;
3af08d828975d7e2581b6829e0eecff14d87a483lm
cb112a141f667f84bf442a77589d1705a2336dbelm return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* close a vldc port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_close_port(vldc_t *vldcp, uint_t portno)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
3af08d828975d7e2581b6829e0eecff14d87a483lm vldc_port_t *vport;
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg vldc_minor_t *vminor;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = DDI_SUCCESS;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT(MUTEX_HELD(&vport->minorp->lock));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm D1("i_vldc_close_port: vldc@%d:%d: closing port\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm vport->inst, vport->minorp->portno);
3af08d828975d7e2581b6829e0eecff14d87a483lm
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg vminor = vport->minorp;
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg
3af08d828975d7e2581b6829e0eecff14d87a483lm switch (vport->status) {
3af08d828975d7e2581b6829e0eecff14d87a483lm case VLDC_PORT_CLOSED:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* nothing to do */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("i_vldc_close_port: port %d in an unexpected "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "state (%d)\n", portno, vport->status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm case VLDC_PORT_READY:
3af08d828975d7e2581b6829e0eecff14d87a483lm case VLDC_PORT_RESET:
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg do {
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg rv = i_vldc_ldc_close(vport);
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg if (rv != EAGAIN)
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg break;
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg /*
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * EAGAIN indicates that ldc_close() failed because
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * ldc callback thread is active for the channel.
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * cv_timedwait() is used to release vminor->lock and
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * allow ldc callback thread to complete.
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * after waking up, check if the port has been closed
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg * by another thread in the meantime.
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&vminor->cv, &vminor->lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(vldc_close_delay), TR_CLOCK_TICK);
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg rv = 0;
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg } while (vport->status != VLDC_PORT_CLOSED);
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg if ((rv != 0) || (vport->status == VLDC_PORT_CLOSED))
cb112a141f667f84bf442a77589d1705a2336dbelm return (rv);
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg
3af08d828975d7e2581b6829e0eecff14d87a483lm break;
cb112a141f667f84bf442a77589d1705a2336dbelm
cb112a141f667f84bf442a77589d1705a2336dbelm case VLDC_PORT_OPEN:
cb112a141f667f84bf442a77589d1705a2336dbelm break;
cb112a141f667f84bf442a77589d1705a2336dbelm
cb112a141f667f84bf442a77589d1705a2336dbelm default:
cb112a141f667f84bf442a77589d1705a2336dbelm DWARN("i_vldc_close_port: port %d in an unexpected "
cb112a141f667f84bf442a77589d1705a2336dbelm "state (%d)\n", portno, vport->status);
cb112a141f667f84bf442a77589d1705a2336dbelm ASSERT(0); /* fail quickly to help diagnosis */
cb112a141f667f84bf442a77589d1705a2336dbelm return (EINVAL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(vport->status == VLDC_PORT_OPEN);
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free memory */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vport->send_buf, vport->mtu);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vport->recv_buf, vport->mtu);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
4d39be2b45b5ac811d28452e6eb629ac64aebfc4sg if (strcmp(vminor->sname, VLDC_HVCTL_SVCNAME) == 0)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan kmem_free(vport->cookie_buf, vldc_max_cookie);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->status = VLDC_PORT_CLOSED;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * attach(9E): attach a device to the system.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * called once for each instance of the device on the system.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i, instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (cmd) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case DDI_ATTACH:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = ddi_get_instance(dip);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_soft_state_zalloc(vldc_ssp, instance) != DDI_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_soft_state_free(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_attach: DDI_ATTACH instance=%d\n", instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&vldcp->lock, NULL, MUTEX_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->dip = dip;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->detaching = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < VLDC_MAX_PORTS; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* No minor node association to start with */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->port[i].minorp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < VLDC_MAX_MINORS; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&(vldcp->minor_tbl[i].lock), NULL,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo MUTEX_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cv_init(&(vldcp->minor_tbl[i].cv), NULL,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo CV_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* No port association to start with */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->minor_tbl[i].portno = VLDC_INVALID_PORTNO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Register for MD update notification */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (i_vldc_mdeg_register(vldcp) != DDI_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_soft_state_free(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case DDI_RESUME:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * detach(9E): detach a device from the system.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i, instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (cmd) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case DDI_DETACH:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = ddi_get_instance(dip);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_detach: DDI_DETACH instance=%d\n", instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Fail the detach if all ports have not been removed. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < VLDC_MAX_MINORS; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp->minor_tbl[i].portno != VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_detach: vldc@%d:%d is bound, "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "detach failed\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, vldcp->minor_tbl[i].portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Prevent MDEG from adding new ports before the callback can
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * be unregistered. The lock can't be held accross the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * unregistration call because a callback may be in progress
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and blocked on the lock.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->detaching = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (i_vldc_mdeg_unregister(vldcp) != MDEG_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp->detaching = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Tear down all bound ports and free resources. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < VLDC_MAX_MINORS; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp->minor_tbl[i].portno != VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) i_vldc_remove_port(vldcp, i);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&(vldcp->minor_tbl[i].lock));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cv_destroy(&(vldcp->minor_tbl[i].cv));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&vldcp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ddi_soft_state_free(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case DDI_SUSPEND:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* cb_open */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_open(dev_t *devp, int flag, int otyp, cred_t *cred)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(flag, otyp, cred))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = getminor(*devp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = VLDCINST(minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = VLDCMINOR(vldcp, minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portno = vminor->portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno == VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_open: opening vldc@%d:%lu\n", instance, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->status != VLDC_PORT_CLOSED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EBUSY);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->recv_buf = kmem_alloc(vport->mtu, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->send_buf = kmem_alloc(vport->mtu, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME) == 0)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vport->cookie_buf = kmem_alloc(vldc_max_cookie, KM_SLEEP);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->is_stream = B_FALSE; /* assume not a stream */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->hanged_up = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->status = VLDC_PORT_OPEN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* cb_close */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_close(dev_t dev, int flag, int otyp, cred_t *cred)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(flag, otyp, cred))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = getminor(dev);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = VLDCINST(minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = VLDCMINOR(vldcp, minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portno = vminor->portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno == VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOLINK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_close: closing vldc@%d:%lu\n", instance, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = i_vldc_close_port(vldcp, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_set_ldc_mode(vldc_port_t *vport, vldc_t *vldcp, int channel_mode)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_attr_t attr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT(MUTEX_HELD(&vport->minorp->lock));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate mode */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (channel_mode) {
20ae46ebaff1237662e05edf9db61538aa85d448ha case LDC_MODE_RELIABLE:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->is_stream = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case LDC_MODE_RAW:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case LDC_MODE_UNRELIABLE:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->is_stream = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EINVAL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->status == VLDC_PORT_READY) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = i_vldc_ldc_close(vport);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_set_ldc_mode: i_vldc_ldc_close "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "failed, rv=%d\n", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_set_ldc_mode: vport status %d, mode %d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->status, channel_mode);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->ldc_mode = channel_mode;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.devclass = LDC_DEV_SERIAL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.instance = ddi_get_instance(vldcp->dip);
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm attr.mtu = vport->mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.mode = vport->ldc_mode;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((rv = ldc_init(vport->ldc_id, &attr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &vport->ldc_handle)) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_ioctl_opt_op: ldc_init failed, rv=%d\n", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto error_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* register it */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((rv = ldc_reg_callback(vport->ldc_handle,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo i_vldc_cb, (caddr_t)vport)) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_ioctl_opt_op: ldc_reg_callback failed, rv=%d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto error_reg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* open the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((rv = ldc_open(vport->ldc_handle)) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_ioctl_opt_op: ldc_open failed, rv=%d\n", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto error_open;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->status = VLDC_PORT_READY;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Attempt to bring the channel up, but do not
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fail if the other end is not up yet.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_up(vport->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv == ECONNREFUSED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_ioctl_opt_op: remote endpoint not up yet\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_ioctl_opt_op: ldc_up failed, rv=%d\n", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto error_up;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan rv = ldc_status(vport->ldc_handle, &vport->ldc_status);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan if (rv != 0) {
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan DWARN("vldc_ioctl_opt_op: vldc@%d:%d could not get ldc "
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan "status, rv=%d\n", vport->inst, vport->number, rv);
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan goto error_up;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan }
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_ioctl_opt_op: ldc %ld initialized successfully\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->ldc_id);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoerror_up:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->status = VLDC_PORT_OPEN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_close(vport->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoerror_open:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_unreg_callback(vport->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoerror_reg:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_fini(vport->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoerror_init:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ioctl to read cookie */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_ioctl_read_cookie(vldc_port_t *vport, int vldc_instance, void *arg,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int mode)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_data_t copy_info;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint64_t len, balance, copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan caddr_t src_addr, dst_addr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyin(arg, &copy_info, sizeof (copy_info), mode) == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan len = balance = copy_info.length;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan src_addr = (caddr_t)copy_info.src_addr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst_addr = (caddr_t)copy_info.dst_addr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan while (balance > 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* get the max amount to the copied */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan copy_size = MIN(balance, vldc_max_cookie);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_enter(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan D2("i_vldc_ioctl_read_cookie: vldc@%d:%d reading from 0x%p "
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "size 0x%lx to 0x%p\n", vldc_instance, vport->number,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst_addr, copy_size, src_addr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* read from the HV into the temporary buffer */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_mem_rdwr_cookie(vport->ldc_handle, vport->cookie_buf,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan &copy_size, dst_addr, LDC_COPY_IN);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (rv != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DWARN("i_vldc_ioctl_read_cookie: vldc@%d:%d cannot "
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "read address 0x%p, rv=%d\n",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vldc_instance, vport->number, dst_addr, rv);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&vport->minorp->lock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (EFAULT);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan D2("i_vldc_ioctl_read_cookie: vldc@%d:%d read succeeded\n",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vldc_instance, vport->number);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * copy data from temporary buffer out to the
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * caller and free buffer
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rv = ddi_copyout(vport->cookie_buf, src_addr, copy_size, mode);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (rv != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (EFAULT);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* adjust len, source and dest */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan balance -= copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan src_addr += copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst_addr += copy_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set the structure to reflect outcome */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo copy_info.length = len;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyout(&copy_info, arg, sizeof (copy_info), mode) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ioctl to write cookie */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_ioctl_write_cookie(vldc_port_t *vport, int vldc_instance, void *arg,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int mode)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_data_t copy_info;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint64_t len, balance, copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan caddr_t src_addr, dst_addr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ddi_copyin(arg, &copy_info, sizeof (copy_info), mode) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("i_vldc_ioctl_write_cookie: vldc@%d:%d writing 0x%lx size 0x%lx "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "to 0x%lx\n", vldc_instance, vport->number, copy_info.src_addr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo copy_info.length, copy_info.dst_addr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan len = balance = copy_info.length;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan src_addr = (caddr_t)copy_info.src_addr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst_addr = (caddr_t)copy_info.dst_addr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan while (balance > 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* get the max amount to the copied */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan copy_size = MIN(balance, vldc_max_cookie);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * copy into the temporary buffer the data
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * to be written to the HV
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ddi_copyin((caddr_t)src_addr, vport->cookie_buf,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan copy_size, mode) != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (EFAULT);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_enter(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* write the data from the temporary buffer to the HV */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_mem_rdwr_cookie(vport->ldc_handle, vport->cookie_buf,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan &copy_size, dst_addr, LDC_COPY_OUT);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (rv != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DWARN("i_vldc_ioctl_write_cookie: vldc@%d:%d "
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "failed to write at address 0x%p\n, rv=%d",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vldc_instance, vport->number, dst_addr, rv);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&vport->minorp->lock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (EFAULT);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan D2("i_vldc_ioctl_write_cookie: vldc@%d:%d write succeeded\n",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vldc_instance, vport->number);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* adjust len, source and dest */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan balance -= copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan src_addr += copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst_addr += copy_size;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set the structure to reflect outcome */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo copy_info.length = len;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyout(&copy_info, (caddr_t)arg,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (copy_info), mode) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vldc specific ioctl option commands */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoi_vldc_ioctl_opt_op(vldc_port_t *vport, vldc_t *vldcp, void *arg, int mode)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_opt_op_t vldc_cmd;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t new_mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyin(arg, &vldc_cmd, sizeof (vldc_cmd), mode) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_ioctl_opt_op: op %d\n", vldc_cmd.opt_sel);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (vldc_cmd.opt_sel) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VLDC_OPT_MTU_SZ:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldc_cmd.op_sel == VLDC_OP_GET) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_cmd.opt_val = vport->mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyout(&vldc_cmd, arg,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (vldc_cmd), mode) == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo new_mtu = vldc_cmd.opt_val;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((new_mtu < LDC_PACKET_SIZE) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (new_mtu > vldc_max_mtu)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EINVAL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((vport->status != VLDC_PORT_CLOSED) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (new_mtu != vport->mtu)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The port has buffers allocated since it is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * not closed plus the MTU size has changed.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Reallocate the buffers to the new MTU size.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vport->recv_buf, vport->mtu);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->recv_buf = kmem_alloc(new_mtu, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vport->send_buf, vport->mtu);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->send_buf = kmem_alloc(new_mtu, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->mtu = new_mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VLDC_OPT_STATUS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldc_cmd.op_sel == VLDC_OP_GET) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_cmd.opt_val = vport->status;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyout(&vldc_cmd, arg,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (vldc_cmd), mode) == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOTSUP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VLDC_OPT_MODE:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldc_cmd.op_sel == VLDC_OP_GET) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_cmd.opt_val = vport->ldc_mode;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ddi_copyout(&vldc_cmd, arg,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (vldc_cmd), mode) == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EFAULT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vldc_set_ldc_mode(vport, vldcp, vldc_cmd.opt_val);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vport->minorp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_ioctl_opt_op: unsupported op %d\n", vldc_cmd.opt_sel);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOTSUP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* cb_ioctl */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int *rvalp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(credp, rvalp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv = EINVAL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = getminor(dev);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = VLDCINST(minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = VLDCMINOR(vldcp, minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portno = vminor->portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno == VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOLINK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor->in_use += 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_ioctl: vldc@%d:%lu cmd=0x%x\n", instance, portno, cmd);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (cmd) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VLDC_IOCTL_OPT_OP:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = i_vldc_ioctl_opt_op(vport, vldcp, (void *)arg, mode);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VLDC_IOCTL_READ_COOKIE:
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME)) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rv = EINVAL;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan break;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = i_vldc_ioctl_read_cookie(vport, instance,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void *)arg, mode);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VLDC_IOCTL_WRITE_COOKIE:
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME)) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rv = EINVAL;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan break;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = i_vldc_ioctl_write_cookie(vport, instance,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void *)arg, mode);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_ioctl: vldc@%d:%lu unknown cmd=0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, portno, cmd);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = EINVAL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor->in_use -= 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vminor->in_use == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cv_signal(&vminor->cv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D1("vldc_ioctl: rv=%d\n", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* cb_read */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_read(dev_t dev, struct uio *uiop, cred_t *credp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(credp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t size = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = getminor(dev);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = VLDCINST(minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = VLDCMINOR(vldcp, minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portno = vminor->portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno == VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOLINK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("vldc_read: vldc@%d:%lu reading data\n", instance, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check the port status */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->status != VLDC_PORT_READY) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_read: vldc@%d:%lu not in the ready state\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOTACTIVE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read data */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size = MIN(vport->mtu, uiop->uio_resid);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_read(vport->ldc_handle, vport->recv_buf, &size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("vldc_read: vldc@%d:%lu ldc_read size=%ld, rv=%d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, portno, size, rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (size != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = uiomove(vport->recv_buf, size, UIO_READ, uiop);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = EWOULDBLOCK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (rv) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case ENOBUFS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case ETIMEDOUT:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case EWOULDBLOCK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = EWOULDBLOCK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ECONNRESET;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* cb_write */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_write(dev_t dev, struct uio *uiop, cred_t *credp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(credp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t orig_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv = EINVAL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = getminor(dev);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = VLDCINST(minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = VLDCMINOR(vldcp, minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portno = vminor->portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno == VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOLINK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check the port status */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->status != VLDC_PORT_READY) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_write: vldc@%d:%lu not in the ready state\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, portno);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOTACTIVE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo orig_size = uiop->uio_resid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size = orig_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (size > vport->mtu) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->is_stream) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* can only send MTU size at a time */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size = vport->mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (EMSGSIZE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("vldc_write: vldc@%d:%lu writing %lu bytes\n", instance, portno,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = uiomove(vport->send_buf, size, UIO_WRITE, uiop);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_write(vport->ldc_handle, (caddr_t)vport->send_buf,
d1a9c4c143aaef0b57cf9531ab060cc86dddaf09jm &size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN("vldc_write: vldc@%d:%lu failed writing %lu "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "bytes rv=%d\n", instance, portno, size, rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* resid is total number of bytes *not* sent */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uiop->uio_resid = orig_size - size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* cb_chpoll */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovldc_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct pollhead **phpp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor_t minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_t *vldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_port_t *vport;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldc_minor_t *vminor;
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm boolean_t haspkts;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo minor = getminor(dev);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = VLDCINST(minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vldcp = ddi_get_soft_state(vldc_ssp, instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENXIO);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vminor = VLDCMINOR(vldcp, minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portno = vminor->portno;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portno == VLDC_INVALID_PORTNO) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOLINK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport = &(vldcp->port[portno]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check the port status */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vport->status != VLDC_PORT_READY) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ENOTACTIVE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("vldc_chpoll: vldc@%d:%lu polling events 0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, portno, events);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *reventsp = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan if (vport->ldc_status == LDC_UP) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check if the receive queue is empty and if not, signal that
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * there is data ready to read.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (events & POLLIN) {
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm if ((ldc_chkq(vport->ldc_handle, &haspkts) == 0) &&
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm haspkts) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *reventsp |= POLLIN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (events & POLLOUT)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *reventsp |= POLLOUT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (vport->hanged_up) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *reventsp |= POLLHUP;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport->hanged_up = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vminor->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (((*reventsp) == 0) && (!anyyet)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *phpp = &vport->poll;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo D2("vldc_chpoll: vldc@%d:%lu ev=0x%x, rev=0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance, portno, events, *reventsp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}