ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @ 13991:c4ed5b740a8d

linux: remove {lock,unlock}_vm_area(). Instead use vmalloc_sync_all()
in alloc_vm_area().
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Feb 16 11:24:10 2007 +0000 (2007-02-16)
parents d275951acf10
children
line source
1 /*****************************************************************************
2 * drivers/xen/tpmback/interface.c
3 *
4 * Vritual TPM interface management.
5 *
6 * Copyright (c) 2005, IBM Corporation
7 *
8 * Author: Stefan Berger, stefanb@us.ibm.com
9 *
10 * This code has been derived from drivers/xen/netback/interface.c
11 * Copyright (c) 2004, Keir Fraser
12 */
14 #include "common.h"
15 #include <xen/balloon.h>
16 #include <xen/gnttab.h>
18 static kmem_cache_t *tpmif_cachep;
19 int num_frontends = 0;
21 LIST_HEAD(tpmif_list);
23 static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
24 {
25 tpmif_t *tpmif;
27 tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
28 if (tpmif == NULL)
29 goto out_of_memory;
31 memset(tpmif, 0, sizeof (*tpmif));
32 tpmif->domid = domid;
33 tpmif->status = DISCONNECTED;
34 tpmif->bi = bi;
35 snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
36 atomic_set(&tpmif->refcnt, 1);
38 tpmif->mmap_pages = alloc_empty_pages_and_pagevec(TPMIF_TX_RING_SIZE);
39 if (tpmif->mmap_pages == NULL)
40 goto out_of_memory;
42 list_add(&tpmif->tpmif_list, &tpmif_list);
43 num_frontends++;
45 return tpmif;
47 out_of_memory:
48 if (tpmif != NULL)
49 kmem_cache_free(tpmif_cachep, tpmif);
50 printk("%s: out of memory\n", __FUNCTION__);
51 return ERR_PTR(-ENOMEM);
52 }
54 static void free_tpmif(tpmif_t * tpmif)
55 {
56 num_frontends--;
57 list_del(&tpmif->tpmif_list);
58 free_empty_pages_and_pagevec(tpmif->mmap_pages, TPMIF_TX_RING_SIZE);
59 kmem_cache_free(tpmif_cachep, tpmif);
60 }
62 tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi)
63 {
64 tpmif_t *tpmif;
66 list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
67 if (tpmif->bi == bi) {
68 if (tpmif->domid == domid) {
69 tpmif_get(tpmif);
70 return tpmif;
71 } else {
72 return ERR_PTR(-EEXIST);
73 }
74 }
75 }
77 return alloc_tpmif(domid, bi);
78 }
80 static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
81 {
82 struct gnttab_map_grant_ref op;
84 gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
85 GNTMAP_host_map, shared_page, tpmif->domid);
87 if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
88 BUG();
90 if (op.status) {
91 DPRINTK(" Grant table operation failure !\n");
92 return op.status;
93 }
95 tpmif->shmem_ref = shared_page;
96 tpmif->shmem_handle = op.handle;
98 return 0;
99 }
101 static void unmap_frontend_page(tpmif_t *tpmif)
102 {
103 struct gnttab_unmap_grant_ref op;
105 gnttab_set_unmap_op(&op, (unsigned long)tpmif->tx_area->addr,
106 GNTMAP_host_map, tpmif->shmem_handle);
108 if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
109 BUG();
110 }
112 int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
113 {
114 int err;
116 if (tpmif->irq)
117 return 0;
119 if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
120 return -ENOMEM;
122 err = map_frontend_page(tpmif, shared_page);
123 if (err) {
124 free_vm_area(tpmif->tx_area);
125 return err;
126 }
128 tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
130 err = bind_interdomain_evtchn_to_irqhandler(
131 tpmif->domid, evtchn, tpmif_be_int, 0, tpmif->devname, tpmif);
132 if (err < 0) {
133 unmap_frontend_page(tpmif);
134 free_vm_area(tpmif->tx_area);
135 return err;
136 }
137 tpmif->irq = err;
139 tpmif->shmem_ref = shared_page;
140 tpmif->active = 1;
142 return 0;
143 }
145 void tpmif_disconnect_complete(tpmif_t *tpmif)
146 {
147 if (tpmif->irq)
148 unbind_from_irqhandler(tpmif->irq, tpmif);
150 if (tpmif->tx) {
151 unmap_frontend_page(tpmif);
152 free_vm_area(tpmif->tx_area);
153 }
155 free_tpmif(tpmif);
156 }
158 void __init tpmif_interface_init(void)
159 {
160 tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
161 0, 0, NULL, NULL);
162 }
164 void __exit tpmif_interface_exit(void)
165 {
166 kmem_cache_destroy(tpmif_cachep);
167 }