1*df660251SIan Campbell /****************************************************************************** 2*df660251SIan Campbell * Talks to Xen Store to figure out what devices we have (backend half). 3*df660251SIan Campbell * 4*df660251SIan Campbell * Copyright (C) 2005 Rusty Russell, IBM Corporation 5*df660251SIan Campbell * Copyright (C) 2005 Mike Wray, Hewlett-Packard 6*df660251SIan Campbell * Copyright (C) 2005, 2006 XenSource Ltd 7*df660251SIan Campbell * Copyright (C) 2007 Solarflare Communications, Inc. 8*df660251SIan Campbell * 9*df660251SIan Campbell * This program is free software; you can redistribute it and/or 10*df660251SIan Campbell * modify it under the terms of the GNU General Public License version 2 11*df660251SIan Campbell * as published by the Free Software Foundation; or, when distributed 12*df660251SIan Campbell * separately from the Linux kernel or incorporated into other 13*df660251SIan Campbell * software packages, subject to the following license: 14*df660251SIan Campbell * 15*df660251SIan Campbell * Permission is hereby granted, free of charge, to any person obtaining a copy 16*df660251SIan Campbell * of this source file (the "Software"), to deal in the Software without 17*df660251SIan Campbell * restriction, including without limitation the rights to use, copy, modify, 18*df660251SIan Campbell * merge, publish, distribute, sublicense, and/or sell copies of the Software, 19*df660251SIan Campbell * and to permit persons to whom the Software is furnished to do so, subject to 20*df660251SIan Campbell * the following conditions: 21*df660251SIan Campbell * 22*df660251SIan Campbell * The above copyright notice and this permission notice shall be included in 23*df660251SIan Campbell * all copies or substantial portions of the Software. 24*df660251SIan Campbell * 25*df660251SIan Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26*df660251SIan Campbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27*df660251SIan Campbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28*df660251SIan Campbell * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29*df660251SIan Campbell * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 30*df660251SIan Campbell * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 31*df660251SIan Campbell * IN THE SOFTWARE. 32*df660251SIan Campbell */ 33*df660251SIan Campbell 34*df660251SIan Campbell #define DPRINTK(fmt, args...) \ 35*df660251SIan Campbell pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ 36*df660251SIan Campbell __func__, __LINE__, ##args) 37*df660251SIan Campbell 38*df660251SIan Campbell #include <linux/kernel.h> 39*df660251SIan Campbell #include <linux/err.h> 40*df660251SIan Campbell #include <linux/string.h> 41*df660251SIan Campbell #include <linux/ctype.h> 42*df660251SIan Campbell #include <linux/fcntl.h> 43*df660251SIan Campbell #include <linux/mm.h> 44*df660251SIan Campbell #include <linux/notifier.h> 45*df660251SIan Campbell 46*df660251SIan Campbell #include <asm/page.h> 47*df660251SIan Campbell #include <asm/pgtable.h> 48*df660251SIan Campbell #include <asm/xen/hypervisor.h> 49*df660251SIan Campbell #include <asm/hypervisor.h> 50*df660251SIan Campbell #include <xen/xenbus.h> 51*df660251SIan Campbell #include <xen/evtchn.h> 52*df660251SIan Campbell #include <xen/features.h> 53*df660251SIan Campbell 54*df660251SIan Campbell #include "xenbus_comms.h" 55*df660251SIan Campbell #include "xenbus_probe.h" 56*df660251SIan Campbell 57*df660251SIan Campbell /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ 58*df660251SIan Campbell static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) 59*df660251SIan Campbell { 60*df660251SIan Campbell int domid, err; 61*df660251SIan Campbell const char *devid, *type, *frontend; 62*df660251SIan Campbell unsigned int typelen; 63*df660251SIan Campbell 64*df660251SIan Campbell type = strchr(nodename, '/'); 65*df660251SIan Campbell if (!type) 66*df660251SIan Campbell return -EINVAL; 67*df660251SIan Campbell type++; 68*df660251SIan Campbell typelen = strcspn(type, "/"); 69*df660251SIan Campbell if (!typelen || type[typelen] != '/') 70*df660251SIan Campbell return -EINVAL; 71*df660251SIan Campbell 72*df660251SIan Campbell devid = strrchr(nodename, '/') + 1; 73*df660251SIan Campbell 74*df660251SIan Campbell err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, 75*df660251SIan Campbell "frontend", NULL, &frontend, 76*df660251SIan Campbell NULL); 77*df660251SIan Campbell if (err) 78*df660251SIan Campbell return err; 79*df660251SIan Campbell if (strlen(frontend) == 0) 80*df660251SIan Campbell err = -ERANGE; 81*df660251SIan Campbell if (!err && !xenbus_exists(XBT_NIL, frontend, "")) 82*df660251SIan Campbell err = -ENOENT; 83*df660251SIan Campbell kfree(frontend); 84*df660251SIan Campbell 85*df660251SIan Campbell if (err) 86*df660251SIan Campbell return err; 87*df660251SIan Campbell 88*df660251SIan Campbell if (snprintf(bus_id, XEN_BUS_ID_SIZE, 89*df660251SIan Campbell "%.*s-%i-%s", typelen, type, domid, devid) >= XEN_BUS_ID_SIZE) 90*df660251SIan Campbell return -ENOSPC; 91*df660251SIan Campbell return 0; 92*df660251SIan Campbell } 93*df660251SIan Campbell 94*df660251SIan Campbell static int xenbus_uevent_backend(struct device *dev, 95*df660251SIan Campbell struct kobj_uevent_env *env) 96*df660251SIan Campbell { 97*df660251SIan Campbell struct xenbus_device *xdev; 98*df660251SIan Campbell struct xenbus_driver *drv; 99*df660251SIan Campbell struct xen_bus_type *bus; 100*df660251SIan Campbell 101*df660251SIan Campbell DPRINTK(""); 102*df660251SIan Campbell 103*df660251SIan Campbell if (dev == NULL) 104*df660251SIan Campbell return -ENODEV; 105*df660251SIan Campbell 106*df660251SIan Campbell xdev = to_xenbus_device(dev); 107*df660251SIan Campbell bus = container_of(xdev->dev.bus, struct xen_bus_type, bus); 108*df660251SIan Campbell if (xdev == NULL) 109*df660251SIan Campbell return -ENODEV; 110*df660251SIan Campbell 111*df660251SIan Campbell /* stuff we want to pass to /sbin/hotplug */ 112*df660251SIan Campbell if (add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype)) 113*df660251SIan Campbell return -ENOMEM; 114*df660251SIan Campbell 115*df660251SIan Campbell if (add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename)) 116*df660251SIan Campbell return -ENOMEM; 117*df660251SIan Campbell 118*df660251SIan Campbell if (add_uevent_var(env, "XENBUS_BASE_PATH=%s", bus->root)) 119*df660251SIan Campbell return -ENOMEM; 120*df660251SIan Campbell 121*df660251SIan Campbell if (dev->driver) { 122*df660251SIan Campbell drv = to_xenbus_driver(dev->driver); 123*df660251SIan Campbell if (drv && drv->uevent) 124*df660251SIan Campbell return drv->uevent(xdev, env); 125*df660251SIan Campbell } 126*df660251SIan Campbell 127*df660251SIan Campbell return 0; 128*df660251SIan Campbell } 129*df660251SIan Campbell 130*df660251SIan Campbell /* backend/<typename>/<frontend-uuid>/<name> */ 131*df660251SIan Campbell static int xenbus_probe_backend_unit(struct xen_bus_type *bus, 132*df660251SIan Campbell const char *dir, 133*df660251SIan Campbell const char *type, 134*df660251SIan Campbell const char *name) 135*df660251SIan Campbell { 136*df660251SIan Campbell char *nodename; 137*df660251SIan Campbell int err; 138*df660251SIan Campbell 139*df660251SIan Campbell nodename = kasprintf(GFP_KERNEL, "%s/%s", dir, name); 140*df660251SIan Campbell if (!nodename) 141*df660251SIan Campbell return -ENOMEM; 142*df660251SIan Campbell 143*df660251SIan Campbell DPRINTK("%s\n", nodename); 144*df660251SIan Campbell 145*df660251SIan Campbell err = xenbus_probe_node(bus, type, nodename); 146*df660251SIan Campbell kfree(nodename); 147*df660251SIan Campbell return err; 148*df660251SIan Campbell } 149*df660251SIan Campbell 150*df660251SIan Campbell /* backend/<typename>/<frontend-domid> */ 151*df660251SIan Campbell static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type, const char *domid) 152*df660251SIan Campbell { 153*df660251SIan Campbell char *nodename; 154*df660251SIan Campbell int err = 0; 155*df660251SIan Campbell char **dir; 156*df660251SIan Campbell unsigned int i, dir_n = 0; 157*df660251SIan Campbell 158*df660251SIan Campbell DPRINTK(""); 159*df660251SIan Campbell 160*df660251SIan Campbell nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", bus->root, type, domid); 161*df660251SIan Campbell if (!nodename) 162*df660251SIan Campbell return -ENOMEM; 163*df660251SIan Campbell 164*df660251SIan Campbell dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); 165*df660251SIan Campbell if (IS_ERR(dir)) { 166*df660251SIan Campbell kfree(nodename); 167*df660251SIan Campbell return PTR_ERR(dir); 168*df660251SIan Campbell } 169*df660251SIan Campbell 170*df660251SIan Campbell for (i = 0; i < dir_n; i++) { 171*df660251SIan Campbell err = xenbus_probe_backend_unit(bus, nodename, type, dir[i]); 172*df660251SIan Campbell if (err) 173*df660251SIan Campbell break; 174*df660251SIan Campbell } 175*df660251SIan Campbell kfree(dir); 176*df660251SIan Campbell kfree(nodename); 177*df660251SIan Campbell return err; 178*df660251SIan Campbell } 179*df660251SIan Campbell 180*df660251SIan Campbell static void frontend_changed(struct xenbus_watch *watch, 181*df660251SIan Campbell const char **vec, unsigned int len) 182*df660251SIan Campbell { 183*df660251SIan Campbell xenbus_otherend_changed(watch, vec, len, 0); 184*df660251SIan Campbell } 185*df660251SIan Campbell 186*df660251SIan Campbell static struct device_attribute xenbus_backend_dev_attrs[] = { 187*df660251SIan Campbell __ATTR_NULL 188*df660251SIan Campbell }; 189*df660251SIan Campbell 190*df660251SIan Campbell static struct xen_bus_type xenbus_backend = { 191*df660251SIan Campbell .root = "backend", 192*df660251SIan Campbell .levels = 3, /* backend/type/<frontend>/<id> */ 193*df660251SIan Campbell .get_bus_id = backend_bus_id, 194*df660251SIan Campbell .probe = xenbus_probe_backend, 195*df660251SIan Campbell .otherend_changed = frontend_changed, 196*df660251SIan Campbell .bus = { 197*df660251SIan Campbell .name = "xen-backend", 198*df660251SIan Campbell .match = xenbus_match, 199*df660251SIan Campbell .uevent = xenbus_uevent_backend, 200*df660251SIan Campbell .probe = xenbus_dev_probe, 201*df660251SIan Campbell .remove = xenbus_dev_remove, 202*df660251SIan Campbell .shutdown = xenbus_dev_shutdown, 203*df660251SIan Campbell .dev_attrs = xenbus_backend_dev_attrs, 204*df660251SIan Campbell }, 205*df660251SIan Campbell }; 206*df660251SIan Campbell 207*df660251SIan Campbell static void backend_changed(struct xenbus_watch *watch, 208*df660251SIan Campbell const char **vec, unsigned int len) 209*df660251SIan Campbell { 210*df660251SIan Campbell DPRINTK(""); 211*df660251SIan Campbell 212*df660251SIan Campbell xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); 213*df660251SIan Campbell } 214*df660251SIan Campbell 215*df660251SIan Campbell static struct xenbus_watch be_watch = { 216*df660251SIan Campbell .node = "backend", 217*df660251SIan Campbell .callback = backend_changed, 218*df660251SIan Campbell }; 219*df660251SIan Campbell 220*df660251SIan Campbell static int read_frontend_details(struct xenbus_device *xendev) 221*df660251SIan Campbell { 222*df660251SIan Campbell return xenbus_read_otherend_details(xendev, "frontend-id", "frontend"); 223*df660251SIan Campbell } 224*df660251SIan Campbell 225*df660251SIan Campbell //void xenbus_backend_suspend(int (*fn)(struct device *, void *)) 226*df660251SIan Campbell //{ 227*df660251SIan Campbell // DPRINTK(""); 228*df660251SIan Campbell // bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); 229*df660251SIan Campbell //} 230*df660251SIan Campbell 231*df660251SIan Campbell //void xenbus_backend_resume(int (*fn)(struct device *, void *)) 232*df660251SIan Campbell //{ 233*df660251SIan Campbell // DPRINTK(""); 234*df660251SIan Campbell // bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); 235*df660251SIan Campbell //} 236*df660251SIan Campbell 237*df660251SIan Campbell //int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *)) 238*df660251SIan Campbell //{ 239*df660251SIan Campbell // return bus_for_each_dev(&xenbus_backend.bus, NULL, arg, fn); 240*df660251SIan Campbell //} 241*df660251SIan Campbell //EXPORT_SYMBOL_GPL(xenbus_for_each_backend); 242*df660251SIan Campbell 243*df660251SIan Campbell int xenbus_dev_is_online(struct xenbus_device *dev) 244*df660251SIan Campbell { 245*df660251SIan Campbell int rc, val; 246*df660251SIan Campbell 247*df660251SIan Campbell rc = xenbus_scanf(XBT_NIL, dev->nodename, "online", "%d", &val); 248*df660251SIan Campbell if (rc != 1) 249*df660251SIan Campbell val = 0; /* no online node present */ 250*df660251SIan Campbell 251*df660251SIan Campbell return val; 252*df660251SIan Campbell } 253*df660251SIan Campbell EXPORT_SYMBOL_GPL(xenbus_dev_is_online); 254*df660251SIan Campbell 255*df660251SIan Campbell int __xenbus_register_backend(struct xenbus_driver *drv, 256*df660251SIan Campbell struct module *owner, const char *mod_name) 257*df660251SIan Campbell { 258*df660251SIan Campbell drv->read_otherend_details = read_frontend_details; 259*df660251SIan Campbell 260*df660251SIan Campbell return xenbus_register_driver_common(drv, &xenbus_backend, 261*df660251SIan Campbell owner, mod_name); 262*df660251SIan Campbell } 263*df660251SIan Campbell EXPORT_SYMBOL_GPL(__xenbus_register_backend); 264*df660251SIan Campbell 265*df660251SIan Campbell static int backend_probe_and_watch(struct notifier_block *notifier, 266*df660251SIan Campbell unsigned long event, 267*df660251SIan Campbell void *data) 268*df660251SIan Campbell { 269*df660251SIan Campbell /* Enumerate devices in xenstore and watch for changes. */ 270*df660251SIan Campbell xenbus_probe_devices(&xenbus_backend); 271*df660251SIan Campbell printk(KERN_CRIT "%s devices probed ok\n", __func__); 272*df660251SIan Campbell register_xenbus_watch(&be_watch); 273*df660251SIan Campbell printk(KERN_CRIT "%s watch add ok ok\n", __func__); 274*df660251SIan Campbell printk(KERN_CRIT "%s all done\n", __func__); 275*df660251SIan Campbell return NOTIFY_DONE; 276*df660251SIan Campbell } 277*df660251SIan Campbell 278*df660251SIan Campbell static int __init xenbus_probe_backend_init(void) 279*df660251SIan Campbell { 280*df660251SIan Campbell static struct notifier_block xenstore_notifier = { 281*df660251SIan Campbell .notifier_call = backend_probe_and_watch 282*df660251SIan Campbell }; 283*df660251SIan Campbell int err; 284*df660251SIan Campbell 285*df660251SIan Campbell DPRINTK(""); 286*df660251SIan Campbell 287*df660251SIan Campbell /* Register ourselves with the kernel bus subsystem */ 288*df660251SIan Campbell err = bus_register(&xenbus_backend.bus); 289*df660251SIan Campbell if (err) { 290*df660251SIan Campbell printk(KERN_CRIT "%s didn't register bus!\n", __func__); 291*df660251SIan Campbell return err; 292*df660251SIan Campbell } 293*df660251SIan Campbell printk(KERN_CRIT "%s bus registered ok\n", __func__); 294*df660251SIan Campbell 295*df660251SIan Campbell register_xenstore_notifier(&xenstore_notifier); 296*df660251SIan Campbell 297*df660251SIan Campbell return 0; 298*df660251SIan Campbell } 299*df660251SIan Campbell 300*df660251SIan Campbell module_init(xenbus_probe_backend_init); 301