843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
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 * CDDL HEADER END
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Xen virtual device driver interfaces
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
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#else /* XPV_HVM_DRIVER */
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif /* XPV_HVM_DRIVER */
06bbe1e05e4f6fd0773ee85a50c0de7adfc4fa06edp#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_oestate_handler(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_hpstate_handler(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_bepath_cb(struct xenbus_watch *, const char **,
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xendev_offline_device(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void i_xvdi_probe_path_handler(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XD_DOM_GUEST 0x02 /* Guest domains (i.e. non-dom0). */
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb",
843e19887f64dde75055cf8842fc4db2171eff45johnlev { XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb",
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson { XEN_BLKTAP, "tap", NULL, "backend/tap", NULL, "xpvtap",
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 * Xen device channel device access and DMA attributes
843e19887f64dde75055cf8842fc4db2171eff45johnlev DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, /* lowest usable address */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, /* flags (reserved) */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif /* DEBUG */
843e19887f64dde75055cf8842fc4db2171eff45johnlev domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz list_create(&pdp->xd_xb_watches, sizeof (xd_xb_watches_t),
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 * devices that do not need to interact with xenstore
843e19887f64dde75055cf8842fc4db2171eff45johnlev * PV devices that need to probe xenstore
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) {
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev /* Don't try to init a dev that may be closing */
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP);
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'.
97869ac5121a555decdf3080d02beef2af506da6jhd (void) snprintf(unitaddr, sizeof (unitaddr), "%d", vdevnum);
97869ac5121a555decdf3080d02beef2af506da6jhd (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unit-address",
97869ac5121a555decdf3080d02beef2af506da6jhd if (xenbus_read(XBT_NULL, xsname, "mac", (void *)&prop_str,
97869ac5121a555decdf3080d02beef2af506da6jhd (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "mac",
97869ac5121a555decdf3080d02beef2af506da6jhd * cache a copy of the otherend name
97869ac5121a555decdf3080d02beef2af506da6jhd * for ease of observeability
97869ac5121a555decdf3080d02beef2af506da6jhd if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, "dev",
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Remove any registered callbacks. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Remove any registered watches. */
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev /* tell other end to close */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Bind the event channel for this device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Currently we only support one evtchn per device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Allocate an event channel for this device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Currently we only support one evtchn per device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Unbind the event channel for this device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Currently we only support one evtchn per device instance.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Map an inter-domain communication ring for a virtual device.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is used by backend drivers.
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
843e19887f64dde75055cf8842fc4db2171eff45johnlev ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
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 /* map in ring page */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson err = xen_map_gref(GNTTABOP_map_grant_ref, &mapop, 1, B_FALSE);
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 ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* init backend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* unmap ring page */
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Unmap a ring for a virtual device.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is used by backend drivers.
843e19887f64dde75055cf8842fc4db2171eff45johnlev unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif /* XPV_HVM_DRIVER */
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
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp)
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 /* init frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents,
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
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
843e19887f64dde75055cf8842fc4db2171eff45johnlev *ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Allocate page for this ring buffer
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) {
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 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr :
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* init frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Release ring buffers allocated for Xen devices
843e19887f64dde75055cf8842fc4db2171eff45johnlev * used for frontend driver
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) gnttab_end_foreign_access_ref(ring->xr_gref, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Must have a driver to use. */
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 (xenbus_read_driver_state(xsname) >= XenbusStateClosing))
843e19887f64dde75055cf8842fc4db2171eff45johnlev ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip);
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 (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen)
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *c[1];
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 * xendev_enum_class()
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Don't need to probe this kind of device from the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * store, just create one if it doesn't exist.
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev if (xvdi_find_dev(parent, devclass, DOMID_SELF, VDEV_NOXS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Probe this kind of device from the store, both
843e19887f64dde75055cf8842fc4db2171eff45johnlev * frontend and backend.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xendev_enum_all()
843e19887f64dde75055cf8842fc4db2171eff45johnlevxendev_enum_all(dev_info_t *parent, boolean_t store_unavailable)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Dom0 relies on watchpoints to create non-soft
843e19887f64dde75055cf8842fc4db2171eff45johnlev * devices - don't attempt to iterate over the store.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If the store is not yet available, don't attempt to
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 * 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 * Determine if a devinfo instance exists of a particular device
843e19887f64dde75055cf8842fc4db2171eff45johnlev * class, domain and xenstore virtual device number.
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_find_dev(dev_info_t *parent, xendev_devclass_t devclass,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Console and soft devices have no vdev. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((domid == dom) && (vdevnum == vdev) && (devcls == devclass))
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_dev_error(dev_info_t *dip, int errno, char *errstr)
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_fatal_error(dev_info_t *dip, int errno, char *errstr)
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen /* evt is alloc'ed in i_xvdi_oestate_cb */
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.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* send notification to driver */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * take default action, if driver hasn't registered its
843e19887f64dde75055cf8842fc4db2171eff45johnlev * event handler yet
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We'll try to remove the devinfo node of this device if the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * other end has closed.
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_taskq_dispatch(DEVI(ddi_get_parent(dip))->devi_taskq,
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((ddi_get_eventcookie(dip, XS_HP_STATE, &evc) == DDI_SUCCESS) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_bepath_cb(struct xenbus_watch *w, const char **vec, unsigned int len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If the backend is not the same as that we already stored,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * re-set our watch for its' state.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xenbus_read(XBT_NULL, "", vec[XS_WATCH_PATH], (void *)be, &bel)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_free(xd_xb_watches_t *xxwp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_release(xd_xb_watches_t *xxwp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(MUTEX_HELD(&xxwp->xxw_xppd->xd_ndi_lk));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_hold(xd_xb_watches_t *xxwp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(MUTEX_HELD(&xxwp->xxw_xppd->xd_ndi_lk));
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 xxwp->xxw_cb(dip, xxwp->xxw_watch.node, xxwp->xxw_arg);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczi_xvdi_xb_watch_cb(struct xenbus_watch *w, const char **vec, unsigned int len)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = ddi_get_parent_data(dip);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz for (xxwp = list_head(&pdp->xd_xb_watches); xxwp != NULL;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxwp = list_next(&pdp->xd_xb_watches, xxwp)) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) ddi_taskq_dispatch(pdp->xd_xb_watch_taskq,
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 Pilatowiczxvdi_add_xb_watch_handler(dev_info_t *dip, const char *dir, const char *node,
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = ddi_get_parent_data(dip);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT((dip != NULL) && (dir != NULL) && (node != NULL));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz xxw_new = kmem_zalloc(sizeof (*xxw_new), KM_SLEEP);
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 * 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 ASSERT(list_is_empty(&pdp->xd_xb_watches));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz (void) snprintf(tq_name, sizeof (tq_name),
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if ((pdp->xd_xb_watch_taskq = ddi_taskq_create(dip, tq_name,
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 ASSERT(strcmp(xxwp->xxw_watch.node, path) != 0);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (strcmp(xxwp->xxw_watch.node, path) != 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (register_xenbus_watch(&xxw_new->xxw_watch) != 0) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ddi_taskq_destroy(pdp->xd_xb_watch_taskq);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz list_insert_head(&pdp->xd_xb_watches, xxw_new);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Tear down all xenbus watches registered by the specified dip.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxvdi_remove_xb_watch_handlers(dev_info_t *dip)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz struct xendev_ppd *pdp = ddi_get_parent_data(dip);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz while ((xxwp = list_remove_head(&pdp->xd_xb_watches)) != NULL) {
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz unregister_xenbus_watch(&xxwp->xxw_watch);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT(list_is_empty(&pdp->xd_xb_watches));
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.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Create taskq for delivering other end state change event to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * this device later.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Set nthreads to 1 to make sure that events can be delivered
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in order.
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 "xendev_oe_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Watch for changes to the XenbusState of otherend.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Unwatch for changes to XenbusState of otherend */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* make sure no event handler is running */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* clean up */
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Create taskq for delivering hotplug status change event to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * this device later.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Set nthreads to 1 to make sure that events can be delivered
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in order.
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 "xendev_hp_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_hp_watch.dev = (struct xenbus_device *)dip; /* yuck! */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (register_xenbus_watch(&pdp->xd_hp_watch) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Unwatch for changes to "hotplug-status" node for backend device. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Make sure no event handler is running. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Clean up. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Frontend devices must watch for the backend path
843e19887f64dde75055cf8842fc4db2171eff45johnlev * changing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Backend devices must watch for hotplug events.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Frontend devices need to watch for the backend path changing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev len = strlen(pdp->xd_xsdev.nodename) + strlen("/backend") + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev pdp->xd_bepath_watch.dev = (struct xenbus_device *)dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (register_xenbus_watch(&pdp->xd_bepath_watch) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_switch_state(dev_info_t *dip, xenbus_transaction_t xbt,
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),
843e19887f64dde75055cf8842fc4db2171eff45johnlev rv = xenbus_switch_state(&pdp->xd_xsdev, xbt, newState);
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "xvdi_switch_state: change state failed");
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Notify hotplug script running in userland
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_post_event(dev_info_t *dip, xendev_hotplug_cmd_t hpc)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(devname, sizeof (devname) - 1, "%s%d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_NOSLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_int32(attr_list, "domain", pdp->xd_domain);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_int32(attr_list, "vdev", pdp->xd_vdevnum);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_string(attr_list, "devclass", xdcp->xsdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = nvlist_add_string(attr_list, "device", devname);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((pdp->xd_xsdev.frontend == 1) ? "frontend" : "backend"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev",
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev",
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_probe_path_cb(struct xenbus_watch *w, const char **vec,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = i_ddi_strdup((char *)vec[XS_WATCH_PATH], KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_taskq_dispatch(DEVI(xendev_dip)->devi_taskq,
843e19887f64dde75055cf8842fc4db2171eff45johnlev i_xvdi_probe_path_handler, (void *)path, DDI_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(w, sizeof (*w));
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Watch for devices being created in the store.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Iterate over the store looking for backend devices to create.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((domains = xenbus_directory(XBT_NULL, xdcp->xs_path_be, "",
843e19887f64dde75055cf8842fc4db2171eff45johnlev ldomains += strlen(domains[i]) + 1 + sizeof (char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Iterate over the store looking for frontend devices to create.
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_enum_worker(dev_info_t *parent, i_xd_cfg_t *xdcp,
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((devices = xenbus_directory(XBT_NULL, path, domain_path,
843e19887f64dde75055cf8842fc4db2171eff45johnlev ldevices += strlen(devices[j]) + 1 + sizeof (char *);
6e24ea8fbc65bc61c4dc401c14061538301f2521edp if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Leaf drivers should call this in their detach() routine during suspend.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Leaf drivers should call this in their attach() routine during resume.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Add event handler for the leaf driver
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to handle event triggered by the change in xenstore
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson void (*evthandler)(dev_info_t *, ddi_eventcookie_t, void *, void *),
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Unsupported watch. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * No event handler provided, take default action to handle
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ddi_get_eventcookie(dip, name, &ecv) != DDI_SUCCESS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "failed to find %s cookie for %s@%s",
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (ddi_add_event_handler(dip, ecv, evthandler, arg, cbid)
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "failed to add %s event handler for %s@%s",
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 (pdp->xd_xsdev.otherend_state != XenbusStateUnknown)) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt = kmem_alloc(sizeof (i_oestate_evt_t), KM_SLEEP);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_xvdi_oestate_handler, (void *)evt, DDI_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Remove event handler for the leaf driver and unwatch xenstore
843e19887f64dde75055cf8842fc4db2171eff45johnlev * so, driver will not be notified when xenstore entry changed later
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_remove_event_handler(dev_info_t *dip, char *name)
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "event %s not supported, cannot remove", name);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * common ring interfaces
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define GET_RING_SIZE(_ringp) RING_SIZE(FRONT_RING(ringp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1)))
843e19887f64dde75055cf8842fc4db2171eff45johnlev (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1)))
843e19887f64dde75055cf8842fc4db2171eff45johnlevunsigned int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_has_unconsumed_requests(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_get32(ringp->xr_acc_hdl, &brp->sring->req_prod)) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((brp->req_cons - brp->rsp_prod_pvt) != RING_SIZE(brp)));
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod));
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_has_unconsumed_responses(xendev_ring_t *ringp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod));
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* NOTE: req_event will be increased as needed */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_FE(ringp, frp->req_prod_pvt++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for backend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_FINAL_CHECK_FOR_REQUESTS() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &brp->sring->req_event,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* only frontend should be able to push request */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_PUSH_REQUEST_AND_CHECK_NOTIFY() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev old = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_prod);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &frp->sring->req_prod, new);
843e19887f64dde75055cf8842fc4db2171eff45johnlev reqevt = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_event);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((RING_IDX)(new - reqevt) < (RING_IDX)(new - old));
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* NOTE: rsp_event will be increased as needed */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for backend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (GET_RING_ENTRY_BE(ringp, brp->rsp_prod_pvt++));
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* for frontend ring */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_FINAL_CHECK_FOR_RESPONSES() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &frp->sring->rsp_event,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* only backend should be able to push response */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* RING_PUSH_RESPONSE_AND_CHECK_NOTIFY() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev old = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_prod);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_put32(ringp->xr_acc_hdl, &brp->sring->rsp_prod, new);
843e19887f64dde75055cf8842fc4db2171eff45johnlev rspevt = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_event);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((RING_IDX)(new - rspevt) < (RING_IDX)(new - old));
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* shared ring initialization */
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_init_front_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize)
843e19887f64dde75055cf8842fc4db2171eff45johnlevxvdi_ring_init_back_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize)
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif /* XPV_HVM_DRIVER */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is currently the only chance to delete a devinfo node, which
843e19887f64dde75055cf8842fc4db2171eff45johnlev * is _not_ always successful.
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) devfs_clean(ddi_get_parent(dip), devname + 1, DV_CLEAN_FORCE);
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_oestate_cb(struct xenbus_device *dev, XenbusState oestate)
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),
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson /* only call the handler if our state has changed */
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson * Try to deliver the oestate change event to the dip
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson evt = kmem_alloc(sizeof (i_oestate_evt_t), KM_SLEEP);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson i_xvdi_oestate_handler, (void *)evt, DDI_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevi_xvdi_hpstate_cb(struct xenbus_watch *w, const char **vec,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len)
eea6c6b990c4c67e19555ad428a1dda17b2efd49Max zhen (void) xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "",
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#endif /* DEBUG */
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, xdcp = &xdci[0]; i < NXDC; i++, xdcp++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (strncmp(path, xdcp->xs_path_fe, strlen(xdcp->xs_path_fe))
843e19887f64dde75055cf8842fc4db2171eff45johnlev (strncmp(path, xdcp->xs_path_be, strlen(xdcp->xs_path_be))
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (p == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "cannot parse frontend path %s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "cannot parse backend path %s",
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev * This is an oxymoron, so indicates a bogus configuration we
1ca30e39ba109652a7cbb9fa4d158cc78d0fbbadjohnlev * must check for.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xvdi_create_dev(parent, xdcp->devclass, dom, vdev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev "i_xvdi_probe_path_handler: %s already exists", path);