xen-vtx-unstable

view linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @ 6774:4d899a738d59

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 15:05:49 2005 +0000 (2005-09-13)
parents 9ead08216805 cdfa7dd00c44
children e7c7196fa329 8ca0f98ba8e2
line source
1 /* Xenbus code for tpmif backend
2 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 #include <stdarg.h>
19 #include <linux/module.h>
20 #include <asm-xen/xenbus.h>
21 #include "common.h"
23 struct backend_info
24 {
25 struct xenbus_device *dev;
27 /* our communications channel */
28 tpmif_t *tpmif;
30 long int frontend_id;
31 long int instance; // instance of TPM
33 /* watch front end for changes */
34 struct xenbus_watch backend_watch;
36 struct xenbus_watch watch;
37 char * frontpath;
38 };
40 static int tpmback_remove(struct xenbus_device *dev)
41 {
42 struct backend_info *be = dev->data;
44 if (be->watch.node) {
45 unregister_xenbus_watch(&be->watch);
46 }
47 unregister_xenbus_watch(&be->backend_watch);
49 tpmif_vtpm_close(be->instance);
51 if (be->tpmif) {
52 tpmif_put(be->tpmif);
53 }
55 if (be->frontpath)
56 kfree(be->frontpath);
57 kfree(be);
58 return 0;
59 }
62 static void frontend_changed(struct xenbus_watch *watch, const char *node)
63 {
64 unsigned long ringref;
65 unsigned int evtchn;
66 unsigned long ready = 1;
67 int err;
68 struct backend_info *be
69 = container_of(watch, struct backend_info, watch);
71 /* If other end is gone, delete ourself. */
72 if (node && !xenbus_exists(be->frontpath, "")) {
73 xenbus_rm(be->dev->nodename, "");
74 device_unregister(&be->dev->dev);
75 return;
76 }
78 if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
79 return;
81 err = xenbus_gather(be->frontpath,
82 "ring-ref", "%lu", &ringref,
83 "event-channel", "%u", &evtchn, NULL);
84 if (err) {
85 xenbus_dev_error(be->dev, err,
86 "reading %s/ring-ref and event-channel",
87 be->frontpath);
88 return;
89 }
92 /*
93 * Tell the front-end that we are ready to go -
94 * unless something bad happens
95 */
96 err = xenbus_transaction_start(be->dev->nodename);
97 if (err) {
98 xenbus_dev_error(be->dev, err, "starting transaction");
99 return;
100 }
102 err = xenbus_printf(be->dev->nodename,
103 "ready", "%lu", ready);
104 if (err) {
105 xenbus_dev_error(be->dev, err, "writing 'ready'");
106 goto abort;
107 }
109 err = tpmif_map(be->tpmif, ringref, evtchn);
110 if (err) {
111 xenbus_dev_error(be->dev, err,
112 "mapping shared-frame %lu port %u",
113 ringref, evtchn);
114 goto abort;
115 }
117 err = tpmif_vtpm_open(be->tpmif,
118 be->frontend_id,
119 be->instance);
120 if (err) {
121 xenbus_dev_error(be->dev, err,
122 "queueing vtpm open packet");
123 /*
124 * Should close down this device and notify FE
125 * about closure.
126 */
127 goto abort;
128 }
130 xenbus_transaction_end(0);
131 xenbus_dev_ok(be->dev);
132 return;
133 abort:
134 xenbus_transaction_end(1);
135 }
138 static void backend_changed(struct xenbus_watch *watch, const char *node)
139 {
140 int err;
141 long int instance;
142 struct backend_info *be
143 = container_of(watch, struct backend_info, backend_watch);
144 struct xenbus_device *dev = be->dev;
146 err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
147 if (XENBUS_EXIST_ERR(err))
148 return;
149 if (err < 0) {
150 xenbus_dev_error(dev, err, "reading 'instance' variable");
151 return;
152 }
154 if (be->instance != -1 && be->instance != instance) {
155 printk(KERN_WARNING
156 "cannot change the instance\n");
157 return;
158 }
159 be->instance = instance;
161 if (be->tpmif == NULL) {
162 be->tpmif = tpmif_find(be->frontend_id,
163 instance);
164 if (IS_ERR(be->tpmif)) {
165 err = PTR_ERR(be->tpmif);
166 be->tpmif = NULL;
167 xenbus_dev_error(dev, err, "creating interface");
168 return;
169 }
171 /* Pass in NULL node to skip exist test. */
172 frontend_changed(&be->watch, be->frontpath);
173 }
174 }
177 static int tpmback_probe(struct xenbus_device *dev,
178 const struct xenbus_device_id *id)
179 {
180 struct backend_info *be;
181 char *frontend;
182 int err;
184 be = kmalloc(sizeof(*be), GFP_KERNEL);
185 if (!be) {
186 xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
187 err = -ENOMEM;
188 }
190 memset(be, 0, sizeof(*be));
192 frontend = NULL;
193 err = xenbus_gather(dev->nodename,
194 "frontend-id", "%li", &be->frontend_id,
195 "frontend", NULL, &frontend,
196 NULL);
197 if (XENBUS_EXIST_ERR(err))
198 goto free_be;
199 if (err < 0) {
200 xenbus_dev_error(dev, err,
201 "reading %s/frontend or frontend-id",
202 dev->nodename);
203 goto free_be;
204 }
205 if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
206 /* If we can't get a frontend path and a frontend-id,
207 * then our bus-id is no longer valid and we need to
208 * destroy the backend device.
209 */
210 err = -ENOENT;
211 goto free_be;
212 }
214 be->dev = dev;
215 be->backend_watch.node = dev->nodename;
216 be->backend_watch.callback = backend_changed;
217 be->instance = -1;
218 err = register_xenbus_watch(&be->backend_watch);
219 if (err) {
220 be->backend_watch.node = NULL;
221 xenbus_dev_error(dev, err, "adding backend watch on %s",
222 dev->nodename);
223 goto free_be;
224 }
226 be->frontpath = frontend;
227 be->watch.node = be->frontpath;
228 be->watch.callback = frontend_changed;
229 err = register_xenbus_watch(&be->watch);
230 if (err) {
231 be->watch.node = NULL;
232 xenbus_dev_error(dev, err,
233 "adding frontend watch on %s",
234 be->frontpath);
235 goto free_be;
236 }
238 dev->data = be;
240 backend_changed(&be->backend_watch, dev->nodename);
241 return err;
243 free_be:
244 if (be->backend_watch.node)
245 unregister_xenbus_watch(&be->backend_watch);
246 if (frontend)
247 kfree(frontend);
248 kfree(be);
249 return err;
250 }
253 static struct xenbus_device_id tpmback_ids[] = {
254 { "vtpm" },
255 { "" }
256 };
259 static struct xenbus_driver tpmback = {
260 .name = "vtpm",
261 .owner = THIS_MODULE,
262 .ids = tpmback_ids,
263 .probe = tpmback_probe,
264 .remove = tpmback_remove,
265 };
268 void tpmif_xenbus_init(void)
269 {
270 xenbus_register_backend(&tpmback);
271 }