direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @ 8121:58d46463413e

GNTTABOP_map_grant_ref returns error status and handle as
separate fields. Update callers for new interface. Also
use int16_t as standard error code type on all public
interfaces.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Nov 30 17:24:27 2005 +0100 (2005-11-30)
parents cb215a84d1af
children fd9b2c1bb577
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 <asm-xen/balloon.h>
17 #define TPMIF_HASHSZ (2 << 5)
18 #define TPMIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(TPMIF_HASHSZ-1))
20 static kmem_cache_t *tpmif_cachep;
21 int num_frontends = 0;
23 LIST_HEAD(tpmif_list);
25 tpmif_t *
26 alloc_tpmif(domid_t domid, long int instance)
27 {
28 struct page *page;
29 tpmif_t *tpmif;
31 tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
32 if (!tpmif)
33 return ERR_PTR(-ENOMEM);
35 memset(tpmif, 0, sizeof (*tpmif));
36 tpmif->domid = domid;
37 tpmif->status = DISCONNECTED;
38 tpmif->tpm_instance = instance;
39 atomic_set(&tpmif->refcnt, 1);
41 page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
42 BUG_ON(page == NULL);
43 tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
45 list_add(&tpmif->tpmif_list, &tpmif_list);
46 num_frontends++;
48 return tpmif;
49 }
51 void
52 free_tpmif(tpmif_t * tpmif)
53 {
54 num_frontends--;
55 list_del(&tpmif->tpmif_list);
56 kmem_cache_free(tpmif_cachep, tpmif);
57 }
59 tpmif_t *
60 tpmif_find(domid_t domid, long int instance)
61 {
62 tpmif_t *tpmif;
64 list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
65 if (tpmif->tpm_instance == instance) {
66 if (tpmif->domid == domid) {
67 tpmif_get(tpmif);
68 return tpmif;
69 } else {
70 return ERR_PTR(-EEXIST);
71 }
72 }
73 }
75 return alloc_tpmif(domid, instance);
76 }
78 static int
79 map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
80 {
81 int ret;
82 struct gnttab_map_grant_ref op = {
83 .host_addr = (unsigned long)tpmif->tx_area->addr,
84 .flags = GNTMAP_host_map,
85 .ref = shared_page,
86 .dom = tpmif->domid,
87 };
89 lock_vm_area(tpmif->tx_area);
90 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
91 unlock_vm_area(tpmif->tx_area);
92 BUG_ON(ret);
94 if (op.status) {
95 DPRINTK(" Grant table operation failure !\n");
96 return op.status;
97 }
99 tpmif->shmem_ref = shared_page;
100 tpmif->shmem_handle = op.handle;
102 return 0;
103 }
105 static void
106 unmap_frontend_page(tpmif_t *tpmif)
107 {
108 struct gnttab_unmap_grant_ref op;
109 int ret;
111 op.host_addr = (unsigned long)tpmif->tx_area->addr;
112 op.handle = tpmif->shmem_handle;
113 op.dev_bus_addr = 0;
115 lock_vm_area(tpmif->tx_area);
116 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
117 unlock_vm_area(tpmif->tx_area);
118 BUG_ON(ret);
119 }
121 int
122 tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
123 {
124 int err;
125 evtchn_op_t op = {
126 .cmd = EVTCHNOP_bind_interdomain,
127 .u.bind_interdomain.remote_dom = tpmif->domid,
128 .u.bind_interdomain.remote_port = evtchn };
130 if (tpmif->irq) {
131 return 0;
132 }
134 if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
135 return -ENOMEM;
137 err = map_frontend_page(tpmif, shared_page);
138 if (err) {
139 free_vm_area(tpmif->tx_area);
140 return err;
141 }
143 err = HYPERVISOR_event_channel_op(&op);
144 if (err) {
145 unmap_frontend_page(tpmif);
146 free_vm_area(tpmif->tx_area);
147 return err;
148 }
150 tpmif->evtchn = op.u.bind_interdomain.local_port;
152 tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
154 tpmif->irq = bind_evtchn_to_irqhandler(
155 tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif);
156 tpmif->shmem_ref = shared_page;
157 tpmif->active = 1;
159 return 0;
160 }
162 static void
163 __tpmif_disconnect_complete(void *arg)
164 {
165 tpmif_t *tpmif = (tpmif_t *) arg;
167 if (tpmif->irq)
168 unbind_from_irqhandler(tpmif->irq, tpmif);
170 if (tpmif->tx) {
171 unmap_frontend_page(tpmif);
172 free_vm_area(tpmif->tx_area);
173 }
175 free_tpmif(tpmif);
176 }
178 void
179 tpmif_disconnect_complete(tpmif_t * tpmif)
180 {
181 INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif);
182 schedule_work(&tpmif->work);
183 }
185 void __init
186 tpmif_interface_init(void)
187 {
188 tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
189 0, 0, NULL, NULL);
190 }
192 /*
193 * Local variables:
194 * c-file-style: "linux"
195 * indent-tabs-mode: t
196 * c-indent-level: 8
197 * c-basic-offset: 8
198 * tab-width: 8
199 * End:
200 */