 283c0972d5
			
		
	
	
	283c0972d5
	
	
	
		
			
			Convert printks to pr_<level> (excludes printk(KERN_DEBUG...) to be more consistent throughout the xen subsystem. Add pr_fmt with KBUILD_MODNAME or "xen:" KBUILD_MODNAME Coalesce formats and add missing word spaces Add missing newlines Align arguments and reflow to 80 columns Remove DRV_NAME from formats as pr_fmt adds the same content This does change some of the prefixes of these messages but it also does make them more consistent. Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
		
			
				
	
	
		
			243 lines
		
	
	
	
		
			6.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
	
		
			6.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /******************************************************************************
 | |
|  * xenbus_comms.c
 | |
|  *
 | |
|  * Low level code to talks to Xen Store: ringbuffer and event channel.
 | |
|  *
 | |
|  * Copyright (C) 2005 Rusty Russell, IBM Corporation
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License version 2
 | |
|  * as published by the Free Software Foundation; or, when distributed
 | |
|  * separately from the Linux kernel or incorporated into other
 | |
|  * software packages, subject to the following license:
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
|  * of this source file (the "Software"), to deal in the Software without
 | |
|  * restriction, including without limitation the rights to use, copy, modify,
 | |
|  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
 | |
|  * and to permit persons to whom the Software is furnished to do so, subject to
 | |
|  * the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | |
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 | |
|  * IN THE SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | |
| 
 | |
| #include <linux/wait.h>
 | |
| #include <linux/interrupt.h>
 | |
| #include <linux/sched.h>
 | |
| #include <linux/err.h>
 | |
| #include <xen/xenbus.h>
 | |
| #include <asm/xen/hypervisor.h>
 | |
| #include <xen/events.h>
 | |
| #include <xen/page.h>
 | |
| #include "xenbus_comms.h"
 | |
| 
 | |
| static int xenbus_irq;
 | |
| 
 | |
| static DECLARE_WORK(probe_work, xenbus_probe);
 | |
| 
 | |
| static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 | |
| 
 | |
| static irqreturn_t wake_waiting(int irq, void *unused)
 | |
| {
 | |
| 	if (unlikely(xenstored_ready == 0)) {
 | |
| 		xenstored_ready = 1;
 | |
| 		schedule_work(&probe_work);
 | |
| 	}
 | |
| 
 | |
| 	wake_up(&xb_waitq);
 | |
| 	return IRQ_HANDLED;
 | |
| }
 | |
| 
 | |
| static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
 | |
| {
 | |
| 	return ((prod - cons) <= XENSTORE_RING_SIZE);
 | |
| }
 | |
| 
 | |
| static void *get_output_chunk(XENSTORE_RING_IDX cons,
 | |
| 			      XENSTORE_RING_IDX prod,
 | |
| 			      char *buf, uint32_t *len)
 | |
| {
 | |
| 	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
 | |
| 	if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
 | |
| 		*len = XENSTORE_RING_SIZE - (prod - cons);
 | |
| 	return buf + MASK_XENSTORE_IDX(prod);
 | |
| }
 | |
| 
 | |
| static const void *get_input_chunk(XENSTORE_RING_IDX cons,
 | |
| 				   XENSTORE_RING_IDX prod,
 | |
| 				   const char *buf, uint32_t *len)
 | |
| {
 | |
| 	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
 | |
| 	if ((prod - cons) < *len)
 | |
| 		*len = prod - cons;
 | |
| 	return buf + MASK_XENSTORE_IDX(cons);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xb_write - low level write
 | |
|  * @data: buffer to send
 | |
|  * @len: length of buffer
 | |
|  *
 | |
|  * Returns 0 on success, error otherwise.
 | |
|  */
 | |
| int xb_write(const void *data, unsigned len)
 | |
| {
 | |
| 	struct xenstore_domain_interface *intf = xen_store_interface;
 | |
| 	XENSTORE_RING_IDX cons, prod;
 | |
| 	int rc;
 | |
| 
 | |
| 	while (len != 0) {
 | |
| 		void *dst;
 | |
| 		unsigned int avail;
 | |
| 
 | |
| 		rc = wait_event_interruptible(
 | |
| 			xb_waitq,
 | |
| 			(intf->req_prod - intf->req_cons) !=
 | |
| 			XENSTORE_RING_SIZE);
 | |
| 		if (rc < 0)
 | |
| 			return rc;
 | |
| 
 | |
| 		/* Read indexes, then verify. */
 | |
| 		cons = intf->req_cons;
 | |
| 		prod = intf->req_prod;
 | |
| 		if (!check_indexes(cons, prod)) {
 | |
| 			intf->req_cons = intf->req_prod = 0;
 | |
| 			return -EIO;
 | |
| 		}
 | |
| 
 | |
| 		dst = get_output_chunk(cons, prod, intf->req, &avail);
 | |
| 		if (avail == 0)
 | |
| 			continue;
 | |
| 		if (avail > len)
 | |
| 			avail = len;
 | |
| 
 | |
| 		/* Must write data /after/ reading the consumer index. */
 | |
| 		mb();
 | |
| 
 | |
| 		memcpy(dst, data, avail);
 | |
| 		data += avail;
 | |
| 		len -= avail;
 | |
| 
 | |
| 		/* Other side must not see new producer until data is there. */
 | |
| 		wmb();
 | |
| 		intf->req_prod += avail;
 | |
| 
 | |
| 		/* Implies mb(): other side will see the updated producer. */
 | |
| 		notify_remote_via_evtchn(xen_store_evtchn);
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int xb_data_to_read(void)
 | |
| {
 | |
| 	struct xenstore_domain_interface *intf = xen_store_interface;
 | |
| 	return (intf->rsp_cons != intf->rsp_prod);
 | |
| }
 | |
| 
 | |
| int xb_wait_for_data_to_read(void)
 | |
| {
 | |
| 	return wait_event_interruptible(xb_waitq, xb_data_to_read());
 | |
| }
 | |
| 
 | |
| int xb_read(void *data, unsigned len)
 | |
| {
 | |
| 	struct xenstore_domain_interface *intf = xen_store_interface;
 | |
| 	XENSTORE_RING_IDX cons, prod;
 | |
| 	int rc;
 | |
| 
 | |
| 	while (len != 0) {
 | |
| 		unsigned int avail;
 | |
| 		const char *src;
 | |
| 
 | |
| 		rc = xb_wait_for_data_to_read();
 | |
| 		if (rc < 0)
 | |
| 			return rc;
 | |
| 
 | |
| 		/* Read indexes, then verify. */
 | |
| 		cons = intf->rsp_cons;
 | |
| 		prod = intf->rsp_prod;
 | |
| 		if (!check_indexes(cons, prod)) {
 | |
| 			intf->rsp_cons = intf->rsp_prod = 0;
 | |
| 			return -EIO;
 | |
| 		}
 | |
| 
 | |
| 		src = get_input_chunk(cons, prod, intf->rsp, &avail);
 | |
| 		if (avail == 0)
 | |
| 			continue;
 | |
| 		if (avail > len)
 | |
| 			avail = len;
 | |
| 
 | |
| 		/* Must read data /after/ reading the producer index. */
 | |
| 		rmb();
 | |
| 
 | |
| 		memcpy(data, src, avail);
 | |
| 		data += avail;
 | |
| 		len -= avail;
 | |
| 
 | |
| 		/* Other side must not see free space until we've copied out */
 | |
| 		mb();
 | |
| 		intf->rsp_cons += avail;
 | |
| 
 | |
| 		pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
 | |
| 
 | |
| 		/* Implies mb(): other side will see the updated consumer. */
 | |
| 		notify_remote_via_evtchn(xen_store_evtchn);
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xb_init_comms - Set up interrupt handler off store event channel.
 | |
|  */
 | |
| int xb_init_comms(void)
 | |
| {
 | |
| 	struct xenstore_domain_interface *intf = xen_store_interface;
 | |
| 
 | |
| 	if (intf->req_prod != intf->req_cons)
 | |
| 		pr_err("request ring is not quiescent (%08x:%08x)!\n",
 | |
| 		       intf->req_cons, intf->req_prod);
 | |
| 
 | |
| 	if (intf->rsp_prod != intf->rsp_cons) {
 | |
| 		pr_warn("response ring is not quiescent (%08x:%08x): fixing up\n",
 | |
| 			intf->rsp_cons, intf->rsp_prod);
 | |
| 		/* breaks kdump */
 | |
| 		if (!reset_devices)
 | |
| 			intf->rsp_cons = intf->rsp_prod;
 | |
| 	}
 | |
| 
 | |
| 	if (xenbus_irq) {
 | |
| 		/* Already have an irq; assume we're resuming */
 | |
| 		rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
 | |
| 	} else {
 | |
| 		int err;
 | |
| 		err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting,
 | |
| 						0, "xenbus", &xb_waitq);
 | |
| 		if (err < 0) {
 | |
| 			pr_err("request irq failed %i\n", err);
 | |
| 			return err;
 | |
| 		}
 | |
| 
 | |
| 		xenbus_irq = err;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void xb_deinit_comms(void)
 | |
| {
 | |
| 	unbind_from_irqhandler(xenbus_irq, &xb_waitq);
 | |
| 	xenbus_irq = 0;
 | |
| }
 |