xenbus_probe.c revision 8863:94039d51dda4
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* 28 * Talks to Xen Store to figure out what devices we have. 29 * 30 * Copyright (C) 2005 Rusty Russell, IBM Corporation 31 * Copyright (C) 2005 Mike Wray, Hewlett-Packard 32 * Copyright (C) 2005 XenSource Ltd 33 * 34 * This file may be distributed separately from the Linux kernel, or 35 * incorporated into other software packages, subject to the following license: 36 * 37 * Permission is hereby granted, free of charge, to any person obtaining a copy 38 * of this source file (the "Software"), to deal in the Software without 39 * restriction, including without limitation the rights to use, copy, modify, 40 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 41 * and to permit persons to whom the Software is furnished to do so, subject to 42 * the following conditions: 43 * 44 * The above copyright notice and this permission notice shall be included in 45 * all copies or substantial portions of the Software. 46 * 47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 48 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 51 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 52 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 53 * IN THE SOFTWARE. 54 */ 55 56#ifdef XPV_HVM_DRIVER 57#include <sys/xpv_support.h> 58#endif 59#include <sys/hypervisor.h> 60#include <xen/sys/xenbus_impl.h> 61#include <xen/sys/xenbus_comms.h> 62#include <xen/public/io/xs_wire.h> 63 64static int 65read_otherend_details(struct xenbus_device *xendev, 66 char *id_node, char *path_node) 67{ 68 int err = xenbus_gather(XBT_NULL, xendev->nodename, 69 id_node, "%i", &xendev->otherend_id, path_node, NULL, 70 &xendev->otherend, NULL); 71 if (err) { 72 xenbus_dev_fatal(xendev, err, 73 "reading other end details from %s", xendev->nodename); 74 return (err); 75 } 76 if (strlen(xendev->otherend) == 0 || 77 !xenbus_exists_dir(xendev->otherend, "")) { 78 xenbus_dev_fatal(xendev, X_ENOENT, "missing other end from %s", 79 xendev->nodename); 80 kmem_free((void *)xendev->otherend, 81 strlen(xendev->otherend) + 1); 82 xendev->otherend = NULL; 83 return (X_ENOENT); 84 } 85 86 return (0); 87} 88 89 90static int 91read_backend_details(struct xenbus_device *xendev) 92{ 93 return (read_otherend_details(xendev, "backend-id", "backend")); 94} 95 96 97static int 98read_frontend_details(struct xenbus_device *xendev) 99{ 100 return (read_otherend_details(xendev, "frontend-id", "frontend")); 101} 102 103 104static void 105free_otherend_details(struct xenbus_device *dev) 106{ 107 if (dev->otherend != NULL) { 108 kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1); 109 dev->otherend = NULL; 110 } 111} 112 113 114static void 115free_otherend_watch(struct xenbus_device *dev) 116{ 117 if (dev->otherend_watch.node) { 118 unregister_xenbus_watch(&dev->otherend_watch); 119 kmem_free((void *)dev->otherend_watch.node, 120 strlen(dev->otherend_watch.node) + 1); 121 dev->otherend_watch.node = NULL; 122 } 123} 124 125 126/*ARGSUSED2*/ 127static void 128otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) 129{ 130 struct xenbus_device *dev = watch->dev; 131 XenbusState state; 132 133 /* 134 * Protect us against watches firing on old details when the otherend 135 * details change, say immediately after a resume. 136 */ 137 if (!dev->otherend || 138 strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) { 139#if 0 140 printf("Ignoring watch at %s", vec[XS_WATCH_PATH]); 141#endif 142 return; 143 } 144 145 state = xenbus_read_driver_state(dev->otherend); 146 147#if 0 148 printf("state is %d, %s, %s", 149 state, dev->otherend_watch.node, vec[XS_WATCH_PATH]); 150#endif 151 if (dev->otherend_changed) 152 dev->otherend_changed(dev, state); 153} 154 155 156int 157talk_to_otherend(struct xenbus_device *dev) 158{ 159 int err; 160 161 free_otherend_watch(dev); 162 free_otherend_details(dev); 163 164 if (dev->frontend) 165 err = read_backend_details(dev); 166 else 167 err = read_frontend_details(dev); 168 if (err) 169 return (err); 170 171 dev->otherend_watch.dev = dev; 172 return (xenbus_watch_path2(dev, dev->otherend, "state", 173 &dev->otherend_watch, otherend_changed)); 174} 175 176 177/* 178 * Local variables: 179 * c-file-style: "solaris" 180 * indent-tabs-mode: t 181 * c-indent-level: 8 182 * c-basic-offset: 8 183 * tab-width: 8 184 * End: 185 */ 186