Skip to content

Commit 0a9c75c

Browse files
sstabelliniBoris Ostrovsky
authored andcommitted
xen/pvcalls: xenbus state handling
Introduce the code to handle xenbus state changes. Implement the probe function for the pvcalls backend. Write the supported versions, max-page-order and function-calls nodes to xenstore, as required by the protocol. Introduce stub functions for disconnecting/connecting to a frontend. Signed-off-by: Stefano Stabellini <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Reviewed-by: Juergen Gross <[email protected]> CC: [email protected] CC: [email protected] Signed-off-by: Boris Ostrovsky <[email protected]>
1 parent 9be0733 commit 0a9c75c

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

drivers/xen/pvcalls-back.c

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,175 @@
2525
#include <xen/xenbus.h>
2626
#include <xen/interface/io/pvcalls.h>
2727

28+
#define PVCALLS_VERSIONS "1"
29+
#define MAX_RING_ORDER XENBUS_MAX_RING_GRANT_ORDER
30+
2831
struct pvcalls_back_global {
2932
struct list_head frontends;
3033
struct semaphore frontends_lock;
3134
} pvcalls_back_global;
3235

36+
static int backend_connect(struct xenbus_device *dev)
37+
{
38+
return 0;
39+
}
40+
41+
static int backend_disconnect(struct xenbus_device *dev)
42+
{
43+
return 0;
44+
}
45+
3346
static int pvcalls_back_probe(struct xenbus_device *dev,
3447
const struct xenbus_device_id *id)
3548
{
49+
int err, abort;
50+
struct xenbus_transaction xbt;
51+
52+
again:
53+
abort = 1;
54+
55+
err = xenbus_transaction_start(&xbt);
56+
if (err) {
57+
pr_warn("%s cannot create xenstore transaction\n", __func__);
58+
return err;
59+
}
60+
61+
err = xenbus_printf(xbt, dev->nodename, "versions", "%s",
62+
PVCALLS_VERSIONS);
63+
if (err) {
64+
pr_warn("%s write out 'versions' failed\n", __func__);
65+
goto abort;
66+
}
67+
68+
err = xenbus_printf(xbt, dev->nodename, "max-page-order", "%u",
69+
MAX_RING_ORDER);
70+
if (err) {
71+
pr_warn("%s write out 'max-page-order' failed\n", __func__);
72+
goto abort;
73+
}
74+
75+
err = xenbus_printf(xbt, dev->nodename, "function-calls",
76+
XENBUS_FUNCTIONS_CALLS);
77+
if (err) {
78+
pr_warn("%s write out 'function-calls' failed\n", __func__);
79+
goto abort;
80+
}
81+
82+
abort = 0;
83+
abort:
84+
err = xenbus_transaction_end(xbt, abort);
85+
if (err) {
86+
if (err == -EAGAIN && !abort)
87+
goto again;
88+
pr_warn("%s cannot complete xenstore transaction\n", __func__);
89+
return err;
90+
}
91+
92+
if (abort)
93+
return -EFAULT;
94+
95+
xenbus_switch_state(dev, XenbusStateInitWait);
96+
3697
return 0;
3798
}
3899

100+
static void set_backend_state(struct xenbus_device *dev,
101+
enum xenbus_state state)
102+
{
103+
while (dev->state != state) {
104+
switch (dev->state) {
105+
case XenbusStateClosed:
106+
switch (state) {
107+
case XenbusStateInitWait:
108+
case XenbusStateConnected:
109+
xenbus_switch_state(dev, XenbusStateInitWait);
110+
break;
111+
case XenbusStateClosing:
112+
xenbus_switch_state(dev, XenbusStateClosing);
113+
break;
114+
default:
115+
__WARN();
116+
}
117+
break;
118+
case XenbusStateInitWait:
119+
case XenbusStateInitialised:
120+
switch (state) {
121+
case XenbusStateConnected:
122+
backend_connect(dev);
123+
xenbus_switch_state(dev, XenbusStateConnected);
124+
break;
125+
case XenbusStateClosing:
126+
case XenbusStateClosed:
127+
xenbus_switch_state(dev, XenbusStateClosing);
128+
break;
129+
default:
130+
__WARN();
131+
}
132+
break;
133+
case XenbusStateConnected:
134+
switch (state) {
135+
case XenbusStateInitWait:
136+
case XenbusStateClosing:
137+
case XenbusStateClosed:
138+
down(&pvcalls_back_global.frontends_lock);
139+
backend_disconnect(dev);
140+
up(&pvcalls_back_global.frontends_lock);
141+
xenbus_switch_state(dev, XenbusStateClosing);
142+
break;
143+
default:
144+
__WARN();
145+
}
146+
break;
147+
case XenbusStateClosing:
148+
switch (state) {
149+
case XenbusStateInitWait:
150+
case XenbusStateConnected:
151+
case XenbusStateClosed:
152+
xenbus_switch_state(dev, XenbusStateClosed);
153+
break;
154+
default:
155+
__WARN();
156+
}
157+
break;
158+
default:
159+
__WARN();
160+
}
161+
}
162+
}
163+
39164
static void pvcalls_back_changed(struct xenbus_device *dev,
40165
enum xenbus_state frontend_state)
41166
{
167+
switch (frontend_state) {
168+
case XenbusStateInitialising:
169+
set_backend_state(dev, XenbusStateInitWait);
170+
break;
171+
172+
case XenbusStateInitialised:
173+
case XenbusStateConnected:
174+
set_backend_state(dev, XenbusStateConnected);
175+
break;
176+
177+
case XenbusStateClosing:
178+
set_backend_state(dev, XenbusStateClosing);
179+
break;
180+
181+
case XenbusStateClosed:
182+
set_backend_state(dev, XenbusStateClosed);
183+
if (xenbus_dev_is_online(dev))
184+
break;
185+
device_unregister(&dev->dev);
186+
break;
187+
case XenbusStateUnknown:
188+
set_backend_state(dev, XenbusStateClosed);
189+
device_unregister(&dev->dev);
190+
break;
191+
192+
default:
193+
xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
194+
frontend_state);
195+
break;
196+
}
42197
}
43198

44199
static int pvcalls_back_remove(struct xenbus_device *dev)

0 commit comments

Comments
 (0)