00001
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #include <stdarg.h>
00068 #include <linux/module.h>
00069 #include <xen/xenbus.h>
00070 #include <xen/net_driver_util.h>
00071 #include "sdev.h"
00072
00073
00074
00075 struct backend_info
00076 {
00077 struct xenbus_device *dev;
00078 sdev_t *sdev;
00079 struct xenbus_watch backend_watch;
00080 XenbusState frontend_state;
00081 };
00082
00083
00084 static int connect_rings(struct backend_info *);
00085 static void connect(struct backend_info *);
00086 static void maybe_connect(struct backend_info *);
00087 static void backend_changed(struct xenbus_watch *, const char **,
00088 unsigned int);
00089
00090
00091 static int sdevback_remove(struct xenbus_device *dev)
00092 {
00093 struct backend_info *be = dev->data;
00094
00095 if (be->backend_watch.node) {
00096 unregister_xenbus_watch(&be->backend_watch);
00097 kfree(be->backend_watch.node);
00098 be->backend_watch.node = NULL;
00099 }
00100 if (be->sdev) {
00101 sdev_disconnect(be->sdev);
00102 be->sdev = NULL;
00103 }
00104 kfree(be);
00105 dev->data = NULL;
00106 return 0;
00107 }
00108
00109
00115 static int sdevback_probe(struct xenbus_device *dev,
00116 const struct xenbus_device_id *id)
00117 {
00118 int err;
00119 struct backend_info *be = kzalloc(sizeof(struct backend_info),
00120 GFP_KERNEL);
00121
00122 if (!be) {
00123 xenbus_dev_fatal(dev, -ENOMEM,
00124 "allocating backend structure");
00125 return -ENOMEM;
00126 }
00127
00128 be->dev = dev;
00129 dev->data = be;
00130
00131 err = xenbus_watch_path2(dev, dev->nodename, "handle",
00132 &be->backend_watch, backend_changed);
00133 if (err)
00134 goto fail;
00135
00136 err = xenbus_switch_state(dev, XenbusStateInitWait);
00137 if (err) {
00138 goto fail;
00139 }
00140
00141 return 0;
00142
00143 fail:
00144 DPRINTK("failed");
00145 sdevback_remove(dev);
00146 return err;
00147 }
00148
00149
00155 static int sdevback_uevent(struct xenbus_device *xdev, char **envp,
00156 int num_envp, char *buffer, int buffer_size)
00157 {
00158 struct backend_info *be = xdev->data;
00159 sdev_t *sdev = be->sdev;
00160 int i = 0, length = 0;
00161 char *val;
00162
00163 DPRINTK("sdevback_uevent");
00164
00165 val = xenbus_read(XBT_NULL, xdev->nodename, "script", NULL);
00166 if (IS_ERR(val)) {
00167 int err = PTR_ERR(val);
00168 xenbus_dev_fatal(xdev, err, "reading script");
00169 return err;
00170 }
00171 else {
00172 add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
00173 &length, "script=%s", val);
00174 kfree(val);
00175 }
00176
00177 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
00178 "vwif=%s", sdev->dev->name);
00179
00180 envp[i] = NULL;
00181
00182 return 0;
00183 }
00184
00185
00190 static void backend_changed(struct xenbus_watch *watch,
00191 const char **vec, unsigned int len)
00192 {
00193 int err;
00194 long handle;
00195 struct backend_info *be
00196 = container_of(watch, struct backend_info, backend_watch);
00197 struct xenbus_device *dev = be->dev;
00198
00199 DPRINTK("");
00200
00201 err = xenbus_scanf(XBT_NULL, dev->nodename, "handle", "%li", &handle);
00202 if (XENBUS_EXIST_ERR(err)) {
00203
00204
00205
00206 return;
00207 }
00208 if (err != 1) {
00209 xenbus_dev_fatal(dev, err, "reading handle");
00210 return;
00211 }
00212
00213 if (be->sdev == NULL) {
00214 u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
00215
00216 be->sdev = alloc_sdev(dev->otherend_id, handle, be_mac);
00217 if (IS_ERR(be->sdev)) {
00218 err = PTR_ERR(be->sdev);
00219 be->sdev = NULL;
00220 xenbus_dev_fatal(dev, err, "creating interface");
00221 return;
00222 }
00223
00224 kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
00225 maybe_connect(be);
00226 }
00227 }
00228
00229
00233 static void frontend_changed(struct xenbus_device *dev,
00234 XenbusState frontend_state)
00235 {
00236 struct backend_info *be = dev->data;
00237
00238 DPRINTK("");
00239
00240 be->frontend_state = frontend_state;
00241
00242 switch (frontend_state) {
00243 case XenbusStateInitialising:
00244 case XenbusStateInitialised:
00245 break;
00246
00247 case XenbusStateConnected:
00248 maybe_connect(be);
00249 break;
00250
00251 case XenbusStateClosing:
00252 xenbus_switch_state(dev, XenbusStateClosing);
00253 break;
00254
00255 case XenbusStateClosed:
00256 if (be->sdev != NULL)
00257 kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
00258 device_unregister(&dev->dev);
00259 break;
00260
00261 case XenbusStateUnknown:
00262 case XenbusStateInitWait:
00263 default:
00264 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
00265 frontend_state);
00266 break;
00267 }
00268 }
00269
00270
00271
00272
00273
00274 static void maybe_connect(struct backend_info *be)
00275 {
00276 if (be->sdev != NULL && be->frontend_state == XenbusStateConnected) {
00277 connect(be);
00278 }
00279 }
00280
00281
00282 static void connect(struct backend_info *be)
00283 {
00284 int err;
00285 struct xenbus_device *dev = be->dev;
00286
00287 err = connect_rings(be);
00288 if (err)
00289 return;
00290
00291 err = xen_net_read_mac(dev, be->sdev->fe_dev_addr);
00292 if (err) {
00293 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
00294 return;
00295 }
00296
00297 xenbus_switch_state(dev, XenbusStateConnected);
00298 }
00299
00300
00301 static int connect_rings(struct backend_info *be)
00302 {
00303 struct xenbus_device *dev = be->dev;
00304 unsigned long tx_ring_ref, rx_ring_ref;
00305 unsigned int evtchn;
00306 int err;
00307
00308 DPRINTK("");
00309
00310 err = xenbus_gather(XBT_NULL, dev->otherend,
00311 "tx-ring-ref", "%lu", &tx_ring_ref,
00312 "rx-ring-ref", "%lu", &rx_ring_ref,
00313 "event-channel", "%u", &evtchn, NULL);
00314 if (err) {
00315 xenbus_dev_fatal(dev, err,
00316 "reading %s/ring-ref and event-channel",
00317 dev->otherend);
00318 return err;
00319 }
00320
00321
00322 err = sdev_map(be->sdev, tx_ring_ref, rx_ring_ref, evtchn);
00323 if (err) {
00324 xenbus_dev_fatal(dev, err,
00325 "mapping shared-frames %lu/%lu port %u",
00326 tx_ring_ref, rx_ring_ref, evtchn);
00327 return err;
00328 }
00329 return 0;
00330 }
00331
00332
00333
00334
00335
00336 static struct xenbus_device_id sdevback_ids[] = {
00337 { "vwif" },
00338 { "" }
00339 };
00340
00341
00342 static struct xenbus_driver sdevback = {
00343 .name = "vwif",
00344 .owner = THIS_MODULE,
00345 .ids = sdevback_ids,
00346 .probe = sdevback_probe,
00347 .remove = sdevback_remove,
00348 .uevent = sdevback_uevent,
00349 .otherend_changed = frontend_changed,
00350 };
00351
00352
00353 void sdev_xenbus_init(void)
00354 {
00355 char *err1 = "failed to register vwif device due to ";
00356 char * err2 = "faulty de-registration upon module unload";
00357
00358 if (xenbus_register_backend(&sdevback) < 0)
00359 printk(KERN_ERR
00360 "orbisquartus: %s%s\n", err1, err2);
00361 }
00362
00363
00364 void sdev_xenbus_exit(void)
00365 {
00366 xenbus_unregister_driver(&sdevback);
00367 }