14bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge/****************************************************************************** 24bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * Talks to Xen Store to figure out what devices we have. 34bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * 44bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * Copyright (C) 2005 Rusty Russell, IBM Corporation 54bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * Copyright (C) 2005 Mike Wray, Hewlett-Packard 64bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * Copyright (C) 2005, 2006 XenSource Ltd 74bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * 84bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * This program is free software; you can redistribute it and/or 94bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * modify it under the terms of the GNU General Public License version 2 104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * as published by the Free Software Foundation; or, when distributed 114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * separately from the Linux kernel or incorporated into other 124bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * software packages, subject to the following license: 134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * 144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * Permission is hereby granted, free of charge, to any person obtaining a copy 154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * of this source file (the "Software"), to deal in the Software without 164bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * restriction, including without limitation the rights to use, copy, modify, 174bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * merge, publish, distribute, sublicense, and/or sell copies of the Software, 184bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * and to permit persons to whom the Software is furnished to do so, subject to 194bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * the following conditions: 204bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * 214bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * The above copyright notice and this permission notice shall be included in 224bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * all copies or substantial portions of the Software. 234bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * 244bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 254bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 264bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 274bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 284bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 294bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 304bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * IN THE SOFTWARE. 314bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge */ 324bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 334bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#define DPRINTK(fmt, args...) \ 344bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ 354bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge __func__, __LINE__, ##args) 364bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 374bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/kernel.h> 384bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/err.h> 394bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/string.h> 404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/ctype.h> 414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/fcntl.h> 424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/mm.h> 431107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt#include <linux/proc_fs.h> 444bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/notifier.h> 454bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/kthread.h> 464bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/mutex.h> 474bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <linux/io.h> 485a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 4972ee5112a0007c958dc57f4a1469c4bbd2cf4d11Paul Gortmaker#include <linux/module.h> 504bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <asm/page.h> 524bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <asm/pgtable.h> 534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <asm/xen/hypervisor.h> 541ccbf5344c3daef046d2323190cc6807c44f1917Jeremy Fitzhardinge 551ccbf5344c3daef046d2323190cc6807c44f1917Jeremy Fitzhardinge#include <xen/xen.h> 564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <xen/xenbus.h> 574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <xen/events.h> 584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include <xen/page.h> 594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 60bee6ab53e652a414af20392899879b58cd80d033Sheng Yang#include <xen/hvm.h> 61bee6ab53e652a414af20392899879b58cd80d033Sheng Yang 624bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include "xenbus_comms.h" 634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge#include "xenbus_probe.h" 644bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 651107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt 664bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xen_store_evtchn; 678e3e99918b9ccd6bc2369ddbcd74056f8796e1e0Jeremy FitzhardingeEXPORT_SYMBOL_GPL(xen_store_evtchn); 681107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt 694bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestruct xenstore_domain_interface *xen_store_interface; 708e3e99918b9ccd6bc2369ddbcd74056f8796e1e0Jeremy FitzhardingeEXPORT_SYMBOL_GPL(xen_store_interface); 718e3e99918b9ccd6bc2369ddbcd74056f8796e1e0Jeremy Fitzhardinge 724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic unsigned long xen_store_mfn; 734bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 744bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic BLOCKING_NOTIFIER_HEAD(xenstore_chain); 754bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge/* If something in array of ids matches this device, return it. */ 774bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic const struct xenbus_device_id * 784bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingematch_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) 794bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 804bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge for (; *arr->devicetype != '\0'; arr++) { 814bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!strcmp(arr->devicetype, dev->devicetype)) 824bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return arr; 834bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 844bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return NULL; 854bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 864bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 874bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xenbus_match(struct device *_dev, struct device_driver *_drv) 884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 894bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_driver *drv = to_xenbus_driver(_drv); 904bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 914bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!drv->ids) 924bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 934bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 944bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; 954bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 962de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_match); 972de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 984bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 994bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic void free_otherend_details(struct xenbus_device *dev) 1004bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 1014bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(dev->otherend); 1024bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev->otherend = NULL; 1034bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 1044bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1054bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1064bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic void free_otherend_watch(struct xenbus_device *dev) 1074bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 1084bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (dev->otherend_watch.node) { 1094bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge unregister_xenbus_watch(&dev->otherend_watch); 1104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(dev->otherend_watch.node); 1114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev->otherend_watch.node = NULL; 1124bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 1134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 1144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1162de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int talk_to_otherend(struct xenbus_device *dev) 1172de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1182de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); 1192de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1202de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell free_otherend_watch(dev); 1212de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell free_otherend_details(dev); 1222de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1232de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return drv->read_otherend_details(dev); 1242de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 1252de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1262de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1272de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1282de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int watch_otherend(struct xenbus_device *dev) 1292de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1306bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell struct xen_bus_type *bus = 1316bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell container_of(dev->dev.bus, struct xen_bus_type, bus); 1322de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1336bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell return xenbus_watch_pathfmt(dev, &dev->otherend_watch, 1346bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell bus->otherend_changed, 1352de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell "%s/%s", dev->otherend, "state"); 1362de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 1372de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1382de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1392de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellint xenbus_read_otherend_details(struct xenbus_device *xendev, 1404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge char *id_node, char *path_node) 1414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 1424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err = xenbus_gather(XBT_NIL, xendev->nodename, 1434bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge id_node, "%i", &xendev->otherend_id, 1444bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge path_node, NULL, &xendev->otherend, 1454bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge NULL); 1464bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 1474bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_dev_fatal(xendev, err, 1484bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "reading other end details from %s", 1494bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->nodename); 1504bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 1514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 1524bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (strlen(xendev->otherend) == 0 || 1534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge !xenbus_exists(XBT_NIL, xendev->otherend, "")) { 1544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_dev_fatal(xendev, -ENOENT, 1554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "unable to read other end from %s. " 1564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "missing or inaccessible.", 1574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->nodename); 1584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge free_otherend_details(xendev); 1594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return -ENOENT; 1604bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 1614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1624bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 1634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 1642de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_read_otherend_details); 1654bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1662de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellvoid xenbus_otherend_changed(struct xenbus_watch *watch, 1672de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell const char **vec, unsigned int len, 1682de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell int ignore_on_shutdown) 1694bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 1704bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *dev = 1714bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge container_of(watch, struct xenbus_device, otherend_watch); 1724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); 1734bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge enum xenbus_state state; 1744bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1754bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Protect us against watches firing on old details when the otherend 1764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge details change, say immediately after a resume. */ 1774bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!dev->otherend || 1784bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge strncmp(dev->otherend, vec[XS_WATCH_PATH], 1794bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge strlen(dev->otherend))) { 180898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches dev_dbg(&dev->dev, "Ignoring watch at %s\n", 181898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches vec[XS_WATCH_PATH]); 1824bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return; 1834bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 1844bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1854bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge state = xenbus_read_driver_state(dev->otherend); 1864bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 187898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n", 1884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge state, xenbus_strstate(state), dev->otherend_watch.node, 1894bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge vec[XS_WATCH_PATH]); 1904bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 1914bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* 1924bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * Ignore xenbus transitions during shutdown. This prevents us doing 1934bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge * work that can fail e.g., when the rootfs is gone. 1944bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge */ 1954bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (system_state > SYSTEM_RUNNING) { 1962de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (ignore_on_shutdown && (state == XenbusStateClosing)) 1974bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_frontend_closed(dev); 1984bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return; 1994bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 2004bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2014bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (drv->otherend_changed) 2024bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge drv->otherend_changed(dev, state); 2034bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 2042de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_otherend_changed); 2054bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2064bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xenbus_dev_probe(struct device *_dev) 2074bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 2084bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *dev = to_xenbus_device(_dev); 2094bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); 2104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge const struct xenbus_device_id *id; 2114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err; 2124bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge DPRINTK("%s", dev->nodename); 2144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!drv->probe) { 2164bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = -ENODEV; 2174bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge goto fail; 2184bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 2194bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2204bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge id = match_device(drv->ids, dev); 2214bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!id) { 2224bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = -ENODEV; 2234bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge goto fail; 2244bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 2254bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2264bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = talk_to_otherend(dev); 2274bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 2284bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev_warn(&dev->dev, "talk_to_otherend on %s failed.\n", 2294bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev->nodename); 2304bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 2314bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 2324bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2334bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = drv->probe(dev, id); 2344bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) 2354bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge goto fail; 2364bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2374bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = watch_otherend(dev); 2384bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 2394bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev_warn(&dev->dev, "watch_otherend on %s failed.\n", 2404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev->nodename); 2414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 2424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 2434bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2444bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 2454bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingefail: 2464bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); 2474bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_switch_state(dev, XenbusStateClosed); 2487432e4bd0bcec9f18d9c94de8925b8a59d3edf94Jeremy Fitzhardinge return err; 2494bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 2502de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_dev_probe); 2514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2524bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xenbus_dev_remove(struct device *_dev) 2534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 2544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *dev = to_xenbus_device(_dev); 2554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); 2564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge DPRINTK("%s", dev->nodename); 2584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge free_otherend_watch(dev); 2604bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (drv->remove) 2624bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge drv->remove(dev); 2634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 264bd0d5aa417d40d6b996fb7b5c926bcecd56c8984Jan Beulich free_otherend_details(dev); 265bd0d5aa417d40d6b996fb7b5c926bcecd56c8984Jan Beulich 2664bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_switch_state(dev, XenbusStateClosed); 2674bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 2684bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 2692de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_dev_remove); 2704bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2712de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellvoid xenbus_dev_shutdown(struct device *_dev) 2724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 2734bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *dev = to_xenbus_device(_dev); 2744bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge unsigned long timeout = 5*HZ; 2754bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge DPRINTK("%s", dev->nodename); 2774bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2784bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge get_device(&dev->dev); 2794bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (dev->state != XenbusStateConnected) { 2804bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_INFO "%s: %s: %s != Connected, skipping\n", __func__, 2814bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev->nodename, xenbus_strstate(dev->state)); 2824bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge goto out; 2834bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 2844bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_switch_state(dev, XenbusStateClosing); 2854bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge timeout = wait_for_completion_timeout(&dev->down, timeout); 2864bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!timeout) 2874bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_INFO "%s: %s timeout closing device\n", 2884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge __func__, dev->nodename); 2894bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge out: 2904bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge put_device(&dev->dev); 2914bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 2922de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_dev_shutdown); 2934bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2944bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xenbus_register_driver_common(struct xenbus_driver *drv, 29573db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich struct xen_bus_type *bus) 2964bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 2974bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge drv->driver.bus = &bus->bus; 2984bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 2994bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return driver_register(&drv->driver); 3004bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3012de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_register_driver_common); 3024bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3034bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingevoid xenbus_unregister_driver(struct xenbus_driver *drv) 3044bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3054bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge driver_unregister(&drv->driver); 3064bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3074bac07c993d03434ea902d3d4290d9e45944b66cJeremy FitzhardingeEXPORT_SYMBOL_GPL(xenbus_unregister_driver); 3084bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3096913200a566b6d2866d46d7b947a2326c4e11f55Ruslan Pisarevstruct xb_find_info { 3104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *dev; 3114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge const char *nodename; 3124bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge}; 3134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic int cmp_dev(struct device *dev, void *data) 3154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3164bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *xendev = to_xenbus_device(dev); 3174bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xb_find_info *info = data; 3184bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3194bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!strcmp(xendev->nodename, info->nodename)) { 3204bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge info->dev = xendev; 3214bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge get_device(dev); 3224bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 1; 3234bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 3244bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 3254bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3264bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3274bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestruct xenbus_device *xenbus_device_find(const char *nodename, 3284bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct bus_type *bus) 3294bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3304bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xb_find_info info = { .dev = NULL, .nodename = nodename }; 3314bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3324bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge bus_for_each_dev(bus, NULL, &info, cmp_dev); 3334bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return info.dev; 3344bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3354bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3364bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic int cleanup_dev(struct device *dev, void *data) 3374bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3384bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *xendev = to_xenbus_device(dev); 3394bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xb_find_info *info = data; 3404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int len = strlen(info->nodename); 3414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge DPRINTK("%s", info->nodename); 3434bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3444bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Match the info->nodename path, or any subdirectory of that path. */ 3454bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (strncmp(xendev->nodename, info->nodename, len)) 3464bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 3474bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3484bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* If the node name is longer, ensure it really is a subdirectory. */ 3494bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if ((strlen(xendev->nodename) > len) && (xendev->nodename[len] != '/')) 3504bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 3514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3524bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge info->dev = xendev; 3534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge get_device(dev); 3544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 1; 3554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic void xenbus_cleanup_devices(const char *path, struct bus_type *bus) 3584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xb_find_info info = { .nodename = path }; 3604bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge do { 3624bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge info.dev = NULL; 3634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge bus_for_each_dev(bus, NULL, &info, cleanup_dev); 3644bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (info.dev) { 3654bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge device_unregister(&info.dev->dev); 3664bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge put_device(&info.dev->dev); 3674bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 3684bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } while (info.dev); 3694bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3704bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 3714bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic void xenbus_dev_release(struct device *dev) 3724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3734bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (dev) 3744bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(to_xenbus_device(dev)); 3754bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 377cc85e93342c030f8ba07f572afa159ec4518231fBastian Blankstatic ssize_t nodename_show(struct device *dev, 378cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank struct device_attribute *attr, char *buf) 3794bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3804bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); 3814bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3824bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 383cc85e93342c030f8ba07f572afa159ec4518231fBastian Blankstatic ssize_t devtype_show(struct device *dev, 384cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank struct device_attribute *attr, char *buf) 3854bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 3864bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); 3874bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 3884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 389cc85e93342c030f8ba07f572afa159ec4518231fBastian Blankstatic ssize_t modalias_show(struct device *dev, 390cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank struct device_attribute *attr, char *buf) 391d2f0c52bec954460e72dee48f3a29c6f310d76beMark McLoughlin{ 392149bb2fab547253e6359e76f1b86b95247110e68Bastian Blank return sprintf(buf, "%s:%s\n", dev->bus->name, 393149bb2fab547253e6359e76f1b86b95247110e68Bastian Blank to_xenbus_device(dev)->devicetype); 394d2f0c52bec954460e72dee48f3a29c6f310d76beMark McLoughlin} 395cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank 396cc85e93342c030f8ba07f572afa159ec4518231fBastian Blankstruct device_attribute xenbus_dev_attrs[] = { 397cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank __ATTR_RO(nodename), 398cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank __ATTR_RO(devtype), 399cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank __ATTR_RO(modalias), 400cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank __ATTR_NULL 401cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank}; 402cc85e93342c030f8ba07f572afa159ec4518231fBastian BlankEXPORT_SYMBOL_GPL(xenbus_dev_attrs); 4034bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4044bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xenbus_probe_node(struct xen_bus_type *bus, 4054bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge const char *type, 4064bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge const char *nodename) 4074bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 4082a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers char devname[XEN_BUS_ID_SIZE]; 4094bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err; 4104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *xendev; 4114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge size_t stringlen; 4124bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge char *tmpstring; 4134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge enum xenbus_state state = xenbus_read_driver_state(nodename); 4154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4164bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (state != XenbusStateInitialising) { 4174bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Device is not new, so ignore it. This can happen if a 4184bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge device is going away after switching to Closed. */ 4194bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 4204bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 4214bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4224bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge stringlen = strlen(nodename) + 1 + strlen(type) + 1; 4234bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev = kzalloc(sizeof(*xendev) + stringlen, GFP_KERNEL); 4244bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!xendev) 4254bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return -ENOMEM; 4264bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4274bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->state = XenbusStateInitialising; 4284bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4294bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Copy the strings into the extra space. */ 4304bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4314bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge tmpstring = (char *)(xendev + 1); 4324bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge strcpy(tmpstring, nodename); 4334bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->nodename = tmpstring; 4344bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4354bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge tmpstring += strlen(tmpstring) + 1; 4364bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge strcpy(tmpstring, type); 4374bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->devicetype = tmpstring; 4384bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge init_completion(&xendev->down); 4394bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->dev.bus = &bus->bus; 4414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xendev->dev.release = xenbus_dev_release; 4424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4432a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers err = bus->get_bus_id(devname, xendev->nodename); 4444bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) 4454bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge goto fail; 4464bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4472a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers dev_set_name(&xendev->dev, devname); 4482a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers 4494bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Register with generic device framework. */ 4504bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = device_register(&xendev->dev); 4514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) 4524bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge goto fail; 4534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 4554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingefail: 4564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(xendev); 4574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 4584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 4592de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_probe_node); 4604bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) 4624bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 4634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err = 0; 4644bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge char **dir; 4654bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge unsigned int dir_n = 0; 4664bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int i; 4674bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4684bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n); 469a39bda27b35266beae945f48e0b6ab58d06a17d5Jeremy Fitzhardinge if (IS_ERR(dir)) 4704bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return PTR_ERR(dir); 4714bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge for (i = 0; i < dir_n; i++) { 4732de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell err = bus->probe(bus, type, dir[i]); 474a39bda27b35266beae945f48e0b6ab58d06a17d5Jeremy Fitzhardinge if (err) 4754bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge break; 4764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 477a39bda27b35266beae945f48e0b6ab58d06a17d5Jeremy Fitzhardinge 4784bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(dir); 4794bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 4804bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 4814bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4824bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint xenbus_probe_devices(struct xen_bus_type *bus) 4834bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 4844bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err = 0; 4854bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge char **dir; 4864bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge unsigned int i, dir_n; 4874bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n); 489a39bda27b35266beae945f48e0b6ab58d06a17d5Jeremy Fitzhardinge if (IS_ERR(dir)) 4904bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return PTR_ERR(dir); 4914bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 4924bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge for (i = 0; i < dir_n; i++) { 4934bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = xenbus_probe_device_type(bus, dir[i]); 494a39bda27b35266beae945f48e0b6ab58d06a17d5Jeremy Fitzhardinge if (err) 4954bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge break; 4964bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 497a39bda27b35266beae945f48e0b6ab58d06a17d5Jeremy Fitzhardinge 4984bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(dir); 4994bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 5004bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 5012de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_probe_devices); 5024bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5034bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic unsigned int char_count(const char *str, char c) 5044bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 5054bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge unsigned int i, ret = 0; 5064bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5074bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge for (i = 0; str[i]; i++) 5084bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (str[i] == c) 5094bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge ret++; 5104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return ret; 5114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 5124bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingestatic int strsep_len(const char *str, char c, unsigned int len) 5144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 5154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge unsigned int i; 5164bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5174bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge for (i = 0; str[i]; i++) 5184bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (str[i] == c) { 5194bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (len == 0) 5204bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return i; 5214bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge len--; 5224bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 5234bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return (len == 0) ? i : -ERANGE; 5244bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 5254bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5264bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingevoid xenbus_dev_changed(const char *node, struct xen_bus_type *bus) 5274bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 5284bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int exists, rootlen; 5294bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_device *dev; 5302a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers char type[XEN_BUS_ID_SIZE]; 5314bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge const char *p, *root; 5324bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5334bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (char_count(node, '/') < 2) 5344bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return; 5354bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5364bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge exists = xenbus_exists(XBT_NIL, node, ""); 5374bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!exists) { 5384bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_cleanup_devices(node, &bus->bus); 5394bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return; 5404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 5414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* backend/<type>/... or device/<type>/... */ 5434bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge p = strchr(node, '/') + 1; 5442a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers snprintf(type, XEN_BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p); 5452a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers type[XEN_BUS_ID_SIZE-1] = '\0'; 5464bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5474bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge rootlen = strsep_len(node, '/', bus->levels); 5484bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (rootlen < 0) 5494bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return; 5504bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge root = kasprintf(GFP_KERNEL, "%.*s", rootlen, node); 5514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!root) 5524bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return; 5534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge dev = xenbus_device_find(root, &bus->bus); 5554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (!dev) 5564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xenbus_probe_node(bus, type, root); 5574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge else 5584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge put_device(&dev->dev); 5594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5604bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge kfree(root); 5614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 562c6a960ce8858f20036cc3afc3b9422670d0d9021Jeremy FitzhardingeEXPORT_SYMBOL_GPL(xenbus_dev_changed); 5634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 564c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKIint xenbus_dev_suspend(struct device *dev) 5654bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 5664bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err = 0; 5674bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_driver *drv; 5686bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell struct xenbus_device *xdev 5696bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell = container_of(dev, struct xenbus_device, dev); 5704bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5712de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell DPRINTK("%s", xdev->nodename); 5724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5734bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (dev->driver == NULL) 5744bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 5754bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge drv = to_xenbus_driver(dev->driver); 5764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (drv->suspend) 577c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI err = drv->suspend(xdev); 5784bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) 5794bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_WARNING 5802a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers "xenbus: suspend %s failed: %i\n", dev_name(dev), err); 5814bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 5824bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 5832de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_dev_suspend); 5844bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5852de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellint xenbus_dev_resume(struct device *dev) 5864bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 5874bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err; 5884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge struct xenbus_driver *drv; 5896bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell struct xenbus_device *xdev 5906bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell = container_of(dev, struct xenbus_device, dev); 5914bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5922de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell DPRINTK("%s", xdev->nodename); 5934bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 5944bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (dev->driver == NULL) 5954bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 5964bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge drv = to_xenbus_driver(dev->driver); 5974bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = talk_to_otherend(xdev); 5984bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 5994bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_WARNING 6004bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "xenbus: resume (talk_to_otherend) %s failed: %i\n", 6012a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers dev_name(dev), err); 6024bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 6034bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 6044bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6054bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge xdev->state = XenbusStateInitialising; 6064bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6074bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (drv->resume) { 6084bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = drv->resume(xdev); 6094bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 6104bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_WARNING 6114bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "xenbus: resume %s failed: %i\n", 6122a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers dev_name(dev), err); 6134bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 6144bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 6154bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 6164bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6174bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = watch_otherend(xdev); 6184bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 6194bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_WARNING 6204bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "xenbus_probe: resume (watch_otherend) %s failed: " 6212a678cc53977c97aaf666c338f6312b7bbd3406dKay Sievers "%d.\n", dev_name(dev), err); 6224bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 6234bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 6244bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6254bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return 0; 6264bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 6272de06cc1f18d638cc7ab1169f61a8599045c2d4fIan CampbellEXPORT_SYMBOL_GPL(xenbus_dev_resume); 6284bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 629c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKIint xenbus_dev_cancel(struct device *dev) 630c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI{ 631c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI /* Do nothing */ 632c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI DPRINTK("cancel"); 633c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI return 0; 634c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI} 635c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKIEXPORT_SYMBOL_GPL(xenbus_dev_cancel); 636c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI 6374bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge/* A flag to determine if xenstored is 'ready' (i.e. has started) */ 6386913200a566b6d2866d46d7b947a2326c4e11f55Ruslan Pisarevint xenstored_ready; 6394bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6404bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6414bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingeint register_xenstore_notifier(struct notifier_block *nb) 6424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 6434bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int ret = 0; 6444bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 645a947f0f8f7012a5e8689a9cff7209ec6964ec154Stefano Stabellini if (xenstored_ready > 0) 646a947f0f8f7012a5e8689a9cff7209ec6964ec154Stefano Stabellini ret = nb->notifier_call(nb, 0, NULL); 647a947f0f8f7012a5e8689a9cff7209ec6964ec154Stefano Stabellini else 648a947f0f8f7012a5e8689a9cff7209ec6964ec154Stefano Stabellini blocking_notifier_chain_register(&xenstore_chain, nb); 6494bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6504bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return ret; 6514bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 6524bac07c993d03434ea902d3d4290d9e45944b66cJeremy FitzhardingeEXPORT_SYMBOL_GPL(register_xenstore_notifier); 6534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingevoid unregister_xenstore_notifier(struct notifier_block *nb) 6554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 6564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge blocking_notifier_chain_unregister(&xenstore_chain, nb); 6574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 6584bac07c993d03434ea902d3d4290d9e45944b66cJeremy FitzhardingeEXPORT_SYMBOL_GPL(unregister_xenstore_notifier); 6594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6604bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardingevoid xenbus_probe(struct work_struct *unused) 6614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 662a947f0f8f7012a5e8689a9cff7209ec6964ec154Stefano Stabellini xenstored_ready = 1; 6634bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 6644bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Notify others that xenstore is up */ 6654bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge blocking_notifier_call_chain(&xenstore_chain, 0, NULL); 6664bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 667183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano StabelliniEXPORT_SYMBOL_GPL(xenbus_probe); 6684bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 669183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellinistatic int __init xenbus_probe_initcall(void) 670183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini{ 671183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini if (!xen_domain()) 672183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini return -ENODEV; 673183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini 674183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini if (xen_initial_domain() || xen_hvm_domain()) 675183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini return 0; 676183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini 677183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini xenbus_probe(NULL); 678183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini return 0; 679183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini} 680183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini 681183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellinidevice_initcall(xenbus_probe_initcall); 682183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellini 683e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf/* Set up event channel for xenstored which is run as a local process 684e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf * (this is normally used only in dom0) 685e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf */ 686e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graafstatic int __init xenstored_local_init(void) 6874bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge{ 6884bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge int err = 0; 689b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela unsigned long page = 0; 690e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf struct evtchn_alloc_unbound alloc_unbound; 6914bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 692e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf /* Allocate Xenstore page */ 693e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf page = get_zeroed_page(GFP_KERNEL); 694e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (!page) 695e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf goto out_err; 6964bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 697e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_mfn = xen_start_info->store_mfn = 698e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf pfn_to_mfn(virt_to_phys((void *)page) >> 699e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf PAGE_SHIFT); 7004bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 701e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf /* Next allocate a local port which xenstored can bind to */ 702e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf alloc_unbound.dom = DOMID_SELF; 703e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf alloc_unbound.remote_dom = DOMID_SELF; 704b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela 705e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, 706e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf &alloc_unbound); 707e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (err == -ENOSYS) 708e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf goto out_err; 709b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela 710e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf BUG_ON(err); 711e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_evtchn = xen_start_info->store_evtchn = 712e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf alloc_unbound.port; 713b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela 714e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf return 0; 715b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela 716e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf out_err: 717e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (page != 0) 718e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf free_page(page); 719e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf return err; 720e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf} 721b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela 722e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graafstatic int __init xenbus_init(void) 723e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf{ 724e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf int err = 0; 725b37a56d6f3c0595d8d65ddd5b7610d11735c4978Juan Quintela 726e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (!xen_domain()) 727e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf return -ENODEV; 728e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf 7292c5d37d30fbd27d424a18abc16786cb152a37017Daniel De Graaf xenbus_ring_ops_init(); 7302c5d37d30fbd27d424a18abc16786cb152a37017Daniel De Graaf 731e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (xen_hvm_domain()) { 732e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf uint64_t v = 0; 733e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); 734e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (err) 735e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf goto out_error; 736e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_evtchn = (int)v; 737e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); 738e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (err) 739e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf goto out_error; 740e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_mfn = (unsigned long)v; 741e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); 7424bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } else { 743e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_evtchn = xen_start_info->store_evtchn; 744e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_mfn = xen_start_info->store_mfn; 745e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf if (xen_store_evtchn) 746e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xenstored_ready = 1; 747e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf else { 748e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf err = xenstored_local_init(); 749bee6ab53e652a414af20392899879b58cd80d033Sheng Yang if (err) 750bee6ab53e652a414af20392899879b58cd80d033Sheng Yang goto out_error; 751bee6ab53e652a414af20392899879b58cd80d033Sheng Yang } 752e4184aaf3b2c4f2b69306f6cfc4bab8733c6c5f1Daniel De Graaf xen_store_interface = mfn_to_virt(xen_store_mfn); 7534bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 7544bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 7554bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge /* Initialize the interface to xenstore. */ 7564bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge err = xs_init(); 7574bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge if (err) { 7584bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge printk(KERN_WARNING 7594bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge "XENBUS: Error initializing xenstore comms: %i\n", err); 7602de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell goto out_error; 7614bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge } 7624bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 7631107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt#ifdef CONFIG_XEN_COMPAT_XENFS 7641107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt /* 7651107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt * Create xenfs mountpoint in /proc for compatibility with 7661107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt * utilities that expect to find "xenbus" under "/proc/xen". 7671107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt */ 7681107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt proc_mkdir("xen", NULL); 7691107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt#endif 7701107ba885e46964316c083d441d5dd185b6c9e49Alex Zeffertt 7716913200a566b6d2866d46d7b947a2326c4e11f55Ruslan Pisarevout_error: 7724bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge return err; 7734bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge} 7744bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 775183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3cStefano Stabellinipostcore_initcall(xenbus_init); 7764bac07c993d03434ea902d3d4290d9e45944b66cJeremy Fitzhardinge 7774bac07c993d03434ea902d3d4290d9e45944b66cJeremy FitzhardingeMODULE_LICENSE("GPL"); 778