Home | History | Annotate | Line # | Download | only in xenbus
xenbus_client.c revision 1.4.10.6
      1  1.4.10.6  yamt /* $NetBSD: xenbus_client.c,v 1.4.10.6 2008/01/21 09:40:38 yamt Exp $ */
      2  1.4.10.2  yamt /******************************************************************************
      3  1.4.10.2  yamt  * Client-facing interface for the Xenbus driver.  In other words, the
      4  1.4.10.2  yamt  * interface between the Xenbus and the device-specific code, be it the
      5  1.4.10.2  yamt  * frontend or the backend of that driver.
      6  1.4.10.2  yamt  *
      7  1.4.10.2  yamt  * Copyright (C) 2005 XenSource Ltd
      8  1.4.10.2  yamt  *
      9  1.4.10.2  yamt  * This file may be distributed separately from the Linux kernel, or
     10  1.4.10.2  yamt  * incorporated into other software packages, subject to the following license:
     11  1.4.10.2  yamt  *
     12  1.4.10.2  yamt  * Permission is hereby granted, free of charge, to any person obtaining a copy
     13  1.4.10.2  yamt  * of this source file (the "Software"), to deal in the Software without
     14  1.4.10.2  yamt  * restriction, including without limitation the rights to use, copy, modify,
     15  1.4.10.2  yamt  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
     16  1.4.10.2  yamt  * and to permit persons to whom the Software is furnished to do so, subject to
     17  1.4.10.2  yamt  * the following conditions:
     18  1.4.10.2  yamt  *
     19  1.4.10.2  yamt  * The above copyright notice and this permission notice shall be included in
     20  1.4.10.2  yamt  * all copies or substantial portions of the Software.
     21  1.4.10.2  yamt  *
     22  1.4.10.2  yamt  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23  1.4.10.2  yamt  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24  1.4.10.2  yamt  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     25  1.4.10.2  yamt  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     26  1.4.10.2  yamt  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     27  1.4.10.2  yamt  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     28  1.4.10.2  yamt  * IN THE SOFTWARE.
     29  1.4.10.2  yamt  */
     30  1.4.10.2  yamt 
     31  1.4.10.2  yamt #include <sys/cdefs.h>
     32  1.4.10.6  yamt __KERNEL_RCSID(0, "$NetBSD: xenbus_client.c,v 1.4.10.6 2008/01/21 09:40:38 yamt Exp $");
     33  1.4.10.2  yamt 
     34  1.4.10.2  yamt #if 0
     35  1.4.10.2  yamt #define DPRINTK(fmt, args...) \
     36  1.4.10.6  yamt     printk("xenbus_client (%s:%d) " fmt ".\n", __func__, __LINE__, ##args)
     37  1.4.10.2  yamt #else
     38  1.4.10.2  yamt #define DPRINTK(fmt, args...) ((void)0)
     39  1.4.10.2  yamt #endif
     40  1.4.10.2  yamt 
     41  1.4.10.2  yamt #include <sys/types.h>
     42  1.4.10.2  yamt #include <sys/null.h>
     43  1.4.10.2  yamt #include <sys/errno.h>
     44  1.4.10.2  yamt #include <sys/malloc.h>
     45  1.4.10.2  yamt #include <sys/systm.h>
     46  1.4.10.2  yamt 
     47  1.4.10.2  yamt #include <machine/stdarg.h>
     48  1.4.10.2  yamt 
     49  1.4.10.5  yamt #include <xen/xen.h>
     50  1.4.10.5  yamt #include <xen/hypervisor.h>
     51  1.4.10.5  yamt #include <xen/evtchn.h>
     52  1.4.10.5  yamt #include <xen/xenbus.h>
     53  1.4.10.5  yamt #include <xen/granttables.h>
     54  1.4.10.2  yamt 
     55  1.4.10.2  yamt 
     56  1.4.10.2  yamt int
     57  1.4.10.2  yamt xenbus_watch_path(struct xenbus_device *dev, char *path,
     58  1.4.10.2  yamt 		      struct xenbus_watch *watch,
     59  1.4.10.2  yamt 		      void (*callback)(struct xenbus_watch *,
     60  1.4.10.2  yamt 				       const char **, unsigned int))
     61  1.4.10.2  yamt {
     62  1.4.10.2  yamt 	int err;
     63  1.4.10.2  yamt 
     64  1.4.10.2  yamt 	watch->node = path;
     65  1.4.10.2  yamt 	watch->xbw_callback = callback;
     66  1.4.10.2  yamt 
     67  1.4.10.2  yamt 	err = register_xenbus_watch(watch);
     68  1.4.10.2  yamt 
     69  1.4.10.2  yamt 	if (err) {
     70  1.4.10.2  yamt 		watch->node = NULL;
     71  1.4.10.2  yamt 		watch->xbw_callback = NULL;
     72  1.4.10.2  yamt 		xenbus_dev_fatal(dev, err, "adding watch on %s", path);
     73  1.4.10.2  yamt 	}
     74  1.4.10.2  yamt 	err = 0;
     75  1.4.10.2  yamt 
     76  1.4.10.2  yamt 	return err;
     77  1.4.10.2  yamt }
     78  1.4.10.2  yamt 
     79  1.4.10.2  yamt int
     80  1.4.10.2  yamt xenbus_watch_path2(struct xenbus_device *dev, const char *path,
     81  1.4.10.2  yamt 		       const char *path2, struct xenbus_watch *watch,
     82  1.4.10.2  yamt 		       void (*callback)(struct xenbus_watch *,
     83  1.4.10.2  yamt 					const char **, unsigned int))
     84  1.4.10.2  yamt {
     85  1.4.10.2  yamt 	int err;
     86  1.4.10.2  yamt 	char *state;
     87  1.4.10.2  yamt 
     88  1.4.10.2  yamt 	DPRINTK("xenbus_watch_path2 path %s path2 %s\n", path, path2);
     89  1.4.10.2  yamt 	state =
     90  1.4.10.2  yamt 		malloc(strlen(path) + 1 + strlen(path2) + 1, M_DEVBUF,
     91  1.4.10.2  yamt 		    M_NOWAIT);
     92  1.4.10.2  yamt 	if (!state) {
     93  1.4.10.2  yamt 		xenbus_dev_fatal(dev, ENOMEM, "allocating path for watch");
     94  1.4.10.2  yamt 		return ENOMEM;
     95  1.4.10.2  yamt 	}
     96  1.4.10.2  yamt 	strcpy(state, path);
     97  1.4.10.2  yamt 	strcat(state, "/");
     98  1.4.10.2  yamt 	strcat(state, path2);
     99  1.4.10.2  yamt 
    100  1.4.10.2  yamt 	err = xenbus_watch_path(dev, state, watch, callback);
    101  1.4.10.2  yamt 
    102  1.4.10.2  yamt 	if (err) {
    103  1.4.10.2  yamt 		free(state, M_DEVBUF);
    104  1.4.10.2  yamt 	}
    105  1.4.10.2  yamt 	return err;
    106  1.4.10.2  yamt }
    107  1.4.10.2  yamt 
    108  1.4.10.2  yamt 
    109  1.4.10.2  yamt int
    110  1.4.10.2  yamt xenbus_switch_state(struct xenbus_device *dev,
    111  1.4.10.2  yamt 			struct xenbus_transaction *xbt,
    112  1.4.10.2  yamt 			XenbusState state)
    113  1.4.10.2  yamt {
    114  1.4.10.2  yamt 	/* We check whether the state is currently set to the given value, and
    115  1.4.10.2  yamt 	   if not, then the state is set.  We don't want to unconditionally
    116  1.4.10.2  yamt 	   write the given state, because we don't want to fire watches
    117  1.4.10.2  yamt 	   unnecessarily.  Furthermore, if the node has gone, we don't write
    118  1.4.10.2  yamt 	   to it, as the device will be tearing down, and we don't want to
    119  1.4.10.2  yamt 	   resurrect that directory.
    120  1.4.10.2  yamt 	 */
    121  1.4.10.2  yamt 
    122  1.4.10.2  yamt 	u_long current_state;
    123  1.4.10.2  yamt 
    124  1.4.10.3  yamt 	int err = xenbus_read_ul(xbt, dev->xbusd_path, "state",
    125  1.4.10.3  yamt 	    &current_state, 10);
    126  1.4.10.2  yamt 	if (err)
    127  1.4.10.2  yamt 		return 0;
    128  1.4.10.2  yamt 
    129  1.4.10.2  yamt 	if ((XenbusState)current_state == state)
    130  1.4.10.2  yamt 		return 0;
    131  1.4.10.2  yamt 
    132  1.4.10.2  yamt 	err = xenbus_printf(xbt, dev->xbusd_path, "state", "%d", state);
    133  1.4.10.2  yamt 	if (err) {
    134  1.4.10.2  yamt 		xenbus_dev_fatal(dev, err, "writing new state");
    135  1.4.10.2  yamt 		return err;
    136  1.4.10.2  yamt 	}
    137  1.4.10.2  yamt 	return 0;
    138  1.4.10.2  yamt }
    139  1.4.10.2  yamt 
    140  1.4.10.2  yamt /**
    141  1.4.10.2  yamt  * Return the path to the error node for the given device, or NULL on failure.
    142  1.4.10.2  yamt  * If the value returned is non-NULL, then it is the caller's to kfree.
    143  1.4.10.2  yamt  */
    144  1.4.10.2  yamt static char *
    145  1.4.10.2  yamt error_path(struct xenbus_device *dev)
    146  1.4.10.2  yamt {
    147  1.4.10.2  yamt 	char *path_buffer = malloc(strlen("error/") + strlen(dev->xbusd_path) +
    148  1.4.10.2  yamt 				    1, M_DEVBUF, M_NOWAIT);
    149  1.4.10.2  yamt 	if (path_buffer == NULL) {
    150  1.4.10.2  yamt 		return NULL;
    151  1.4.10.2  yamt 	}
    152  1.4.10.2  yamt 
    153  1.4.10.2  yamt 	strcpy(path_buffer, "error/");
    154  1.4.10.2  yamt 	strcpy(path_buffer + strlen("error/"), dev->xbusd_path);
    155  1.4.10.2  yamt 
    156  1.4.10.2  yamt 	return path_buffer;
    157  1.4.10.2  yamt }
    158  1.4.10.2  yamt 
    159  1.4.10.2  yamt 
    160  1.4.10.2  yamt static void
    161  1.4.10.2  yamt _dev_error(struct xenbus_device *dev, int err, const char *fmt,
    162  1.4.10.2  yamt 		va_list ap)
    163  1.4.10.2  yamt {
    164  1.4.10.2  yamt 	int ret;
    165  1.4.10.2  yamt 	unsigned int len;
    166  1.4.10.2  yamt 	char *printf_buffer = NULL, *path_buffer = NULL;
    167  1.4.10.2  yamt 
    168  1.4.10.2  yamt #define PRINTF_BUFFER_SIZE 4096
    169  1.4.10.2  yamt 	printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_NOWAIT);
    170  1.4.10.2  yamt 	if (printf_buffer == NULL)
    171  1.4.10.2  yamt 		goto fail;
    172  1.4.10.2  yamt 
    173  1.4.10.2  yamt 	len = sprintf(printf_buffer, "%i ", -err);
    174  1.4.10.2  yamt 	ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
    175  1.4.10.2  yamt 
    176  1.4.10.2  yamt 	KASSERT(len + ret < PRINTF_BUFFER_SIZE);
    177  1.4.10.2  yamt 	dev->xbusd_has_error = 1;
    178  1.4.10.2  yamt 
    179  1.4.10.2  yamt 	path_buffer = error_path(dev);
    180  1.4.10.2  yamt 
    181  1.4.10.2  yamt 	if (path_buffer == NULL) {
    182  1.4.10.2  yamt 		printk("xenbus: failed to write error node for %s (%s)\n",
    183  1.4.10.2  yamt 		       dev->xbusd_path, printf_buffer);
    184  1.4.10.2  yamt 		goto fail;
    185  1.4.10.2  yamt 	}
    186  1.4.10.2  yamt 
    187  1.4.10.2  yamt 	if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) {
    188  1.4.10.2  yamt 		printk("xenbus: failed to write error node for %s (%s)\n",
    189  1.4.10.2  yamt 		       dev->xbusd_path, printf_buffer);
    190  1.4.10.2  yamt 		goto fail;
    191  1.4.10.2  yamt 	}
    192  1.4.10.2  yamt 
    193  1.4.10.2  yamt fail:
    194  1.4.10.2  yamt 	if (printf_buffer)
    195  1.4.10.2  yamt 		free(printf_buffer, M_DEVBUF);
    196  1.4.10.2  yamt 	if (path_buffer)
    197  1.4.10.2  yamt 		free(path_buffer, M_DEVBUF);
    198  1.4.10.2  yamt }
    199  1.4.10.2  yamt 
    200  1.4.10.2  yamt 
    201  1.4.10.2  yamt void
    202  1.4.10.2  yamt xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
    203  1.4.10.2  yamt 		      ...)
    204  1.4.10.2  yamt {
    205  1.4.10.2  yamt 	va_list ap;
    206  1.4.10.2  yamt 
    207  1.4.10.2  yamt 	va_start(ap, fmt);
    208  1.4.10.2  yamt 	_dev_error(dev, err, fmt, ap);
    209  1.4.10.2  yamt 	va_end(ap);
    210  1.4.10.2  yamt }
    211  1.4.10.2  yamt 
    212  1.4.10.2  yamt 
    213  1.4.10.2  yamt void
    214  1.4.10.2  yamt xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
    215  1.4.10.2  yamt 		      ...)
    216  1.4.10.2  yamt {
    217  1.4.10.2  yamt 	va_list ap;
    218  1.4.10.2  yamt 
    219  1.4.10.2  yamt 	va_start(ap, fmt);
    220  1.4.10.2  yamt 	_dev_error(dev, err, fmt, ap);
    221  1.4.10.2  yamt 	va_end(ap);
    222  1.4.10.2  yamt 
    223  1.4.10.2  yamt 	xenbus_switch_state(dev, NULL, XenbusStateClosing);
    224  1.4.10.2  yamt }
    225  1.4.10.2  yamt 
    226  1.4.10.2  yamt 
    227  1.4.10.2  yamt int
    228  1.4.10.2  yamt xenbus_grant_ring(struct xenbus_device *dev, paddr_t ring_pa,
    229  1.4.10.2  yamt     grant_ref_t *entryp)
    230  1.4.10.2  yamt {
    231  1.4.10.2  yamt 	int err = xengnt_grant_access(dev->xbusd_otherend_id, ring_pa,
    232  1.4.10.2  yamt 	    0, entryp);
    233  1.4.10.2  yamt 	if (err != 0)
    234  1.4.10.2  yamt 		xenbus_dev_fatal(dev, err, "granting access to ring page");
    235  1.4.10.2  yamt 	return err;
    236  1.4.10.2  yamt }
    237  1.4.10.2  yamt 
    238  1.4.10.2  yamt 
    239  1.4.10.2  yamt int
    240  1.4.10.2  yamt xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
    241  1.4.10.2  yamt {
    242  1.4.10.2  yamt 	evtchn_op_t op = {
    243  1.4.10.2  yamt 		.cmd = EVTCHNOP_alloc_unbound,
    244  1.4.10.2  yamt 		.u.alloc_unbound.dom = DOMID_SELF,
    245  1.4.10.2  yamt 		.u.alloc_unbound.remote_dom = dev->xbusd_otherend_id };
    246  1.4.10.2  yamt 
    247  1.4.10.2  yamt 	int err = HYPERVISOR_event_channel_op(&op);
    248  1.4.10.2  yamt 	if (err)
    249  1.4.10.2  yamt 		xenbus_dev_fatal(dev, err, "allocating event channel");
    250  1.4.10.2  yamt 	else
    251  1.4.10.2  yamt 		*port = op.u.alloc_unbound.port;
    252  1.4.10.2  yamt 	return err;
    253  1.4.10.2  yamt }
    254  1.4.10.2  yamt 
    255  1.4.10.2  yamt 
    256  1.4.10.2  yamt XenbusState
    257  1.4.10.2  yamt xenbus_read_driver_state(const char *path)
    258  1.4.10.2  yamt {
    259  1.4.10.2  yamt 	u_long result;
    260  1.4.10.2  yamt 
    261  1.4.10.3  yamt 	int err = xenbus_read_ul(NULL, path, "state", &result, 10);
    262  1.4.10.2  yamt 	if (err)
    263  1.4.10.2  yamt 		result = XenbusStateClosed;
    264  1.4.10.2  yamt 
    265  1.4.10.2  yamt 	return result;
    266  1.4.10.2  yamt }
    267  1.4.10.2  yamt 
    268  1.4.10.2  yamt 
    269  1.4.10.2  yamt /*
    270  1.4.10.2  yamt  * Local variables:
    271  1.4.10.2  yamt  *  c-file-style: "linux"
    272  1.4.10.2  yamt  *  indent-tabs-mode: t
    273  1.4.10.2  yamt  *  c-indent-level: 8
    274  1.4.10.2  yamt  *  c-basic-offset: 8
    275  1.4.10.2  yamt  *  tab-width: 8
    276  1.4.10.2  yamt  * End:
    277  1.4.10.2  yamt  */
    278