All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][2/17] USB virt 2.6 split driver---xenidc buffer resource provider
@ 2005-11-21 13:18 harry
  2005-11-21 20:18 ` Muli Ben-Yehuda
  0 siblings, 1 reply; 9+ messages in thread
From: harry @ 2005-11-21 13:18 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 186 bytes --]

This patch implements a resource pool for buffer resources used by the
xenidc transport which is in turn used by the USB driver.

Signed-off-by: Harry Butterworth <butterwo@uk.ibm.com>


[-- Attachment #2: p2-xenidc-buffer-resource-provider.patch --]
[-- Type: text/x-patch, Size: 19255 bytes --]

diff -r 7adcceaaf851 -r 1e2c0ff9c46a linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Sun Nov 20 14:53:27 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Sun Nov 20 14:53:55 2005
@@ -3,3 +3,4 @@
 xenidc-objs =
 xenidc-objs += xenidc_callback.o
 xenidc-objs += xenidc_work.o
+xenidc-objs += xenidc_buffer_resource_provider.o
diff -r 7adcceaaf851 -r 1e2c0ff9c46a linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_buffer_resource_provider.c
--- /dev/null	Sun Nov 20 14:53:27 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_buffer_resource_provider.c	Sun Nov 20 14:53:55 2005
@@ -0,0 +1,443 @@
+/*****************************************************************************/
+/* Xen inter-domain communication buffer resource provider.                  */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify it   */
+/* under the terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2 of the License, or (at your    */
+/* option) any later version.                                                */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful, but       */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of                */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General */
+/* Public License for more details.                                          */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License along   */
+/* with this program; if not, write to the Free Software Foundation, Inc.,   */
+/* 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                   */
+/*                                                                           */
+/*****************************************************************************/
+/*****************************************************************************/
+/* Based on                                                                  */
+/*                                                                           */
+/* arch/xen/drivers/blkback/blkback.c                                        */
+/*                                                                           */
+/* original copyright notice follows...                                      */
+/*****************************************************************************/
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/main.c
+ * 
+ * Back-end of the driver for virtual block devices. This portion of the
+ * driver exports a 'unified' block-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A 
+ * reference front-end implementation can be found in:
+ *  arch/xen/drivers/blkif/frontend
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Copyright (c) 2005, Christopher Clark
+ */
+
+#include <asm/pgalloc.h>
+#include <linux/spinlock.h>
+#include <asm-xen/balloon.h>
+#include <asm-xen/driver_util.h>
+#include <asm-xen/xenidc_buffer_resource_provider.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include "xenidc_trace.h"
+
+struct xenidc_buffer_resource_provider_struct {
+	spinlock_t lock;
+	xenidc_buffer_resource_list resource_allocation;
+	xenidc_buffer_resource_list free_resources;
+	struct list_head page_list;
+	grant_ref_t grant_ref_pool;
+	struct page *page;
+	unsigned long mmap_vstart;
+	struct list_head empty_page_range_list;
+	struct list_head *empty_page_range_link;
+};
+
+static int xenidc_buffer_resource_provider_init_or_exit
+    (xenidc_buffer_resource_provider * provider, int exit) {
+	trace1("%p", provider);
+
+	{
+		int return_value = 0;
+
+		if (exit) {
+			goto EXIT;
+		}
+
+		spin_lock_init(&provider->lock);
+
+		provider->free_resources = xenidc_buffer_resource_list_null();
+
+		INIT_LIST_HEAD(&provider->page_list);
+
+		{
+			int i;
+
+			for (i = 0; i < provider->resource_allocation.pages;
+			     i++) {
+				void *page =
+				    (void *)__get_free_page(GFP_KERNEL);
+
+				if (page == NULL) {
+					return_value = -ENOMEM;
+
+					goto EXIT_NO_PAGE;
+				}
+
+				xenidc_buffer_resource_provider_free_page
+				    (provider, page);
+			}
+		}
+
+		if (provider->resource_allocation.grant_references != 0) {
+			return_value = gnttab_alloc_grant_references
+			    (provider->resource_allocation.grant_references,
+			     &provider->grant_ref_pool);
+
+			if (return_value != 0) {
+				trace0
+				    ("failed to allocate grant reference pool");
+
+				goto EXIT_NO_GRANT_REF;
+			}
+
+			provider->free_resources.grant_references =
+			    provider->resource_allocation.grant_references;
+		}
+
+		if (provider->resource_allocation.empty_page_ranges != 0) {
+			provider->page = balloon_alloc_empty_page_range
+			    (provider->resource_allocation.empty_page_ranges
+			     *
+			     provider->resource_allocation.
+			     empty_page_range_page_count);
+
+			if (provider->page == NULL) {
+				return_value = -ENOMEM;
+
+				goto EXIT_NO_EMPTY_PAGE_RANGE;
+			}
+
+			provider->mmap_vstart =
+			    (unsigned long)
+			    pfn_to_kaddr(page_to_pfn(provider->page));
+
+			INIT_LIST_HEAD(&provider->empty_page_range_list);
+
+			provider->empty_page_range_link = vmalloc
+			    (sizeof(struct list_head)
+			     * provider->resource_allocation.empty_page_ranges);
+
+			if (provider->empty_page_range_link == NULL) {
+				return_value = -ENOMEM;
+
+				goto EXIT_NO_EMPTY_PAGE_RANGE_LINK;
+			}
+
+			{
+				int i;
+
+				for (i = 0;
+				     i <
+				     provider->resource_allocation.
+				     empty_page_ranges; i++) {
+					struct list_head *link =
+					    &provider->empty_page_range_link[i];
+
+					INIT_LIST_HEAD(link);
+
+					list_add(link,
+						 &provider->
+						 empty_page_range_list);
+				}
+			}
+
+			provider->free_resources.empty_page_ranges =
+			    provider->resource_allocation.empty_page_ranges;
+
+			provider->free_resources.empty_page_range_page_count =
+			    provider->resource_allocation.
+			    empty_page_range_page_count;
+		}
+
+		return 0;
+
+	      EXIT:
+
+		if (provider->resource_allocation.empty_page_ranges != 0) {
+			vfree(provider->empty_page_range_link);
+
+		      EXIT_NO_EMPTY_PAGE_RANGE_LINK:
+
+			balloon_dealloc_empty_page_range
+			    (provider->page,
+			     provider->resource_allocation.empty_page_ranges
+			     *
+			     provider->resource_allocation.
+			     empty_page_range_page_count);
+		}
+
+	      EXIT_NO_EMPTY_PAGE_RANGE:
+
+		if (provider->resource_allocation.grant_references != 0) {
+			gnttab_free_grant_references(provider->grant_ref_pool);
+		}
+
+	      EXIT_NO_GRANT_REF:
+
+	      EXIT_NO_PAGE:
+
+		while (!list_empty(&provider->page_list)) {
+			free_page
+			    ((unsigned long)
+			     xenidc_buffer_resource_provider_allocate_page
+			     (provider)
+			    );
+		}
+
+		return return_value;
+	}
+}
+
+xenidc_buffer_resource_provider *xenidc_allocate_buffer_resource_provider
+    (xenidc_buffer_resource_list resource_allocation) {
+	trace();
+
+	{
+		xenidc_buffer_resource_provider *provider =
+		    (xenidc_buffer_resource_provider *)
+		    vmalloc(sizeof(xenidc_buffer_resource_provider));
+
+		if (provider != NULL) {
+			provider->resource_allocation = resource_allocation;
+
+			if (xenidc_buffer_resource_provider_init_or_exit
+			    (provider, 0)
+			    != 0) {
+				vfree(provider);
+
+				provider = NULL;
+			}
+		}
+
+		return provider;
+	}
+}
+
+void xenidc_free_buffer_resource_provider
+    (xenidc_buffer_resource_provider * provider) {
+	trace();
+
+	(void)xenidc_buffer_resource_provider_init_or_exit(provider, 1);
+
+	vfree(provider);
+}
+
+xenidc_buffer_resource_list
+    xenidc_buffer_resource_provider_query_free_resources
+    (xenidc_buffer_resource_provider * provider) {
+	trace();
+
+	{
+		xenidc_buffer_resource_list list;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&provider->lock, flags);
+
+		list = provider->free_resources;
+
+		spin_unlock_irqrestore(&provider->lock, flags);
+
+		return list;
+	}
+}
+
+void *xenidc_buffer_resource_provider_allocate_page
+    (xenidc_buffer_resource_provider * provider) {
+	trace();
+
+	{
+		struct list_head *link;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&provider->lock, flags);
+
+		provider->free_resources.pages--;
+
+		link = provider->page_list.next;
+
+		trace1("%p", link);
+
+		list_del(link);
+
+		spin_unlock_irqrestore(&provider->lock, flags);
+
+		return link;
+	}
+}
+
+void xenidc_buffer_resource_provider_free_page
+    (xenidc_buffer_resource_provider * provider, void *page) {
+	trace1("%p", page);
+
+	{
+		struct list_head *link = page;
+
+		INIT_LIST_HEAD(link);
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&provider->lock, flags);
+
+			provider->free_resources.pages++;
+
+			list_add(link, &provider->page_list);
+
+			spin_unlock_irqrestore(&provider->lock, flags);
+		}
+	}
+}
+
+grant_ref_t xenidc_buffer_resource_provider_allocate_grant_reference
+    (xenidc_buffer_resource_provider * provider) {
+	trace();
+
+	{
+		grant_ref_t reference;
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&provider->lock, flags);
+
+			provider->free_resources.grant_references--;
+
+			reference =
+			    gnttab_claim_grant_reference(&provider->
+							 grant_ref_pool);
+
+			spin_unlock_irqrestore(&provider->lock, flags);
+		}
+
+		return reference;
+	}
+}
+
+void xenidc_buffer_resource_provider_free_grant_reference
+    (xenidc_buffer_resource_provider * provider, grant_ref_t reference) {
+	trace();
+
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&provider->lock, flags);
+
+		gnttab_release_grant_reference(&provider->grant_ref_pool,
+					       reference);
+
+		provider->free_resources.grant_references++;
+
+		spin_unlock_irqrestore(&provider->lock, flags);
+	}
+}
+
+unsigned long xenidc_buffer_resource_provider_allocate_empty_page_range
+    (xenidc_buffer_resource_provider * provider, unsigned long page_count) {
+	trace();
+
+	{
+		unsigned long page_range;
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&provider->lock, flags);
+
+			{
+				struct list_head *link =
+				    provider->empty_page_range_list.next;
+
+				list_del_init(link);
+
+				provider->free_resources.empty_page_ranges--;
+
+				page_range =
+				    (provider->mmap_vstart
+				     +
+				     (PAGE_SIZE
+				      *
+				      provider->resource_allocation.
+				      empty_page_range_page_count
+				      *
+				      (((unsigned long)link
+					-
+					(unsigned long)provider->
+					empty_page_range_link)
+				       / sizeof(struct list_head)
+				      )
+				     )
+				    );
+			}
+
+			spin_unlock_irqrestore(&provider->lock, flags);
+		}
+
+		return page_range;
+	}
+}
+
+void xenidc_buffer_resource_provider_free_empty_page_range
+    (xenidc_buffer_resource_provider * provider, unsigned long page_range) {
+	trace();
+
+	{
+		int i = ((page_range - provider->mmap_vstart)
+			 /
+			 (PAGE_SIZE
+			  *
+			  provider->resource_allocation.
+			  empty_page_range_page_count)
+		    );
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&provider->lock, flags);
+
+		list_add
+		    (&provider->empty_page_range_link[i],
+		     &provider->empty_page_range_list);
+
+		provider->free_resources.empty_page_ranges++;
+
+		spin_unlock_irqrestore(&provider->lock, flags);
+	}
+}
+
+void xenidc_buffer_resource_list_trace(xenidc_buffer_resource_list list)
+{
+	trace();
+
+	printk
+	    (KERN_INFO
+	     "xenidc %s: "
+	     "pages:%d; "
+	     "grant_references:%d; "
+	     "empty_page_ranges:%d; "
+	     "empty_page_range_page_count:%d\n",
+	     __PRETTY_FUNCTION__,
+	     list.pages,
+	     list.grant_references,
+	     list.empty_page_ranges, list.empty_page_range_page_count);
+}
diff -r 7adcceaaf851 -r 1e2c0ff9c46a linux-2.6-xen-sparse/include/asm-xen/xenidc_buffer_resource_provider.h
--- /dev/null	Sun Nov 20 14:53:27 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_buffer_resource_provider.h	Sun Nov 20 14:53:55 2005
@@ -0,0 +1,138 @@
+/*****************************************************************************/
+/* Xen inter-domain communication buffer resource provider.                  */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify it   */
+/* under the terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2 of the License, or (at your    */
+/* option) any later version.                                                */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful, but       */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of                */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General */
+/* Public License for more details.                                          */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License along   */
+/* with this program; if not, write to the Free Software Foundation, Inc.,   */
+/* 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                   */
+/*                                                                           */
+/*****************************************************************************/
+/*                                                                           */
+/* The main point of this buffer resource provider code is to make it        */
+/* possible to write some other generic code to manipulate various types of  */
+/* buffers and keep the other code independent of any buffer-type-specific   */
+/* resource management.                                                      */
+/*                                                                           */
+/* The initial implementation of this code provides sets of resources to     */
+/* clients in isolated per-client pools but this code provides a centralised */
+/* point of buffer resource management so it will be easy to implement a     */
+/* more efficient version which maintains isolation for a base set of        */
+/* resources to avoid deadlock and then shares additional resources between  */
+/* clients.                                                                  */
+
+#ifndef __ASM_XEN_XENIDC_BUFFER_RESOURCE_PROVIDER_H__
+#define __ASM_XEN_XENIDC_BUFFER_RESOURCE_PROVIDER_H__
+
+#include <asm/types.h>
+#include <asm-xen/gnttab.h>
+
+/* A xenidc_buffer_resource_list describes a set of resources, sometimes a   */
+/* set of resources required for an operation and sometimes a set of         */
+/* resources available to perform operations.                                */
+
+typedef struct xenidc_buffer_resource_list_struct xenidc_buffer_resource_list;
+
+struct xenidc_buffer_resource_list_struct {
+	u32 pages;
+	u32 grant_references;
+	u32 empty_page_ranges;
+	u32 empty_page_range_page_count;
+};
+
+/* xenidc_buffer_resource_list_null returns a list specifying no resources. */
+
+static inline xenidc_buffer_resource_list xenidc_buffer_resource_list_null(void)
+{
+	xenidc_buffer_resource_list list;
+
+	memset(&list, 0, sizeof(list));
+
+	return list;
+}
+
+/* xenidc_buffer_resource_list_subset_of returns true iff the resource        */
+/* requirements specified by list 'a' are met by the resources available in   */
+/* list 'b'.                                                                  */
+
+static inline int xenidc_buffer_resource_list_subset_of
+    (xenidc_buffer_resource_list * a, xenidc_buffer_resource_list * b) {
+	return ((a->pages <= b->pages)
+		&& (a->grant_references <= b->grant_references)
+		&& (a->empty_page_ranges <= b->empty_page_ranges)
+		&&
+		(a->empty_page_range_page_count <=
+		 b->empty_page_range_page_count)
+	    );
+}
+
+/* xenidc_buffer_resource_list_plus_equals adds the resource requirements     */
+/* specified by list 'b' to the resource requirements specified by list 'a'   */
+/* such that the resulting list 'a' specifies a set of resources sufficient   */
+/* to meet the sum of the requirements of the original 'a' list and 'b' lists.*/
+
+static inline void xenidc_buffer_resource_list_plus_equals
+    (xenidc_buffer_resource_list * a, xenidc_buffer_resource_list * b) {
+	a->pages += b->pages;
+	a->grant_references += b->grant_references;
+	a->empty_page_ranges += b->empty_page_ranges;
+
+	if (b->empty_page_range_page_count > a->empty_page_range_page_count) {
+		a->empty_page_range_page_count = b->empty_page_range_page_count;
+	}
+}
+
+/* Clients allocate a xenidc_buffer_resource_provider to provide themselves   */
+/* with a pool of resources.                                                  */
+
+typedef struct xenidc_buffer_resource_provider_struct
+    xenidc_buffer_resource_provider;
+
+extern xenidc_buffer_resource_provider *xenidc_allocate_buffer_resource_provider
+    (xenidc_buffer_resource_list resource_allocation);
+
+extern void xenidc_free_buffer_resource_provider
+    (xenidc_buffer_resource_provider * provider);
+
+/* Find out what resources are currently free for allocation. */
+
+extern xenidc_buffer_resource_list
+    xenidc_buffer_resource_provider_query_free_resources
+    (xenidc_buffer_resource_provider * provider);
+
+/* Resource-type specific allocate/free functions. */
+
+extern void *xenidc_buffer_resource_provider_allocate_page
+    (xenidc_buffer_resource_provider * provider);
+
+extern void xenidc_buffer_resource_provider_free_page
+    (xenidc_buffer_resource_provider * provider, void *page);
+
+extern grant_ref_t xenidc_buffer_resource_provider_allocate_grant_reference
+    (xenidc_buffer_resource_provider * provider);
+
+extern void xenidc_buffer_resource_provider_free_grant_reference
+    (xenidc_buffer_resource_provider * provider, grant_ref_t reference);
+
+extern unsigned long xenidc_buffer_resource_provider_allocate_empty_page_range
+    (xenidc_buffer_resource_provider * provider, unsigned long page_count);
+
+extern void xenidc_buffer_resource_provider_free_empty_page_range
+    (xenidc_buffer_resource_provider * provider, unsigned long page_range);
+
+/* xenidc_buffer_resource_list_trace is used for debugging and printks a dump */
+/* of the resource list.                                                      */
+
+extern void xenidc_buffer_resource_list_trace(xenidc_buffer_resource_list list);
+
+#endif

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2005-11-22 12:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-21 13:18 [PATCH][2/17] USB virt 2.6 split driver---xenidc buffer resource provider harry
2005-11-21 20:18 ` Muli Ben-Yehuda
2005-11-21 21:30   ` Harry Butterworth
2005-11-22 10:55     ` Muli Ben-Yehuda
2005-11-22 11:11       ` harry
2005-11-22 11:12       ` Keir Fraser
2005-11-22 11:22         ` Muli Ben-Yehuda
2005-11-22 12:06           ` Keir Fraser
2005-11-22 12:14             ` *** SPAM *** " harry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.