843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or http://www.opensolaris.org/os/licensing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Xen virtual device driver interfaces
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * todo:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * + name space clean up:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xvdi_* - public xen interfaces, for use by all leaf drivers
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xd_* - public xen data structures
843e19887f64dde75055cf8842fc4db2171eff45johnlev * i_xvdi_* - implementation private functions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops
843e19887f64dde75055cf8842fc4db2171eff45johnlev * + add mdb dcmds to dump ring status
843e19887f64dde75055cf8842fc4db2171eff45johnlev * + implement xvdi_xxx to wrap xenbus_xxx read/write function
843e19887f64dde75055cf8842fc4db2171eff45johnlev * + convert (xendev_ring_t *) into xvdi_ring_handle_t
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/conf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/param.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/kmem.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <vm/seg_kmem.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/debug.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/modctl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/autoconf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/ddi_impldefs.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/ddi_subrdefs.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/ddi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sunddi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sunndi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sunldi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/fs/dv_node.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/avintr.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/psm.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/spl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/promif.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/list.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/bootconf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/bootsvcs.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/bootinfo.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/note.h>
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz#include <sys/sysmacros.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifdef XPV_HVM_DRIVER
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/xpv_support.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/hypervisor.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <public/grant_table.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <public/xen.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <public/io/xenbus.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <public/io/xs_wire.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <public/event_channel.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <public/io/xenbus.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#else /* XPV_HVM_DRIVER */
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/hypervisor.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/xen_mmu.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/sys/xenbus_impl.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/evtchn_impl.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif /* XPV_HVM_DRIVER */
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/gnttab.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/sys/xendev.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <vm/hat_i86.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/scsi/generic/inquiry.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <util/sscanf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/public/io/xs_wire.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
06bbe1e05e4f6fd0773ee85a50c0de7adfc4fa06edp#define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
06bbe1e05e4f6fd0773ee85a50c0de7adfc4fa06edp#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
06bbe1e05e4f6fd0773ee85a50c0de7adfc4fa06edp ((ch) >= 'A' && (ch) <= 'F'))
06bbe1e05e4f6fd0773ee85a50c0de7adfc4fa06edp
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_ring_init_sring(xendev_ring_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifndef XPV_HVM_DRIVER
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int i_xvdi_add_watches(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_rem_watches(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int i_xvdi_add_watch_oestate(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_rem_watch_oestate(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_oestate_handler(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int i_xvdi_add_watch_hpstate(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_rem_watch_hpstate(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_hpstate_handler(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int i_xvdi_add_watch_bepath(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_rem_watch_bepath(dev_info_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_bepath_cb(struct xenbus_watch *, const char **,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned in);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xendev_offline_device(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_probe_path_handler(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhentypedef struct oestate_evt {
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen dev_info_t *dip;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen XenbusState state;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen} i_oestate_evt_t;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct xd_cfg {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_devclass_t devclass;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *xsdev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *xs_path_fe;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *xs_path_be;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *node_fe;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *node_be;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *device_type;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int xd_ipl;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int flags;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} i_xd_cfg_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XD_DOM_ZERO 0x01 /* dom0 only. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XD_DOM_GUEST 0x02 /* Guest domains (i.e. non-dom0). */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XD_DOM_IO 0x04 /* IO domains. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XD_DOM_ALL (XD_DOM_ZERO | XD_DOM_GUEST)
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic i_xd_cfg_t xdci[] = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_CONSOLE, NULL, NULL, NULL, "xencons", NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "console", IPL_CONS, XD_DOM_ALL, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb",
843e19887f64dde75055cf8842fc4db2171eff45johnlev "network", IPL_VIF, XD_DOM_ALL, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb",
843e19887f64dde75055cf8842fc4db2171eff45johnlev "block", IPL_VBD, XD_DOM_ALL, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson { XEN_BLKTAP, "tap", NULL, "backend/tap", NULL, "xpvtap",
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson "block", IPL_VBD, XD_DOM_ALL, },
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_XENBUS, NULL, NULL, NULL, "xenbus", NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL, 0, XD_DOM_ALL, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_DOMCAPS, NULL, NULL, NULL, "domcaps", NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL, 0, XD_DOM_ALL, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_BALLOON, NULL, NULL, NULL, "balloon", NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL, 0, XD_DOM_ALL, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_EVTCHN, NULL, NULL, NULL, "evtchn", NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL, 0, XD_DOM_ZERO, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_PRIVCMD, NULL, NULL, NULL, "privcmd", NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL, 0, XD_DOM_ZERO, },
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define NXDC (sizeof (xdci) / sizeof (xdci[0]))
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_enum_fe(dev_info_t *, i_xd_cfg_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_enum_be(dev_info_t *, i_xd_cfg_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_enum_worker(dev_info_t *, i_xd_cfg_t *, char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Xen device channel device access and DMA attributes
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ddi_device_acc_attr_t xendev_dc_accattr = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ddi_dma_attr_t xendev_dc_dmaattr = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev DMA_ATTR_V0, /* version of this structure */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, /* lowest usable address */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0xffffffffffffffffULL, /* highest usable address */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0x7fffffff, /* maximum DMAable byte count */
843e19887f64dde75055cf8842fc4db2171eff45johnlev MMU_PAGESIZE, /* alignment in bytes */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0x7ff, /* bitmap of burst sizes */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 1, /* minimum transfer */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0xffffffffU, /* maximum transfer */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0xffffffffffffffffULL, /* maximum segment length */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 1, /* maximum number of segments */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 1, /* granularity */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, /* flags (reserved) */
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic dev_info_t *xendev_dip = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XVDI_DBG_STATE 0x01
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XVDI_DBG_PROBE 0x02
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#ifdef DEBUG
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlevint i_xvdi_debug = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XVDI_DPRINTF(flag, format, ...) \
843e19887f64dde75055cf8842fc4db2171eff45johnlev{ \
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i_xvdi_debug & (flag)) \
843e19887f64dde75055cf8842fc4db2171eff45johnlev prom_printf((format), __VA_ARGS__); \
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev#else
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XVDI_DPRINTF(flag, format, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif /* DEBUG */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic i_xd_cfg_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_devclass2cfg(xendev_devclass_t devclass)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xdcp->devclass == devclass)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xdcp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_init_dev(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_devclass_t devcls;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int vdevnum;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t domid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t backend;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char xsnamebuf[TYPICALMAXPATHLEN];
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *xsname;
97869ac5121a555decdf3080d02beef2af506da6jhd void *prop_str;
3de3be76cb8643f7d719a74cc987d88f85238c0cjhd unsigned int prop_len;
97869ac5121a555decdf3080d02beef2af506da6jhd char unitaddr[8];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_DONTPASS, "devclass", XEN_INVAL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev DDI_PROP_DONTPASS, "vdev", VDEV_NOXS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_DONTPASS, "domain", DOMID_SELF);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev backend = (domid != DOMID_SELF);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xdcp = i_xvdi_devclass2cfg(devcls);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xdcp->device_type != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "device_type", xdcp->device_type);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_domain = domid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_vdevnum = vdevnum;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_devclass = devcls;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_evtchn = INVALID_EVTCHN;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz list_create(&pdp->xd_xb_watches, sizeof (xd_xb_watches_t),
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz offsetof(xd_xb_watches_t, xxw_list));
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_init(&pdp->xd_evt_lk, NULL, MUTEX_DRIVER, NULL);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_init(&pdp->xd_ndi_lk, NULL, MUTEX_DRIVER, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_set_parent_data(dip, pdp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * devices that do not need to interact with xenstore
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev if (vdevnum == VDEV_NOXS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "unit-address", "0");
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (devcls == XEN_CONSOLE)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "pm-hardware-state", "needs-suspend-resume");
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * PV devices that need to probe xenstore
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "pm-hardware-state", "needs-suspend-resume");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xsname = xsnamebuf;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!backend)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
843e19887f64dde75055cf8842fc4db2171eff45johnlev "%s/%d", xdcp->xs_path_fe, vdevnum);
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
843e19887f64dde75055cf8842fc4db2171eff45johnlev "%s/%d/%d", xdcp->xs_path_be, domid, vdevnum);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) {
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev /* Don't try to init a dev that may be closing */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_destroy(&pdp->xd_ndi_lk);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_destroy(&pdp->xd_evt_lk);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev kmem_free(pdp, sizeof (*pdp));
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev ddi_set_parent_data(dip, NULL);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev return (DDI_FAILURE);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.devicetype = xdcp->xsdev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.frontend = (backend ? 0 : 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.data = dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.otherend_id = (backend ? domid : -1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i_xvdi_add_watches(dip) != DDI_SUCCESS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "xvdi_init_dev: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "cannot add watches for %s", xsname);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_uninit_dev(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
97869ac5121a555decdf3080d02beef2af506da6jhd if (backend)
97869ac5121a555decdf3080d02beef2af506da6jhd return (DDI_SUCCESS);
97869ac5121a555decdf3080d02beef2af506da6jhd
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
97869ac5121a555decdf3080d02beef2af506da6jhd * The unit-address for frontend devices is the name of the
97869ac5121a555decdf3080d02beef2af506da6jhd * of the xenstore node containing the device configuration
97869ac5121a555decdf3080d02beef2af506da6jhd * and is contained in the 'vdev' property.
97869ac5121a555decdf3080d02beef2af506da6jhd * VIF devices are named using an incrementing integer.
97869ac5121a555decdf3080d02beef2af506da6jhd * VBD devices are either named using the 16-bit dev_t value
97869ac5121a555decdf3080d02beef2af506da6jhd * for linux 'hd' and 'xvd' devices, or a simple integer value
97869ac5121a555decdf3080d02beef2af506da6jhd * in the range 0..767. 768 is the base value of the linux
97869ac5121a555decdf3080d02beef2af506da6jhd * dev_t namespace, the dev_t value for 'hda'.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
97869ac5121a555decdf3080d02beef2af506da6jhd (void) snprintf(unitaddr, sizeof (unitaddr), "%d", vdevnum);
97869ac5121a555decdf3080d02beef2af506da6jhd (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unit-address",
97869ac5121a555decdf3080d02beef2af506da6jhd unitaddr);
97869ac5121a555decdf3080d02beef2af506da6jhd
97869ac5121a555decdf3080d02beef2af506da6jhd switch (devcls) {
97869ac5121a555decdf3080d02beef2af506da6jhd case XEN_VNET:
97869ac5121a555decdf3080d02beef2af506da6jhd if (xenbus_read(XBT_NULL, xsname, "mac", (void *)&prop_str,
97869ac5121a555decdf3080d02beef2af506da6jhd &prop_len) != 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
97869ac5121a555decdf3080d02beef2af506da6jhd (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "mac",
97869ac5121a555decdf3080d02beef2af506da6jhd prop_str);
97869ac5121a555decdf3080d02beef2af506da6jhd kmem_free(prop_str, prop_len);
97869ac5121a555decdf3080d02beef2af506da6jhd break;
97869ac5121a555decdf3080d02beef2af506da6jhd case XEN_VBLK:
97869ac5121a555decdf3080d02beef2af506da6jhd /*
97869ac5121a555decdf3080d02beef2af506da6jhd * cache a copy of the otherend name
97869ac5121a555decdf3080d02beef2af506da6jhd * for ease of observeability
97869ac5121a555decdf3080d02beef2af506da6jhd */
97869ac5121a555decdf3080d02beef2af506da6jhd if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, "dev",
97869ac5121a555decdf3080d02beef2af506da6jhd &prop_str, &prop_len) != 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
97869ac5121a555decdf3080d02beef2af506da6jhd (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
97869ac5121a555decdf3080d02beef2af506da6jhd "dev-address", prop_str);
97869ac5121a555decdf3080d02beef2af506da6jhd kmem_free(prop_str, prop_len);
97869ac5121a555decdf3080d02beef2af506da6jhd break;
97869ac5121a555decdf3080d02beef2af506da6jhd default:
97869ac5121a555decdf3080d02beef2af506da6jhd break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_uninit_dev(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Remove any registered callbacks. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_remove_event_handler(dip, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Remove any registered watches. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watches(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev /* tell other end to close */
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj if (pdp->xd_xsdev.otherend_id != (domid_t)-1)
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj (void) xvdi_switch_state(dip, XBT_NULL,
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj XenbusStateClosed);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_xsdev.nodename != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free((char *)(pdp->xd_xsdev.nodename),
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen(pdp->xd_xsdev.nodename) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_set_parent_data(dip, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_destroy(&pdp->xd_ndi_lk);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_destroy(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(pdp, sizeof (*pdp));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Bind the event channel for this device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Currently we only support one evtchn per device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t oeid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int r;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_evtchn == INVALID_EVTCHN);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_devclass == XEN_CONSOLE) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_evtchn = xen_info->console.domU.evtchn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_evtchn = INVALID_EVTCHN;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev oeid = pdp->xd_xsdev.otherend_id;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (oeid == (domid_t)-1) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_dev_error(dip, r, "bind event channel");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifndef XPV_HVM_DRIVER
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Allocate an event channel for this device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Currently we only support one evtchn per device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_alloc_evtchn(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t oeid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int rv;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_evtchn == INVALID_EVTCHN);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_devclass == XEN_CONSOLE) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_evtchn = xen_info->console.domU.evtchn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_evtchn = INVALID_EVTCHN;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev oeid = pdp->xd_xsdev.otherend_id;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (oeid == (domid_t)-1) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_dev_error(dip, rv, "bind event channel");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifndef XPV_HVM_DRIVER
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Unbind the event channel for this device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Currently we only support one evtchn per device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_free_evtchn(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_evtchn != INVALID_EVTCHN) {
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifndef XPV_HVM_DRIVER
843e19887f64dde75055cf8842fc4db2171eff45johnlev ec_unbind_irq(pdp->xd_ispec.intrspec_vec);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_ispec.intrspec_vec = 0;
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj pdp->xd_evtchn = INVALID_EVTCHN;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_evt_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifndef XPV_HVM_DRIVER
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Map an inter-domain communication ring for a virtual device.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is used by backend drivers.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
843e19887f64dde75055cf8842fc4db2171eff45johnlev grant_ref_t gref, xendev_ring_t **ringpp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t oeid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev gnttab_map_grant_ref_t mapop;
843e19887f64dde75055cf8842fc4db2171eff45johnlev gnttab_unmap_grant_ref_t unmapop;
843e19887f64dde75055cf8842fc4db2171eff45johnlev caddr_t ringva;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_acc_hdl_t *ap;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_acc_impl_t *iap;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_ring_t *ring;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char errstr[] = "mapping in ring buffer";
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev oeid = xvdi_get_oeid(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* alloc va in backend dom for ring buffer */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ringva = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, 0, 0, 0, VM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* map in ring page */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson hat_prepare_mapping(kas.a_hat, ringva, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mapop.host_addr = (uint64_t)(uintptr_t)ringva;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mapop.flags = GNTMAP_host_map;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mapop.ref = gref;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mapop.dom = oeid;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson err = xen_map_gref(GNTTABOP_map_grant_ref, &mapop, 1, B_FALSE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_fatal_error(dip, err, errstr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto errout1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mapop.status != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_fatal_error(dip, err, errstr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto errout2;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_vaddr = ringva;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_grant_hdl = mapop.handle;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_gref = gref;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * init an acc handle and associate it w/ this ring
843e19887f64dde75055cf8842fc4db2171eff45johnlev * this is only for backend drivers. we get the memory by calling
843e19887f64dde75055cf8842fc4db2171eff45johnlev * vmem_xalloc(), instead of calling any ddi function, so we have
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to init an acc handle by ourselves
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap = impl_acc_hdl_get(ring->xr_acc_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_vers = VERS_ACCHDL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_dip = dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_xfermodes = DDI_DMA_CONSISTENT;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_acc = xendev_dc_accattr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iap = (ddi_acc_impl_t *)ap->ah_platform_private;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR;
843e19887f64dde75055cf8842fc4db2171eff45johnlev impl_acc_hdl_init(ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_offset = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_len = (off_t)PAGESIZE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ap->ah_addr = ring->xr_vaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* init backend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_ring_init_back_ring(ring, nentry, entrysize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev *ringpp = ring;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnleverrout2:
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* unmap ring page */
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.host_addr = (uint64_t)(uintptr_t)ringva;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.handle = ring->xr_grant_hdl;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.dev_bus_addr = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hat_release_mapping(kas.a_hat, ringva);
843e19887f64dde75055cf8842fc4db2171eff45johnleverrout1:
843e19887f64dde75055cf8842fc4db2171eff45johnlev vmem_xfree(heap_arena, ringva, PAGESIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(ring, sizeof (xendev_ring_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Unmap a ring for a virtual device.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is used by backend drivers.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_unmap_ring(xendev_ring_t *ring)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev gnttab_unmap_grant_ref_t unmapop;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT((ring != NULL) && (ring->xr_vaddr != NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev impl_acc_hdl_free(ring->xr_acc_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.handle = ring->xr_grant_hdl;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.dev_bus_addr = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hat_release_mapping(kas.a_hat, ring->xr_vaddr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev vmem_xfree(heap_arena, ring->xr_vaddr, PAGESIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(ring, sizeof (xendev_ring_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif /* XPV_HVM_DRIVER */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Re-initialise an inter-domain communications ring for the backend domain.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * ring will be re-initialized after re-grant succeed
843e19887f64dde75055cf8842fc4db2171eff45johnlev * ring will be freed if fails to re-grant access to backend domain
843e19887f64dde75055cf8842fc4db2171eff45johnlev * so, don't keep useful data in the ring
843e19887f64dde75055cf8842fc4db2171eff45johnlev * used only in frontend driver
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev paddr_t rpaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev maddr_t rmaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT((ringp != NULL) && (ringp->xr_paddr != 0));
843e19887f64dde75055cf8842fc4db2171eff45johnlev rpaddr = ringp->xr_paddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? rpaddr : pa_to_ma(rpaddr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev gnttab_grant_foreign_access_ref(ringp->xr_gref, xvdi_get_oeid(dip),
843e19887f64dde75055cf8842fc4db2171eff45johnlev rmaddr >> PAGESHIFT, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev *gref = ringp->xr_gref;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* init frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_ring_init_sring(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents,
843e19887f64dde75055cf8842fc4db2171eff45johnlev ringp->xr_entry_size);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * allocate Xen inter-domain communications ring for Xen virtual devices
843e19887f64dde75055cf8842fc4db2171eff45johnlev * used only in frontend driver
843e19887f64dde75055cf8842fc4db2171eff45johnlev * if *ringpp is not NULL, we'll simply re-init it
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
843e19887f64dde75055cf8842fc4db2171eff45johnlev grant_ref_t *gref, xendev_ring_t **ringpp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_ring_t *ring;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_cookie_t dma_cookie;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uint_t ncookies;
843e19887f64dde75055cf8842fc4db2171eff45johnlev grant_ref_t ring_gref;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t oeid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev maddr_t rmaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (*ringpp) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_reinit_ring(dip, gref, *ringpp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev *ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev oeid = xvdi_get_oeid(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Allocate page for this ring buffer
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP,
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, &ring->xr_dma_hdl) != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_dma_mem_alloc(ring->xr_dma_hdl, PAGESIZE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_free_handle(&ring->xr_dma_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_dma_addr_bind_handle(ring->xr_dma_hdl, NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_mem_free(&ring->xr_acc_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_vaddr = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_free_handle(&ring->xr_dma_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ncookies == 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_paddr = dma_cookie.dmac_laddress;
843e19887f64dde75055cf8842fc4db2171eff45johnlev rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr :
843e19887f64dde75055cf8842fc4db2171eff45johnlev pa_to_ma(ring->xr_paddr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((ring_gref = gnttab_grant_foreign_access(oeid,
843e19887f64dde75055cf8842fc4db2171eff45johnlev rmaddr >> PAGESHIFT, 0)) == (grant_ref_t)-1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_dma_unbind_handle(ring->xr_dma_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_mem_free(&ring->xr_acc_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring->xr_vaddr = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_free_handle(&ring->xr_dma_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev *gref = ring->xr_gref = ring_gref;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* init frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_ring_init_sring(ring);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_ring_init_front_ring(ring, nentry, entrysize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnleverr:
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(ring, sizeof (xendev_ring_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Release ring buffers allocated for Xen devices
843e19887f64dde75055cf8842fc4db2171eff45johnlev * used for frontend driver
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_free_ring(xendev_ring_t *ring)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT((ring != NULL) && (ring->xr_vaddr != NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) gnttab_end_foreign_access_ref(ring->xr_gref, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_dma_unbind_handle(ring->xr_dma_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_mem_free(&ring->xr_acc_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_dma_free_handle(&ring->xr_dma_hdl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(ring, sizeof (xendev_ring_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevdev_info_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass,
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t dom, int vdev)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t backend;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char xsnamebuf[TYPICALMAXPATHLEN];
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *type, *node = NULL, *xsname = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int tlen;
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(DEVI_BUSY_OWNED(parent));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev backend = (dom != DOMID_SELF);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xdcp = i_xvdi_devclass2cfg(devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xdcp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev if (vdev != VDEV_NOXS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!backend) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
843e19887f64dde75055cf8842fc4db2171eff45johnlev "%s/%d", xdcp->xs_path_fe, vdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xsname = xsnamebuf;
843e19887f64dde75055cf8842fc4db2171eff45johnlev node = xdcp->node_fe;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
843e19887f64dde75055cf8842fc4db2171eff45johnlev "%s/%d/%d", xdcp->xs_path_be, dom, vdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xsname = xsnamebuf;
843e19887f64dde75055cf8842fc4db2171eff45johnlev node = xdcp->node_be;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev node = xdcp->node_fe;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Must have a driver to use. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (node == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We need to check the state of this device before we go
843e19887f64dde75055cf8842fc4db2171eff45johnlev * further, otherwise we'll end up with a dead loop if
843e19887f64dde75055cf8842fc4db2171eff45johnlev * anything goes wrong.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xsname != NULL) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (xenbus_read_driver_state(xsname) >= XenbusStateClosing))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Driver binding uses the compatible property _before_ the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * node name, so we set the node name to the 'model' of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * device (i.e. 'xnb' or 'xdb') and, if 'type' is present,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * encode both the model and the type in a compatible property
843e19887f64dde75055cf8842fc4db2171eff45johnlev * (i.e. 'xnb,netfront' or 'xnb,SUNW_mac'). This allows a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * driver binding based on the <model,type> pair _before_ a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * binding based on the node name.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xsname != NULL) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen)
843e19887f64dde75055cf8842fc4db2171eff45johnlev == 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t clen;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *c[1];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev clen = strlen(node) + strlen(type) + 2;
843e19887f64dde75055cf8842fc4db2171eff45johnlev c[0] = kmem_alloc(clen, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(c[0], clen, "%s,%s", node, type);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_string_array(DDI_DEV_T_NONE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev dip, "compatible", (char **)c, 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(c[0], clen);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(type, tlen);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "devclass", devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "domain", dom);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vdev", vdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i_ddi_devi_attached(parent))
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev ret = ndi_devi_online(dip, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev ret = ndi_devi_bind_driver(dip, 0);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev if (ret != NDI_SUCCESS)
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xendev_enum_class()
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
d798155d7bf57b12488188910d934e56422d1d3emrj boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info);
d798155d7bf57b12488188910d934e56422d1d3emrj boolean_t domU = !dom0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xdcp = i_xvdi_devclass2cfg(devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xdcp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
d798155d7bf57b12488188910d934e56422d1d3emrj if (dom0 && !(xdcp->flags & XD_DOM_ZERO))
d798155d7bf57b12488188910d934e56422d1d3emrj return;
d798155d7bf57b12488188910d934e56422d1d3emrj
d798155d7bf57b12488188910d934e56422d1d3emrj if (domU && !(xdcp->flags & XD_DOM_GUEST))
d798155d7bf57b12488188910d934e56422d1d3emrj return;
d798155d7bf57b12488188910d934e56422d1d3emrj
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xdcp->xsdev == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev int circ;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Don't need to probe this kind of device from the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * store, just create one if it doesn't exist.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_enter(parent, &circ);
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev if (xvdi_find_dev(parent, devclass, DOMID_SELF, VDEV_NOXS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_create_dev(parent, devclass,
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev DOMID_SELF, VDEV_NOXS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_exit(parent, circ);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Probe this kind of device from the store, both
843e19887f64dde75055cf8842fc4db2171eff45johnlev * frontend and backend.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (xdcp->node_fe != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_xvdi_enum_fe(parent, xdcp);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (xdcp->node_be != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_xvdi_enum_be(parent, xdcp);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xendev_enum_all()
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_enum_all(dev_info_t *parent, boolean_t store_unavailable)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Dom0 relies on watchpoints to create non-soft
843e19887f64dde75055cf8842fc4db2171eff45johnlev * devices - don't attempt to iterate over the store.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (dom0 && (xdcp->xsdev != NULL))
843e19887f64dde75055cf8842fc4db2171eff45johnlev continue;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If the store is not yet available, don't attempt to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * iterate.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (store_unavailable && (xdcp->xsdev != NULL))
843e19887f64dde75055cf8842fc4db2171eff45johnlev continue;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_enum_class(parent, xdcp->devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_devclass_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_nodename_to_devclass(char *nodename)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This relies on the convention that variants of a base
843e19887f64dde75055cf8842fc4db2171eff45johnlev * driver share the same prefix and that there are no drivers
843e19887f64dde75055cf8842fc4db2171eff45johnlev * which share a common prefix with the name of any other base
843e19887f64dde75055cf8842fc4db2171eff45johnlev * drivers.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * So for a base driver 'xnb' (which is the name listed in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xdci) the variants all begin with the string 'xnb' (in fact
843e19887f64dde75055cf8842fc4db2171eff45johnlev * they are 'xnbe', 'xnbo' and 'xnbu') and there are no other
843e19887f64dde75055cf8842fc4db2171eff45johnlev * base drivers which have the prefix 'xnb'.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(nodename != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (((xdcp->node_fe != NULL) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (strncmp(nodename, xdcp->node_fe,
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen(xdcp->node_fe)) == 0)) ||
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((xdcp->node_be != NULL) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (strncmp(nodename, xdcp->node_be,
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen(xdcp->node_be)) == 0)))
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xdcp->devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (XEN_INVAL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_devclass_ipl(xendev_devclass_t devclass)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xdcp = i_xvdi_devclass2cfg(devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xdcp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xdcp->xd_ipl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Determine if a devinfo instance exists of a particular device
843e19887f64dde75055cf8842fc4db2171eff45johnlev * class, domain and xenstore virtual device number.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevdev_info_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_find_dev(dev_info_t *parent, xendev_devclass_t devclass,
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t dom, int vdev)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(DEVI_BUSY_OWNED(parent));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (devclass) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_CONSOLE:
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_XENBUS:
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_DOMCAPS:
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_BALLOON:
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_EVTCHN:
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_PRIVCMD:
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Console and soft devices have no vdev. */
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev vdev = VDEV_NOXS;
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (dip = ddi_get_child(parent); dip != NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev dip = ddi_get_next_sibling(dip)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev int *vdevnump, *domidp, *devclsp, vdevnum;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uint_t ndomid, nvdevnum, ndevcls;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_devclass_t devcls;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t domid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_DONTPASS, "domain", &domidp, &ndomid) !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev continue;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ndomid == 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid = (domid_t)*domidp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_prop_free(domidp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_DONTPASS, "vdev", &vdevnump, &nvdevnum) !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev continue;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(nvdevnum == 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev vdevnum = *vdevnump;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_prop_free(vdevnump);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_PROP_DONTPASS, "devclass", &devclsp,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &ndevcls) != DDI_PROP_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev continue;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ndevcls == 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev devcls = (xendev_devclass_t)*devclsp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_prop_free(devclsp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid = pdp->xd_domain;
843e19887f64dde75055cf8842fc4db2171eff45johnlev vdevnum = pdp->xd_vdevnum;
843e19887f64dde75055cf8842fc4db2171eff45johnlev devcls = pdp->xd_devclass;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((domid == dom) && (vdevnum == vdev) && (devcls == devclass))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_get_evtchn(dev_info_t *xdip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (pdp->xd_evtchn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_get_vdevnum(dev_info_t *xdip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (pdp->xd_vdevnum);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevchar *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_get_xsname(dev_info_t *xdip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((char *)(pdp->xd_xsdev.nodename));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevchar *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_get_oename(dev_info_t *xdip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_devclass == XEN_CONSOLE)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((char *)(pdp->xd_xsdev.otherend));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstruct xenbus_device *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_get_xsd(dev_info_t *xdip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (&pdp->xd_xsdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevdomid_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_get_oeid(dev_info_t *xdip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_devclass == XEN_CONSOLE)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((domid_t)-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((domid_t)(pdp->xd_xsdev.otherend_id));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_dev_error(dev_info_t *dip, int errno, char *errstr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xenbus_dev_error(&pdp->xd_xsdev, errno, errstr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_fatal_error(dev_info_t *dip, int errno, char *errstr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xenbus_dev_fatal(&pdp->xd_xsdev, errno, errstr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_oestate_handler(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen i_oestate_evt_t *evt = (i_oestate_evt_t *)arg;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen dev_info_t *dip = evt->dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev XenbusState oestate = pdp->xd_xsdev.otherend_state;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen XenbusState curr_oestate = evt->state;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_eventcookie_t evc;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen /* evt is alloc'ed in i_xvdi_oestate_cb */
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen kmem_free(evt, sizeof (i_oestate_evt_t));
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen /*
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen * If the oestate we're handling is not the latest one,
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen * it does not make any sense to continue handling it.
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen */
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen if (curr_oestate != oestate)
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen return;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_oe_ehid != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* send notification to driver */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_get_eventcookie(dip, XS_OE_STATE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &evc) == DDI_SUCCESS) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_post_event(dip, dip, evc, &oestate);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * take default action, if driver hasn't registered its
843e19887f64dde75055cf8842fc4db2171eff45johnlev * event handler yet
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (oestate == XenbusStateClosing) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_switch_state(dip, XBT_NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XenbusStateClosed);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (oestate == XenbusStateClosed) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_switch_state(dip, XBT_NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XenbusStateClosed);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_post_event(dip, XEN_HP_REMOVE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We'll try to remove the devinfo node of this device if the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * other end has closed.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (oestate == XenbusStateClosed)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_taskq_dispatch(DEVI(ddi_get_parent(dip))->devi_taskq,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_offline_device, dip, DDI_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_hpstate_handler(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip = (dev_info_t *)arg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_eventcookie_t evc;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *hp_status;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int hpl;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((ddi_get_eventcookie(dip, XS_HP_STATE, &evc) == DDI_SUCCESS) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "",
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void *)&hp_status, &hpl) == 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_hotplug_state_t new_state = Unrecognized;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (strcmp(hp_status, "connected") == 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev new_state = Connected;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_post_event(dip, dip, evc, &new_state);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(hp_status, hpl);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_notify_oe(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_evtchn != INVALID_EVTCHN);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ec_notify_via_evtchn(pdp->xd_evtchn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_bepath_cb(struct xenbus_watch *w, const char **vec, unsigned int len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip = (dev_info_t *)w->dev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *be = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int bel;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(len > XS_WATCH_PATH);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(vec[XS_WATCH_PATH] != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If the backend is not the same as that we already stored,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * re-set our watch for its' state.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xenbus_read(XBT_NULL, "", vec[XS_WATCH_PATH], (void *)be, &bel)
843e19887f64dde75055cf8842fc4db2171eff45johnlev == 0) && (strcmp(be, pdp->xd_xsdev.otherend) != 0))
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) i_xvdi_add_watch_oestate(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (be != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(bel > 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(be, bel);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczstatic void
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_free(xd_xb_watches_t *xxwp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(xxwp->xxw_ref == 0);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz strfree((char *)xxwp->xxw_watch.node);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz kmem_free(xxwp, sizeof (*xxwp));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczstatic void
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_release(xd_xb_watches_t *xxwp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(MUTEX_HELD(&xxwp->xxw_xppd->xd_ndi_lk));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(xxwp->xxw_ref > 0);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (--xxwp->xxw_ref == 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_free(xxwp);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczstatic void
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_hold(xd_xb_watches_t *xxwp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(MUTEX_HELD(&xxwp->xxw_xppd->xd_ndi_lk));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(xxwp->xxw_ref > 0);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxwp->xxw_ref++;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczstatic void
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_cb_tq(void *arg)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xd_xb_watches_t *xxwp = (xd_xb_watches_t *)arg;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz dev_info_t *dip = (dev_info_t *)xxwp->xxw_watch.dev;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = xxwp->xxw_xppd;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxwp->xxw_cb(dip, xxwp->xxw_watch.node, xxwp->xxw_arg);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_enter(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_release(xxwp);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczstatic void
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_cb(struct xenbus_watch *w, const char **vec, unsigned int len)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz dev_info_t *dip = (dev_info_t *)w->dev;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = ddi_get_parent_data(dip);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xd_xb_watches_t *xxwp;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(len > XS_WATCH_PATH);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(vec[XS_WATCH_PATH] != NULL);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_enter(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz for (xxwp = list_head(&pdp->xd_xb_watches); xxwp != NULL;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxwp = list_next(&pdp->xd_xb_watches, xxwp)) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (w == &xxwp->xxw_watch)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz break;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (xxwp == NULL) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_hold(xxwp);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) ddi_taskq_dispatch(pdp->xd_xb_watch_taskq,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_cb_tq, xxwp, DDI_SLEEP);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz/*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Any watches registered with xvdi_add_xb_watch_handler() get torn down during
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * a suspend operation. So if a frontend driver want's to use these interfaces,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * that driver is responsible for re-registering any watches it had before
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * the suspend operation.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczint
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxvdi_add_xb_watch_handler(dev_info_t *dip, const char *dir, const char *node,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xvdi_xb_watch_cb_t cb, void *arg)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = ddi_get_parent_data(dip);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xd_xb_watches_t *xxw_new, *xxwp;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz char *path;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz int n;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT((dip != NULL) && (dir != NULL) && (node != NULL));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(cb != NULL);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz n = strlen(dir) + 1 + strlen(node) + 1;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz path = kmem_zalloc(n, KM_SLEEP);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) strlcat(path, dir, n);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) strlcat(path, "/", n);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) strlcat(path, node, n);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT((strlen(path) + 1) == n);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new = kmem_zalloc(sizeof (*xxw_new), KM_SLEEP);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_ref = 1;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_watch.node = path;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_watch.callback = i_xvdi_xb_watch_cb;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_watch.dev = (struct xenbus_device *)dip;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_xppd = pdp;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_cb = cb;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new->xxw_arg = arg;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_enter(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz /*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * If this is the first watch we're setting up, create a taskq
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * to dispatch watch events and initialize the watch list.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (pdp->xd_xb_watch_taskq == NULL) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz char tq_name[TASKQ_NAMELEN];
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(list_is_empty(&pdp->xd_xb_watches));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) snprintf(tq_name, sizeof (tq_name),
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz "%s_xb_watch_tq", ddi_get_name(dip));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if ((pdp->xd_xb_watch_taskq = ddi_taskq_create(dip, tq_name,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_release(xxw_new);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (DDI_FAILURE);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz /* Don't allow duplicate watches to be registered */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz for (xxwp = list_head(&pdp->xd_xb_watches); xxwp != NULL;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxwp = list_next(&pdp->xd_xb_watches, xxwp)) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(strcmp(xxwp->xxw_watch.node, path) != 0);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (strcmp(xxwp->xxw_watch.node, path) != 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz continue;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_release(xxw_new);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (DDI_FAILURE);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (register_xenbus_watch(&xxw_new->xxw_watch) != 0) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (list_is_empty(&pdp->xd_xb_watches)) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ddi_taskq_destroy(pdp->xd_xb_watch_taskq);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz pdp->xd_xb_watch_taskq = NULL;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_release(xxw_new);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (DDI_FAILURE);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz list_insert_head(&pdp->xd_xb_watches, xxw_new);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (DDI_SUCCESS);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz/*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Tear down all xenbus watches registered by the specified dip.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczvoid
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxvdi_remove_xb_watch_handlers(dev_info_t *dip)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = ddi_get_parent_data(dip);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xd_xb_watches_t *xxwp;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ddi_taskq_t *tq;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_enter(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz while ((xxwp = list_remove_head(&pdp->xd_xb_watches)) != NULL) {
df889519a436e455c9229b6d19145998ff836008Mark Johnson mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz unregister_xenbus_watch(&xxwp->xxw_watch);
df889519a436e455c9229b6d19145998ff836008Mark Johnson mutex_enter(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz i_xvdi_xb_watch_release(xxwp);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz }
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(list_is_empty(&pdp->xd_xb_watches));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz /*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * We can't hold xd_ndi_lk while we destroy the xd_xb_watch_taskq.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * This is because if there are currently any executing taskq threads,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * we will block until they are finished, and to finish they need
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * to aquire xd_ndi_lk in i_xvdi_xb_watch_cb_tq() so they can release
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * their reference on their corresponding xxwp structure.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz tq = pdp->xd_xb_watch_taskq;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz pdp->xd_xb_watch_taskq = NULL;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (tq != NULL)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ddi_taskq_destroy(tq);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_add_watch_oestate(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.nodename != NULL);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson ASSERT(mutex_owned(&pdp->xd_ndi_lk));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Create taskq for delivering other end state change event to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * this device later.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Set nthreads to 1 to make sure that events can be delivered
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in order.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Note: It is _not_ guaranteed that driver can see every
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xenstore change under the path that it is watching. If two
843e19887f64dde75055cf8842fc4db2171eff45johnlev * changes happen consecutively in a very short amount of
843e19887f64dde75055cf8842fc4db2171eff45johnlev * time, it is likely that the driver will see only the last
843e19887f64dde75055cf8842fc4db2171eff45johnlev * one.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_oe_taskq == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((pdp->xd_oe_taskq = ddi_taskq_create(dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "xendev_oe_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Watch for changes to the XenbusState of otherend.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.otherend_state = XenbusStateUnknown;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.otherend_changed = i_xvdi_oestate_cb;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (talk_to_otherend(&pdp->xd_xsdev) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watch_oestate(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_rem_watch_oestate(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_device *dev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson ASSERT(mutex_owned(&pdp->xd_ndi_lk));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev = &pdp->xd_xsdev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Unwatch for changes to XenbusState of otherend */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (dev->otherend_watch.node != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev unregister_xenbus_watch(&dev->otherend_watch);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* make sure no event handler is running */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_oe_taskq != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_taskq_destroy(pdp->xd_oe_taskq);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_oe_taskq = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* clean up */
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev->otherend_state = XenbusStateUnknown;
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev->otherend_id = (domid_t)-1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (dev->otherend_watch.node != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free((void *)dev->otherend_watch.node,
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen(dev->otherend_watch.node) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev->otherend_watch.node = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (dev->otherend != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev->otherend = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_add_watch_hpstate(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.frontend == 0);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson ASSERT(mutex_owned(&pdp->xd_ndi_lk));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Create taskq for delivering hotplug status change event to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * this device later.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Set nthreads to 1 to make sure that events can be delivered
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in order.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Note: It is _not_ guaranteed that driver can see every
843e19887f64dde75055cf8842fc4db2171eff45johnlev * hotplug status change under the path that it is
843e19887f64dde75055cf8842fc4db2171eff45johnlev * watching. If two changes happen consecutively in a very
843e19887f64dde75055cf8842fc4db2171eff45johnlev * short amount of time, it is likely that the driver only
843e19887f64dde75055cf8842fc4db2171eff45johnlev * sees the last one.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_hp_taskq == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((pdp->xd_hp_taskq = ddi_taskq_create(dip,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "xendev_hp_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_hp_watch.node == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.nodename != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev len = strlen(pdp->xd_xsdev.nodename) +
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen("/hotplug-status") + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = kmem_alloc(len, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(path, len, "%s/hotplug-status",
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.nodename);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_watch.node = path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_watch.callback = i_xvdi_hpstate_cb;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_watch.dev = (struct xenbus_device *)dip; /* yuck! */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (register_xenbus_watch(&pdp->xd_hp_watch) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watch_hpstate(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_rem_watch_hpstate(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.frontend == 0);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson ASSERT(mutex_owned(&pdp->xd_ndi_lk));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Unwatch for changes to "hotplug-status" node for backend device. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_hp_watch.node != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev unregister_xenbus_watch(&pdp->xd_hp_watch);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Make sure no event handler is running. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_hp_taskq != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_taskq_destroy(pdp->xd_hp_taskq);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_taskq = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Clean up. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_hp_watch.node != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free((void *)pdp->xd_hp_watch.node,
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen(pdp->xd_hp_watch.node) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_watch.node = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_add_watches(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i_xvdi_add_watch_oestate(dip) != DDI_SUCCESS) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_xsdev.frontend == 1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Frontend devices must watch for the backend path
843e19887f64dde75055cf8842fc4db2171eff45johnlev * changing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i_xvdi_add_watch_bepath(dip) != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto unwatch_and_fail;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Backend devices must watch for hotplug events.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i_xvdi_add_watch_hpstate(dip) != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto unwatch_and_fail;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevunwatch_and_fail:
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watch_oestate(dip);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_rem_watches(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watch_oestate(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_xsdev.frontend == 1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watch_bepath(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watch_hpstate(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xvdi_remove_xb_watch_handlers(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_add_watch_bepath(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.frontend == 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Frontend devices need to watch for the backend path changing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_bepath_watch.node == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.nodename != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev len = strlen(pdp->xd_xsdev.nodename) + strlen("/backend") + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = kmem_alloc(len, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(path, len, "%s/backend",
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.nodename);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_bepath_watch.node = path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_bepath_watch.callback = i_xvdi_bepath_cb;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_bepath_watch.dev = (struct xenbus_device *)dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (register_xenbus_watch(&pdp->xd_bepath_watch) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_bepath_watch.node = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_rem_watch_bepath(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.frontend == 1);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson ASSERT(mutex_owned(&pdp->xd_ndi_lk));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_bepath_watch.node != NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev unregister_xenbus_watch(&pdp->xd_bepath_watch);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free((void *)(pdp->xd_bepath_watch.node),
843e19887f64dde75055cf8842fc4db2171eff45johnlev strlen(pdp->xd_bepath_watch.node) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_bepath_watch.node = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_switch_state(dev_info_t *dip, xenbus_transaction_t xbt,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XenbusState newState)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int rv;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev XVDI_DPRINTF(XVDI_DBG_STATE,
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen "xvdi_switch_state: %s@%s's xenbus state moves to %d\n",
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen ddi_binding_name(dip) == NULL ? "null" : ddi_binding_name(dip),
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen ddi_get_name_addr(dip) == NULL ? "null" : ddi_get_name_addr(dip),
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen newState);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rv = xenbus_switch_state(&pdp->xd_xsdev, xbt, newState);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (rv > 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "xvdi_switch_state: change state failed");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (rv);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Notify hotplug script running in userland
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_post_event(dev_info_t *dip, xendev_hotplug_cmd_t hpc)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev nvlist_t *attr_list = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev sysevent_id_t eid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char devname[256]; /* XXPV dme: ? */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xdcp = i_xvdi_devclass2cfg(pdp->xd_devclass);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xdcp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(devname, sizeof (devname) - 1, "%s%d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_driver_name(dip), ddi_get_instance(dip));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_NOSLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_int32(attr_list, "domain", pdp->xd_domain);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_int32(attr_list, "vdev", pdp->xd_vdevnum);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_string(attr_list, "devclass", xdcp->xsdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_string(attr_list, "device", devname);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_string(attr_list, "fob",
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((pdp->xd_xsdev.frontend == 1) ? "frontend" : "backend"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (hpc) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_HP_ADD:
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev",
843e19887f64dde75055cf8842fc4db2171eff45johnlev "add", attr_list, &eid, DDI_NOSLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case XEN_HP_REMOVE:
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev",
843e19887f64dde75055cf8842fc4db2171eff45johnlev "remove", attr_list, &eid, DDI_NOSLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = DDI_FAILURE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto failure;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevfailure:
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(attr_list);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_probe_path_cb(struct xenbus_watch *w, const char **vec,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xendev_dip == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xendev_dip = ddi_find_devinfo("xpvd", -1, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = i_ddi_strdup((char *)vec[XS_WATCH_PATH], KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_taskq_dispatch(DEVI(xendev_dip)->devi_taskq,
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_probe_path_handler, (void *)path, DDI_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_watch_device(char *path)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_watch *w;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(path != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev w = kmem_zalloc(sizeof (*w), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev w->node = path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev w->callback = &i_xvdi_probe_path_cb;
843e19887f64dde75055cf8842fc4db2171eff45johnlev w->dev = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (register_xenbus_watch(w) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "i_xvdi_watch_device: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "cannot set watch on %s", path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(w, sizeof (*w));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_watch_devices(int newstate)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int devclass;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Watch for devices being created in the store.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (newstate == XENSTORE_DOWN)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (devclass = 0; devclass < NXDC; devclass++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xdci[devclass].xs_path_fe != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_watch_device(xdci[devclass].xs_path_fe);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xdci[devclass].xs_path_be != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_watch_device(xdci[devclass].xs_path_be);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Iterate over the store looking for backend devices to create.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_enum_be(dev_info_t *parent, i_xd_cfg_t *xdcp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char **domains;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int ndomains;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ldomains, i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((domains = xenbus_directory(XBT_NULL, xdcp->xs_path_be, "",
843e19887f64dde75055cf8842fc4db2171eff45johnlev &ndomains)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, ldomains = 0; i < ndomains; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ldomains += strlen(domains[i]) + 1 + sizeof (char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_enum_worker(parent, xdcp, domains[i]);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(domains, ldomains);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Iterate over the store looking for frontend devices to create.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_enum_fe(dev_info_t *parent, i_xd_cfg_t *xdcp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_enum_worker(parent, xdcp, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_enum_worker(dev_info_t *parent, i_xd_cfg_t *xdcp,
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *domain)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path, *domain_path, *ep;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char **devices;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int ndevices;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ldevices, j, circ;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t dom;
6e24ea8fbc65bc61c4dc401c14061538301f2521edp long tmplong;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (domain == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev dom = DOMID_SELF;
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = xdcp->xs_path_fe;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domain_path = "";
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
6e24ea8fbc65bc61c4dc401c14061538301f2521edp (void) ddi_strtol(domain, &ep, 0, &tmplong);
6e24ea8fbc65bc61c4dc401c14061538301f2521edp dom = tmplong;
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = xdcp->xs_path_be;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domain_path = domain;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((devices = xenbus_directory(XBT_NULL, path, domain_path,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &ndevices)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (j = 0, ldevices = 0; j < ndevices; j++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev int vdev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ldevices += strlen(devices[j]) + 1 + sizeof (char *);
6e24ea8fbc65bc61c4dc401c14061538301f2521edp (void) ddi_strtol(devices[j], &ep, 0, &tmplong);
6e24ea8fbc65bc61c4dc401c14061538301f2521edp vdev = tmplong;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_enter(parent, &circ);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
6e24ea8fbc65bc61c4dc401c14061538301f2521edp if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_create_dev(parent, xdcp->devclass,
843e19887f64dde75055cf8842fc4db2171eff45johnlev dom, vdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_exit(parent, circ);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(devices, ldevices);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Leaf drivers should call this in their detach() routine during suspend.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_suspend(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_rem_watches(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Leaf drivers should call this in their attach() routine during resume.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_resume(dev_info_t *dip)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (i_xvdi_add_watches(dip));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Add event handler for the leaf driver
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to handle event triggered by the change in xenstore
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_add_event_handler(dev_info_t *dip, char *name,
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson void (*evthandler)(dev_info_t *, ddi_eventcookie_t, void *, void *),
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_eventcookie_t ecv;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_callback_id_t *cbid;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson boolean_t call_handler;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_oestate_evt_t *evt = NULL;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson XenbusState oestate;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (strcmp(name, XS_OE_STATE) == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_xsdev.otherend != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev cbid = &pdp->xd_oe_ehid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (strcmp(name, XS_HP_STATE) == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pdp->xd_xsdev.frontend == 1) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp->xd_hp_watch.node != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev cbid = &pdp->xd_hp_ehid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Unsupported watch. */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * No event handler provided, take default action to handle
843e19887f64dde75055cf8842fc4db2171eff45johnlev * event.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (evthandler == NULL) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(*cbid == NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_get_eventcookie(dip, name, &ecv) != DDI_SUCCESS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "failed to find %s cookie for %s@%s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev name, ddi_get_name(dip), ddi_get_name_addr(dip));
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (ddi_add_event_handler(dip, ecv, evthandler, arg, cbid)
843e19887f64dde75055cf8842fc4db2171eff45johnlev != DDI_SUCCESS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "failed to add %s event handler for %s@%s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev name, ddi_get_name(dip), ddi_get_name_addr(dip));
843e19887f64dde75055cf8842fc4db2171eff45johnlev *cbid = NULL;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson /*
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson * if we're adding an oe state callback, and the ring has already
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson * transitioned out of Unknown, call the handler after we release
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson * the mutex.
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson call_handler = B_FALSE;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if ((strcmp(name, XS_OE_STATE) == 0) &&
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson (pdp->xd_xsdev.otherend_state != XenbusStateUnknown)) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson oestate = pdp->xd_xsdev.otherend_state;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson call_handler = B_TRUE;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (call_handler) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt = kmem_alloc(sizeof (i_oestate_evt_t), KM_SLEEP);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt->dip = dip;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt->state = oestate;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson (void) ddi_taskq_dispatch(pdp->xd_oe_taskq,
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_xvdi_oestate_handler, (void *)evt, DDI_SLEEP);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Remove event handler for the leaf driver and unwatch xenstore
843e19887f64dde75055cf8842fc4db2171eff45johnlev * so, driver will not be notified when xenstore entry changed later
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_remove_event_handler(dev_info_t *dip, char *name)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t rem_oe = B_FALSE, rem_hp = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_callback_id_t oeid = NULL, hpid = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(pdp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (name == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev rem_oe = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev rem_hp = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (strcmp(name, XS_OE_STATE) == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev rem_oe = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (strcmp(name, XS_HP_STATE) == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev rem_hp = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "event %s not supported, cannot remove", name);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (rem_oe && (pdp->xd_oe_ehid != NULL)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev oeid = pdp->xd_oe_ehid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_oe_ehid = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (rem_hp && (pdp->xd_hp_ehid != NULL)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev hpid = pdp->xd_hp_ehid;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_ehid = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (oeid != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_remove_event_handler(oeid);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (hpid != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_remove_event_handler(hpid);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * common ring interfaces
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define FRONT_RING(_ringp) (&(_ringp)->xr_sring.fr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define BACK_RING(_ringp) (&(_ringp)->xr_sring.br)
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define GET_RING_SIZE(_ringp) RING_SIZE(FRONT_RING(ringp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define GET_RING_ENTRY_FE(_ringp, _idx) \
843e19887f64dde75055cf8842fc4db2171eff45johnlev (FRONT_RING(_ringp)->sring->ring + \
843e19887f64dde75055cf8842fc4db2171eff45johnlev (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1)))
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define GET_RING_ENTRY_BE(_ringp, _idx) \
843e19887f64dde75055cf8842fc4db2171eff45johnlev (BACK_RING(_ringp)->sring->ring + \
843e19887f64dde75055cf8842fc4db2171eff45johnlev (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1)))
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevunsigned int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_avail_slots(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *frp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_be_t *brp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ringp->xr_frontend) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp = FRONT_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_SIZE(ringp) -
843e19887f64dde75055cf8842fc4db2171eff45johnlev (frp->req_prod_pvt - frp->rsp_cons));
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp = BACK_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_SIZE(ringp) -
843e19887f64dde75055cf8842fc4db2171eff45johnlev (brp->rsp_prod_pvt - brp->req_cons));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_has_unconsumed_requests(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_be_t *brp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(!ringp->xr_frontend);
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp = BACK_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((brp->req_cons !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_get32(ringp->xr_acc_hdl, &brp->sring->req_prod)) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((brp->req_cons - brp->rsp_prod_pvt) != RING_SIZE(brp)));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_has_incomp_request(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *frp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ringp->xr_frontend);
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp = FRONT_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (frp->req_prod_pvt !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_has_unconsumed_responses(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *frp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ringp->xr_frontend);
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp = FRONT_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (frp->rsp_cons !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* NOTE: req_event will be increased as needed */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_get_request(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *frp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_be_t *brp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ringp->xr_frontend) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp = FRONT_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!RING_FULL(frp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_FE(ringp, frp->req_prod_pvt++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for backend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp = BACK_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_FINAL_CHECK_FOR_REQUESTS() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xvdi_ring_has_unconsumed_requests(ringp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_BE(ringp, brp->req_cons++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &brp->sring->req_event,
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp->req_cons + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev membar_enter();
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xvdi_ring_has_unconsumed_requests(ringp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_BE(ringp,
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp->req_cons++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_push_request(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev RING_IDX old, new, reqevt;
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *frp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* only frontend should be able to push request */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ringp->xr_frontend);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_PUSH_REQUEST_AND_CHECK_NOTIFY() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp = FRONT_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev old = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_prod);
843e19887f64dde75055cf8842fc4db2171eff45johnlev new = frp->req_prod_pvt;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &frp->sring->req_prod, new);
843e19887f64dde75055cf8842fc4db2171eff45johnlev membar_enter();
843e19887f64dde75055cf8842fc4db2171eff45johnlev reqevt = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_event);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((RING_IDX)(new - reqevt) < (RING_IDX)(new - old));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* NOTE: rsp_event will be increased as needed */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_get_response(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *frp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_be_t *brp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!ringp->xr_frontend) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for backend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp = BACK_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_BE(ringp, brp->rsp_prod_pvt++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp = FRONT_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_FINAL_CHECK_FOR_RESPONSES() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xvdi_ring_has_unconsumed_responses(ringp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_FE(ringp, frp->rsp_cons++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &frp->sring->rsp_event,
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp->rsp_cons + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev membar_enter();
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xvdi_ring_has_unconsumed_responses(ringp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_FE(ringp,
843e19887f64dde75055cf8842fc4db2171eff45johnlev frp->rsp_cons++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_push_response(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev RING_IDX old, new, rspevt;
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_be_t *brp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* only backend should be able to push response */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(!ringp->xr_frontend);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_PUSH_RESPONSE_AND_CHECK_NOTIFY() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev brp = BACK_RING(ringp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev old = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_prod);
843e19887f64dde75055cf8842fc4db2171eff45johnlev new = brp->rsp_prod_pvt;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &brp->sring->rsp_prod, new);
843e19887f64dde75055cf8842fc4db2171eff45johnlev membar_enter();
843e19887f64dde75055cf8842fc4db2171eff45johnlev rspevt = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_event);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((RING_IDX)(new - rspevt) < (RING_IDX)(new - old));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_init_sring(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_acc_handle_t acchdl;
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_sring_t *xsrp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xsrp = (comif_sring_t *)ringp->xr_vaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev acchdl = ringp->xr_acc_hdl;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* shared ring initialization */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(acchdl, &xsrp->req_prod, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(acchdl, &xsrp->rsp_prod, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(acchdl, &xsrp->req_event, 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(acchdl, &xsrp->rsp_event, 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < sizeof (xsrp->pad); i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put8(acchdl, xsrp->pad + i, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_init_front_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_fe_t *xfrp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xfrp = &ringp->xr_sring.fr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xfrp->req_prod_pvt = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xfrp->rsp_cons = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xfrp->nr_ents = nentry;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xfrp->sring = (comif_sring_t *)ringp->xr_vaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ringp->xr_frontend = 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ringp->xr_entry_size = entrysize;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifndef XPV_HVM_DRIVER
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_init_back_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev comif_ring_be_t *xbrp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbrp = &ringp->xr_sring.br;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbrp->rsp_prod_pvt = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbrp->req_cons = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbrp->nr_ents = nentry;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbrp->sring = (comif_sring_t *)ringp->xr_vaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ringp->xr_frontend = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ringp->xr_entry_size = entrysize;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif /* XPV_HVM_DRIVER */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_offline_device(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip = (dev_info_t *)arg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char devname[MAXNAMELEN] = {0};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is currently the only chance to delete a devinfo node, which
843e19887f64dde75055cf8842fc4db2171eff45johnlev * is _not_ always successful.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_deviname(dip, devname);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) devfs_clean(ddi_get_parent(dip), devname + 1, DV_CLEAN_FORCE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_oestate_cb(struct xenbus_device *dev, XenbusState oestate)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip = (dev_info_t *)dev->data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen i_oestate_evt_t *evt = NULL;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson boolean_t call_handler;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen XVDI_DPRINTF(XVDI_DBG_STATE,
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen "i_xvdi_oestate_cb: %s@%s sees oestate change to %d\n",
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen ddi_binding_name(dip) == NULL ? "null" : ddi_binding_name(dip),
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen ddi_get_name_addr(dip) == NULL ? "null" : ddi_get_name_addr(dip),
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen oestate);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson /* only call the handler if our state has changed */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson call_handler = B_FALSE;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_enter(&pdp->xd_ndi_lk);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (dev->otherend_state != oestate) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson dev->otherend_state = oestate;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson call_handler = B_TRUE;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson mutex_exit(&pdp->xd_ndi_lk);
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (call_handler) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson /*
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson * Try to deliver the oestate change event to the dip
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt = kmem_alloc(sizeof (i_oestate_evt_t), KM_SLEEP);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt->dip = dip;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt->state = oestate;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson (void) ddi_taskq_dispatch(pdp->xd_oe_taskq,
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_xvdi_oestate_handler, (void *)evt, DDI_SLEEP);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_hpstate_cb(struct xenbus_watch *w, const char **vec,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *dip = (dev_info_t *)w->dev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xendev_ppd *pdp = ddi_get_parent_data(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen#ifdef DEBUG
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen char *hp_status = NULL;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen unsigned int hpl = 0;
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen (void) xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "",
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen (void *)&hp_status, &hpl);
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen XVDI_DPRINTF(XVDI_DBG_STATE,
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen "i_xvdi_hpstate_cb: %s@%s sees hpstate change to %s\n",
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen ddi_binding_name(dip) == NULL ? "null" : ddi_binding_name(dip),
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen ddi_get_name_addr(dip) == NULL ? "null" : ddi_get_name_addr(dip),
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen hp_status == NULL ? "null" : hp_status);
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen if (hp_status != NULL)
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen kmem_free(hp_status, hpl);
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen#endif /* DEBUG */
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_taskq_dispatch(pdp->xd_hp_taskq,
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_hpstate_handler, (void *)dip, DDI_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_probe_path_handler(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev dev_info_t *parent;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path = arg, *p = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i, vdev, circ;
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xd_cfg_t *xdcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t frontend;
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid_t dom;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, xdcp = &xdci[0]; i < NXDC; i++, xdcp++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xdcp->xs_path_fe != NULL) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (strncmp(path, xdcp->xs_path_fe, strlen(xdcp->xs_path_fe))
843e19887f64dde75055cf8842fc4db2171eff45johnlev == 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev frontend = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev p = path + strlen(xdcp->xs_path_fe);
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xdcp->xs_path_be != NULL) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev (strncmp(path, xdcp->xs_path_be, strlen(xdcp->xs_path_be))
843e19887f64dde75055cf8842fc4db2171eff45johnlev == 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev frontend = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev p = path + strlen(xdcp->xs_path_be);
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (p == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "i_xvdi_probe_path_handler: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "unexpected path prefix in %s", path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto done;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (frontend) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev dom = DOMID_SELF;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (sscanf(p, "/%d/", &vdev) != 1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev XVDI_DPRINTF(XVDI_DBG_PROBE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "cannot parse frontend path %s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto done;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
8793b36b40d14ad0a0fecc97738dc118a928f46cNick Todd if (sscanf(p, "/%hu/%d/", &dom, &vdev) != 2) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev XVDI_DPRINTF(XVDI_DBG_PROBE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "cannot parse backend path %s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto done;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev /*
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev * This is an oxymoron, so indicates a bogus configuration we
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev * must check for.
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev */
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev if (vdev == VDEV_NOXS) {
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev cmn_err(CE_WARN, "i_xvdi_probe_path_handler: "
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev "invalid path %s", path);
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev goto done;
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev }
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev parent = xendev_dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(parent != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_enter(parent, &circ);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev XVDI_DPRINTF(XVDI_DBG_PROBE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: create for %s", path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_create_dev(parent, xdcp->devclass, dom, vdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev XVDI_DPRINTF(XVDI_DBG_PROBE,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: %s already exists", path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_exit(parent, circ);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevdone:
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, strlen(path) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}