xref: /onnv-gate/usr/src/uts/common/xen/io/xenbus_probe.c (revision 8863:94039d51dda4)
15084Sjohnlev /*
25084Sjohnlev  * CDDL HEADER START
35084Sjohnlev  *
45084Sjohnlev  * The contents of this file are subject to the terms of the
55084Sjohnlev  * Common Development and Distribution License (the "License").
65084Sjohnlev  * You may not use this file except in compliance with the License.
75084Sjohnlev  *
85084Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95084Sjohnlev  * or http://www.opensolaris.org/os/licensing.
105084Sjohnlev  * See the License for the specific language governing permissions
115084Sjohnlev  * and limitations under the License.
125084Sjohnlev  *
135084Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
145084Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155084Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
165084Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
175084Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
185084Sjohnlev  *
195084Sjohnlev  * CDDL HEADER END
205084Sjohnlev  */
215084Sjohnlev 
225084Sjohnlev /*
23*8863SEdward.Pilatowicz@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245084Sjohnlev  * Use is subject to license terms.
255084Sjohnlev  */
265084Sjohnlev 
275084Sjohnlev /*
285084Sjohnlev  * Talks to Xen Store to figure out what devices we have.
295084Sjohnlev  *
305084Sjohnlev  * Copyright (C) 2005 Rusty Russell, IBM Corporation
315084Sjohnlev  * Copyright (C) 2005 Mike Wray, Hewlett-Packard
325084Sjohnlev  * Copyright (C) 2005 XenSource Ltd
335084Sjohnlev  *
345084Sjohnlev  * This file may be distributed separately from the Linux kernel, or
355084Sjohnlev  * incorporated into other software packages, subject to the following license:
365084Sjohnlev  *
375084Sjohnlev  * Permission is hereby granted, free of charge, to any person obtaining a copy
385084Sjohnlev  * of this source file (the "Software"), to deal in the Software without
395084Sjohnlev  * restriction, including without limitation the rights to use, copy, modify,
405084Sjohnlev  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
415084Sjohnlev  * and to permit persons to whom the Software is furnished to do so, subject to
425084Sjohnlev  * the following conditions:
435084Sjohnlev  *
445084Sjohnlev  * The above copyright notice and this permission notice shall be included in
455084Sjohnlev  * all copies or substantial portions of the Software.
465084Sjohnlev  *
475084Sjohnlev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
485084Sjohnlev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
495084Sjohnlev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
505084Sjohnlev  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
515084Sjohnlev  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
525084Sjohnlev  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
535084Sjohnlev  * IN THE SOFTWARE.
545084Sjohnlev  */
555084Sjohnlev 
565741Smrj #ifdef XPV_HVM_DRIVER
575741Smrj #include <sys/xpv_support.h>
585741Smrj #endif
595084Sjohnlev #include <sys/hypervisor.h>
605084Sjohnlev #include <xen/sys/xenbus_impl.h>
615084Sjohnlev #include <xen/sys/xenbus_comms.h>
625084Sjohnlev #include <xen/public/io/xs_wire.h>
635084Sjohnlev 
645084Sjohnlev static int
read_otherend_details(struct xenbus_device * xendev,char * id_node,char * path_node)655084Sjohnlev read_otherend_details(struct xenbus_device *xendev,
665084Sjohnlev 			char *id_node, char *path_node)
675084Sjohnlev {
685084Sjohnlev 	int err = xenbus_gather(XBT_NULL, xendev->nodename,
695084Sjohnlev 	    id_node, "%i", &xendev->otherend_id, path_node, NULL,
705084Sjohnlev 	    &xendev->otherend, NULL);
715084Sjohnlev 	if (err) {
725084Sjohnlev 		xenbus_dev_fatal(xendev, err,
735084Sjohnlev 		    "reading other end details from %s", xendev->nodename);
745084Sjohnlev 		return (err);
755084Sjohnlev 	}
765084Sjohnlev 	if (strlen(xendev->otherend) == 0 ||
77*8863SEdward.Pilatowicz@Sun.COM 	    !xenbus_exists_dir(xendev->otherend, "")) {
785084Sjohnlev 		xenbus_dev_fatal(xendev, X_ENOENT, "missing other end from %s",
795084Sjohnlev 		    xendev->nodename);
805084Sjohnlev 		kmem_free((void *)xendev->otherend,
815084Sjohnlev 		    strlen(xendev->otherend) + 1);
825084Sjohnlev 		xendev->otherend = NULL;
835084Sjohnlev 		return (X_ENOENT);
845084Sjohnlev 	}
855084Sjohnlev 
865084Sjohnlev 	return (0);
875084Sjohnlev }
885084Sjohnlev 
895084Sjohnlev 
905084Sjohnlev static int
read_backend_details(struct xenbus_device * xendev)915084Sjohnlev read_backend_details(struct xenbus_device *xendev)
925084Sjohnlev {
935084Sjohnlev 	return (read_otherend_details(xendev, "backend-id", "backend"));
945084Sjohnlev }
955084Sjohnlev 
965084Sjohnlev 
975084Sjohnlev static int
read_frontend_details(struct xenbus_device * xendev)985084Sjohnlev read_frontend_details(struct xenbus_device *xendev)
995084Sjohnlev {
1005084Sjohnlev 	return (read_otherend_details(xendev, "frontend-id", "frontend"));
1015084Sjohnlev }
1025084Sjohnlev 
1035084Sjohnlev 
1045084Sjohnlev static void
free_otherend_details(struct xenbus_device * dev)1055084Sjohnlev free_otherend_details(struct xenbus_device *dev)
1065084Sjohnlev {
1075084Sjohnlev 	if (dev->otherend != NULL) {
1085084Sjohnlev 		kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1);
1095084Sjohnlev 		dev->otherend = NULL;
1105084Sjohnlev 	}
1115084Sjohnlev }
1125084Sjohnlev 
1135084Sjohnlev 
1145084Sjohnlev static void
free_otherend_watch(struct xenbus_device * dev)1155084Sjohnlev free_otherend_watch(struct xenbus_device *dev)
1165084Sjohnlev {
1175084Sjohnlev 	if (dev->otherend_watch.node) {
1185084Sjohnlev 		unregister_xenbus_watch(&dev->otherend_watch);
1195084Sjohnlev 		kmem_free((void *)dev->otherend_watch.node,
1205084Sjohnlev 		    strlen(dev->otherend_watch.node) + 1);
1215084Sjohnlev 		dev->otherend_watch.node = NULL;
1225084Sjohnlev 	}
1235084Sjohnlev }
1245084Sjohnlev 
1255084Sjohnlev 
1265084Sjohnlev /*ARGSUSED2*/
1275084Sjohnlev static void
otherend_changed(struct xenbus_watch * watch,const char ** vec,unsigned int len)1285084Sjohnlev otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len)
1295084Sjohnlev {
1305084Sjohnlev 	struct xenbus_device *dev = watch->dev;
1315084Sjohnlev 	XenbusState state;
1325084Sjohnlev 
1335084Sjohnlev 	/*
1345084Sjohnlev 	 * Protect us against watches firing on old details when the otherend
1355084Sjohnlev 	 * details change, say immediately after a resume.
1365084Sjohnlev 	 */
1375084Sjohnlev 	if (!dev->otherend ||
1385084Sjohnlev 	    strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) {
1395084Sjohnlev #if 0
1405084Sjohnlev 		printf("Ignoring watch at %s", vec[XS_WATCH_PATH]);
1415084Sjohnlev #endif
1425084Sjohnlev 		return;
1435084Sjohnlev 	}
1445084Sjohnlev 
1455084Sjohnlev 	state = xenbus_read_driver_state(dev->otherend);
1465084Sjohnlev 
1475084Sjohnlev #if 0
1485084Sjohnlev 	printf("state is %d, %s, %s",
1495084Sjohnlev 	    state, dev->otherend_watch.node, vec[XS_WATCH_PATH]);
1505084Sjohnlev #endif
1515084Sjohnlev 	if (dev->otherend_changed)
1525084Sjohnlev 		dev->otherend_changed(dev, state);
1535084Sjohnlev }
1545084Sjohnlev 
1555084Sjohnlev 
1565084Sjohnlev int
talk_to_otherend(struct xenbus_device * dev)1575084Sjohnlev talk_to_otherend(struct xenbus_device *dev)
1585084Sjohnlev {
1595084Sjohnlev 	int err;
1605084Sjohnlev 
1615084Sjohnlev 	free_otherend_watch(dev);
1625084Sjohnlev 	free_otherend_details(dev);
1635084Sjohnlev 
1645084Sjohnlev 	if (dev->frontend)
1655084Sjohnlev 		err = read_backend_details(dev);
1665084Sjohnlev 	else
1675084Sjohnlev 		err = read_frontend_details(dev);
1685084Sjohnlev 	if (err)
1695084Sjohnlev 		return (err);
1705084Sjohnlev 
1715084Sjohnlev 	dev->otherend_watch.dev = dev;
1725084Sjohnlev 	return (xenbus_watch_path2(dev, dev->otherend, "state",
1735084Sjohnlev 	    &dev->otherend_watch, otherend_changed));
1745084Sjohnlev }
1755084Sjohnlev 
1765084Sjohnlev 
1775084Sjohnlev /*
1785084Sjohnlev  * Local variables:
1795084Sjohnlev  *  c-file-style: "solaris"
1805084Sjohnlev  *  indent-tabs-mode: t
1815084Sjohnlev  *  c-indent-level: 8
1825084Sjohnlev  *  c-basic-offset: 8
1835084Sjohnlev  *  tab-width: 8
1845084Sjohnlev  * End:
1855084Sjohnlev  */
186