- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / sfc_netfront / accel_xenbus.c
1 /****************************************************************************
2  * Solarflare driver for Xen network acceleration
3  *
4  * Copyright 2006-2008: Solarflare Communications Inc,
5  *                      9501 Jeronimo Road, Suite 250,
6  *                      Irvine, CA 92618, USA
7  *
8  * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published
12  * by the Free Software Foundation, incorporated herein by reference.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  ****************************************************************************
23  */
24
25 #include <linux/stddef.h>
26 #include <linux/errno.h>
27
28 #include <xen/xenbus.h>
29 #include <xen/evtchn.h>
30 #include <xen/gnttab.h>
31
32 #include "accel.h"
33 #include "accel_util.h"
34 #include "accel_msg_iface.h"
35 #include "accel_bufs.h"
36 #include "accel_ssr.h"
37 /* drivers/xen/netfront/netfront.h */
38 #include "netfront.h"
39
40 void netfront_accel_set_closing(netfront_accel_vnic *vnic) 
41 {
42
43         vnic->frontend_state = XenbusStateClosing;
44         net_accel_update_state(vnic->dev, XenbusStateClosing);
45 }
46         
47
48 static void mac_address_change(struct xenbus_watch *watch,
49                                const char **vec, unsigned int len)
50 {
51         netfront_accel_vnic *vnic;
52         struct xenbus_device *dev;
53         int rc;
54
55         DPRINTK("%s\n", __FUNCTION__);
56         
57         vnic = container_of(watch, netfront_accel_vnic, 
58                                 mac_address_watch);
59         dev = vnic->dev;
60
61         rc = net_accel_xen_net_read_mac(dev, vnic->mac);
62
63         if (rc != 0)
64                 EPRINTK("%s: failed to read mac (%d)\n", __FUNCTION__, rc);
65 }
66
67
68 static int setup_mac_address_watch(struct xenbus_device *dev,
69                                    netfront_accel_vnic *vnic)
70 {
71         int err;
72
73         DPRINTK("Setting watch on %s/%s\n", dev->nodename, "mac");
74
75         err = xenbus_watch_path2(dev, dev->nodename, "mac", 
76                                  &vnic->mac_address_watch, 
77                                  mac_address_change);
78         if (err) {
79                 EPRINTK("%s: Failed to register xenbus watch: %d\n",
80                         __FUNCTION__, err);
81                 goto fail;
82         }
83
84         return 0;
85  fail:
86         vnic->mac_address_watch.node = NULL;
87         return err;
88 }
89
90
91 /* Grant access to some pages and publish through xenbus */
92 static int make_named_grant(struct xenbus_device *dev, void *page, 
93                             const char *name, grant_ref_t *gnt_ref)
94 {
95         struct xenbus_transaction tr;
96         int err;
97         grant_ref_t gnt;
98
99         gnt = net_accel_grant_page(dev, virt_to_mfn(page), 0);
100         if (gnt < 0)
101                 return gnt;
102
103         do {
104                 err = xenbus_transaction_start(&tr);
105                 if (err != 0) {
106                         EPRINTK("%s: transaction start failed %d\n",
107                                 __FUNCTION__, err);
108                         return err;
109                 }
110                 err = xenbus_printf(tr, dev->nodename, name, "%d", gnt);
111                 if (err != 0) {
112                         EPRINTK("%s: xenbus_printf failed %d\n", __FUNCTION__,
113                                 err);
114                         xenbus_transaction_end(tr, 1);
115                         return err;
116                 }
117                 err = xenbus_transaction_end(tr, 0);
118         } while (err == -EAGAIN);
119         
120         if (err != 0) {
121                 EPRINTK("%s: transaction end failed %d\n", __FUNCTION__, err);
122                 return err;
123         }
124         
125         *gnt_ref = gnt;
126
127         return 0;
128 }
129
130
131 static int remove_named_grant(struct xenbus_device *dev,
132                               const char *name, grant_ref_t gnt_ref)
133 {
134         struct xenbus_transaction tr;
135         int err;
136
137         net_accel_ungrant_page(gnt_ref);
138
139         do {
140                 err = xenbus_transaction_start(&tr);
141                 if (err != 0) {
142                         EPRINTK("%s: transaction start failed %d\n",
143                                 __FUNCTION__, err);
144                         return err;
145                 }
146                 err = xenbus_rm(tr, dev->nodename, name);
147                 if (err != 0) {
148                         EPRINTK("%s: xenbus_rm failed %d\n", __FUNCTION__,
149                                 err);
150                         xenbus_transaction_end(tr, 1);
151                         return err;
152                 }
153                 err = xenbus_transaction_end(tr, 0);
154         } while (err == -EAGAIN);
155         
156         if (err != 0) {
157                 EPRINTK("%s: transaction end failed %d\n", __FUNCTION__, err);
158                 return err;
159         }
160
161         return 0;
162 }
163
164
165 static 
166 netfront_accel_vnic *netfront_accel_vnic_ctor(struct net_device *net_dev,
167                                               struct xenbus_device *dev)
168 {
169         struct netfront_info *np =
170                 (struct netfront_info *)netdev_priv(net_dev);
171         netfront_accel_vnic *vnic;
172         int err;
173
174         /*
175          * A bug in earlier versions of Xen accel plugin system meant
176          * you could be probed twice for the same device on suspend
177          * cancel.  Be tolerant of that.
178          */ 
179         if (np->accel_priv != NULL)
180                 return ERR_PTR(-EALREADY);
181
182         /* Alloc mem for state */
183         vnic = kzalloc(sizeof(netfront_accel_vnic), GFP_KERNEL);
184         if (vnic == NULL) {
185                 EPRINTK("%s: no memory for vnic state\n", __FUNCTION__);
186                 return ERR_PTR(-ENOMEM);
187         }
188
189         spin_lock_init(&vnic->tx_lock);
190
191         mutex_init(&vnic->vnic_mutex);
192         mutex_lock(&vnic->vnic_mutex);
193
194         /* Store so state can be retrieved from device */
195         BUG_ON(np->accel_priv != NULL);
196         np->accel_priv = vnic;
197         vnic->dev = dev;
198         vnic->net_dev = net_dev;
199         spin_lock_init(&vnic->irq_enabled_lock);
200         netfront_accel_ssr_init(&vnic->ssr_state);
201
202         init_waitqueue_head(&vnic->state_wait_queue);
203         vnic->backend_state = XenbusStateUnknown;
204         vnic->frontend_state = XenbusStateClosed;
205         vnic->removing = 0;
206         vnic->domU_state_is_setup = 0;
207         vnic->dom0_state_is_setup = 0;
208         vnic->poll_enabled = 0;
209         vnic->tx_enabled = 0;
210         vnic->tx_skb = NULL;
211
212 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
213         INIT_WORK(&vnic->msg_from_bend, netfront_accel_msg_from_bend);
214 #else
215         INIT_WORK(&vnic->msg_from_bend, netfront_accel_msg_from_bend, vnic);
216 #endif
217
218         netfront_accel_debugfs_create(vnic);
219
220         mutex_unlock(&vnic->vnic_mutex);
221
222         err = net_accel_xen_net_read_mac(dev, vnic->mac);
223         if (err) 
224                 goto fail_mac;
225
226         /* Setup a watch on the frontend's MAC address */
227         err = setup_mac_address_watch(dev, vnic);
228         if (err)
229                 goto fail_mac;
230
231         return vnic;
232
233 fail_mac:
234
235         mutex_lock(&vnic->vnic_mutex);
236
237         netfront_accel_debugfs_remove(vnic);
238
239         netfront_accel_ssr_fini(vnic, &vnic->ssr_state);
240
241         EPRINTK_ON(vnic->tx_skb != NULL);
242
243         vnic->frontend_state = XenbusStateUnknown;
244         net_accel_update_state(dev, XenbusStateUnknown);
245
246         mutex_unlock(&vnic->vnic_mutex);
247
248         np->accel_priv = NULL;
249         kfree(vnic);
250
251         return ERR_PTR(err);
252 }
253
254
255 static void netfront_accel_vnic_dtor(netfront_accel_vnic *vnic)
256 {
257         struct net_device *net_dev = vnic->net_dev;
258         struct netfront_info *np = 
259                 (struct netfront_info *)netdev_priv(net_dev);
260
261         /*
262          * Now we don't hold the lock any more it is safe to remove
263          * this watch and synchonrise with the completion of
264          * watches
265          */
266         DPRINTK("%s: unregistering xenbus mac watch\n", __FUNCTION__);
267         unregister_xenbus_watch(&vnic->mac_address_watch);
268         kfree(vnic->mac_address_watch.node);
269
270         flush_workqueue(netfront_accel_workqueue);
271
272         mutex_lock(&vnic->vnic_mutex);
273
274         netfront_accel_debugfs_remove(vnic);
275
276         netfront_accel_ssr_fini(vnic, &vnic->ssr_state);
277
278         EPRINTK_ON(vnic->tx_skb != NULL);
279
280         vnic->frontend_state = XenbusStateUnknown;
281         net_accel_update_state(vnic->dev, XenbusStateUnknown);
282
283         mutex_unlock(&vnic->vnic_mutex);
284
285         np->accel_priv = NULL;
286         kfree(vnic);
287 }
288
289
290 static int vnic_setup_domU_shared_state(struct xenbus_device *dev,
291                                         netfront_accel_vnic *vnic)
292 {
293         struct xenbus_transaction tr;
294         int err;
295         int msgs_per_queue;
296
297
298         DPRINTK("Setting up domU shared state.\n");
299
300         msgs_per_queue = (PAGE_SIZE/2) / sizeof(struct net_accel_msg);
301
302         /* Allocate buffer state */
303         vnic->tx_bufs = netfront_accel_init_bufs(&vnic->tx_lock);
304         if (vnic->tx_bufs == NULL) {
305                 err = -ENOMEM;
306                 EPRINTK("%s: Failed to allocate tx buffers\n", __FUNCTION__);
307                 goto fail_tx_bufs;
308         }
309
310         vnic->rx_bufs = netfront_accel_init_bufs(NULL);
311         if (vnic->rx_bufs == NULL) {
312                 err = -ENOMEM;
313                 EPRINTK("%s: Failed to allocate rx buffers\n", __FUNCTION__);
314                 goto fail_rx_bufs;
315         }
316
317         /* 
318          * This allocates two pages, one for the shared page and one
319          * for the message queue.
320          */
321         vnic->shared_page = (struct net_accel_shared_page *)
322                 __get_free_pages(GFP_KERNEL, 1);
323         if (vnic->shared_page == NULL) {
324                 EPRINTK("%s: no memory for shared pages\n", __FUNCTION__);
325                 err = -ENOMEM;
326                 goto fail_shared_page;
327         }
328
329         net_accel_msg_init_queue
330                 (&vnic->from_dom0, &vnic->shared_page->queue0, 
331                  (struct net_accel_msg *)((u8*)vnic->shared_page + PAGE_SIZE),
332                  msgs_per_queue);
333
334         net_accel_msg_init_queue
335                 (&vnic->to_dom0, &vnic->shared_page->queue1,
336                  (struct net_accel_msg *)((u8*)vnic->shared_page +
337                                           (3 * PAGE_SIZE / 2)),
338                  msgs_per_queue);
339         
340         vnic->msg_state = NETFRONT_ACCEL_MSG_NONE;
341
342         err = make_named_grant(dev, vnic->shared_page, "accel-ctrl-page",
343                                &vnic->ctrl_page_gnt);
344         if (err) {
345                 EPRINTK("couldn't make ctrl-page named grant\n");
346                 goto fail_ctrl_page_grant;
347         }
348
349         err = make_named_grant(dev, (u8*)vnic->shared_page + PAGE_SIZE,
350                                "accel-msg-page", &vnic->msg_page_gnt);
351         if (err) {
352                 EPRINTK("couldn't make msg-page named grant\n");
353                 goto fail_msg_page_grant;
354         }
355
356         /* Create xenbus msg event channel */
357         err = bind_listening_port_to_irqhandler
358                 (dev->otherend_id, netfront_accel_msg_channel_irq_from_bend,
359                  IRQF_SAMPLE_RANDOM, "vnicctrl", vnic);
360         if (err < 0) {
361                 EPRINTK("Couldn't bind msg event channel\n");
362                 goto fail_msg_irq;
363         }
364         vnic->msg_channel_irq = err;
365         vnic->msg_channel = irq_to_evtchn_port(vnic->msg_channel_irq);
366         
367         /* Create xenbus net event channel */
368         err = bind_listening_port_to_irqhandler
369                 (dev->otherend_id, netfront_accel_net_channel_irq_from_bend,
370                  IRQF_SAMPLE_RANDOM, "vnicfront", vnic);
371         if (err < 0) {
372                 EPRINTK("Couldn't bind net event channel\n");
373                 goto fail_net_irq;
374         }
375         vnic->net_channel_irq = err;
376         vnic->net_channel = irq_to_evtchn_port(vnic->net_channel_irq);
377         /* Want to ensure we don't get interrupts before we're ready */
378         netfront_accel_disable_net_interrupts(vnic);
379
380         DPRINTK("otherend %d has msg ch %u (%u) and net ch %u (%u)\n",
381                 dev->otherend_id, vnic->msg_channel, vnic->msg_channel_irq, 
382                 vnic->net_channel, vnic->net_channel_irq);
383
384         do {
385                 err = xenbus_transaction_start(&tr);
386                 if (err != 0) {
387                         EPRINTK("%s: Transaction start failed %d\n",
388                                 __FUNCTION__, err);
389                         goto fail_transaction;
390                 }
391
392                 err = xenbus_printf(tr, dev->nodename, "accel-msg-channel",
393                                     "%u", vnic->msg_channel);
394                 if (err != 0) {
395                         EPRINTK("%s: event channel xenbus write failed %d\n",
396                                 __FUNCTION__, err);
397                         xenbus_transaction_end(tr, 1);
398                         goto fail_transaction;
399                 }
400
401                 err = xenbus_printf(tr, dev->nodename, "accel-net-channel",
402                                     "%u", vnic->net_channel);
403                 if (err != 0) {
404                         EPRINTK("%s: net channel xenbus write failed %d\n",
405                                 __FUNCTION__, err);
406                         xenbus_transaction_end(tr, 1);
407                         goto fail_transaction;
408                 }
409
410                 err = xenbus_transaction_end(tr, 0);
411         } while (err == -EAGAIN);
412
413         if (err != 0) {
414                 EPRINTK("%s: Transaction end failed %d\n", __FUNCTION__, err);
415                 goto fail_transaction;
416         }
417
418         DPRINTK("Completed setting up domU shared state\n");
419
420         return 0;
421
422 fail_transaction:
423
424         unbind_from_irqhandler(vnic->net_channel_irq, vnic);
425 fail_net_irq:
426
427         unbind_from_irqhandler(vnic->msg_channel_irq, vnic);
428 fail_msg_irq:
429
430         remove_named_grant(dev, "accel-ctrl-page", vnic->ctrl_page_gnt);
431 fail_msg_page_grant:
432
433         remove_named_grant(dev, "accel-msg-page", vnic->msg_page_gnt);
434 fail_ctrl_page_grant:
435
436         free_pages((unsigned long)vnic->shared_page, 1);
437         vnic->shared_page = NULL;
438 fail_shared_page:
439
440         netfront_accel_fini_bufs(vnic->rx_bufs);
441 fail_rx_bufs:
442
443         netfront_accel_fini_bufs(vnic->tx_bufs);
444 fail_tx_bufs:
445
446         /* Undo the memory allocation created when we got the HELLO */
447         netfront_accel_free_buffer_mem(&vnic->bufpages,
448                                        vnic->rx_bufs,
449                                        vnic->tx_bufs);
450
451         DPRINTK("Failed to setup domU shared state with code %d\n", err);
452
453         return err;
454 }
455
456
457 static void vnic_remove_domU_shared_state(struct xenbus_device *dev, 
458                                           netfront_accel_vnic *vnic)
459 {
460         struct xenbus_transaction tr;
461         
462         /*
463          * Don't remove any watches because we currently hold the
464          * mutex and the watches take the mutex.
465          */
466
467         DPRINTK("%s: removing event channel irq handlers %d %d\n",
468                 __FUNCTION__, vnic->net_channel_irq, vnic->msg_channel_irq);
469         do {
470                 if (xenbus_transaction_start(&tr) != 0)
471                         break;
472                 xenbus_rm(tr, dev->nodename, "accel-msg-channel");
473                 xenbus_rm(tr, dev->nodename, "accel-net-channel");
474         } while (xenbus_transaction_end(tr, 0) == -EAGAIN);
475
476         unbind_from_irqhandler(vnic->net_channel_irq, vnic);
477         unbind_from_irqhandler(vnic->msg_channel_irq, vnic);
478
479         /* ungrant pages for msg channel */
480         remove_named_grant(dev, "accel-ctrl-page", vnic->ctrl_page_gnt);
481         remove_named_grant(dev, "accel-msg-page", vnic->msg_page_gnt);
482         free_pages((unsigned long)vnic->shared_page, 1);
483         vnic->shared_page = NULL;
484
485         /* ungrant pages for buffers, and free buffer memory */
486         netfront_accel_free_buffer_mem(&vnic->bufpages,
487                                        vnic->rx_bufs,
488                                        vnic->tx_bufs);
489         netfront_accel_fini_bufs(vnic->rx_bufs);
490         netfront_accel_fini_bufs(vnic->tx_bufs);
491 }
492
493
494 static void vnic_setup_dom0_shared_state(struct xenbus_device *dev,
495                                         netfront_accel_vnic *vnic)
496 {
497         DPRINTK("Setting up dom0 shared state\n");
498
499         netfront_accel_vi_ctor(vnic);
500
501         /*
502          * Message processing will be enabled when this function
503          * returns, but we might have missed an interrupt.  Schedule a
504          * check just in case.
505          */
506         queue_work(netfront_accel_workqueue, &vnic->msg_from_bend);
507 }
508
509
510 static void vnic_remove_dom0_shared_state(struct xenbus_device *dev,
511                                           netfront_accel_vnic *vnic)
512 {
513         DPRINTK("Removing dom0 shared state\n");
514
515         vnic_stop_fastpath(vnic);
516
517         netfront_accel_vi_dtor(vnic);
518 }
519
520
521 /*************************************************************************/
522
523 /*
524  * The following code handles accelstate changes between the frontend
525  * and the backend.  In response to transitions, calls the following
526  * functions in matching pairs:
527  *
528  *   vnic_setup_domU_shared_state
529  *   vnic_remove_domU_shared_state
530  *
531  *   vnic_setup_dom0_shared_state
532  *   vnic_remove_dom0_shared_state
533  *
534  * Valid state transitions for DomU are as follows:
535  *
536  * Closed->Init       on probe or in response to Init from dom0
537  *
538  * Init->Connected    in response to Init from dom0
539  * Init->Closing      on error providing dom0 is in Init
540  * Init->Closed       on remove or in response to Closing from dom0
541  *
542  * Connected->Closing on error/remove
543  * Connected->Closed  in response to Closing from dom0
544  *
545  * Closing->Closed    in response to Closing from dom0
546  *
547  */
548
549
550 /* Function to deal with Xenbus accel state change in backend */
551 static void netfront_accel_backend_accel_changed(netfront_accel_vnic *vnic,
552                                                  XenbusState backend_state)
553 {
554         struct xenbus_device *dev = vnic->dev;
555         XenbusState frontend_state;
556         int state;
557
558         DPRINTK("%s: changing from %s to %s. nodename %s, otherend %s\n",
559                 __FUNCTION__, xenbus_strstate(vnic->backend_state),
560                 xenbus_strstate(backend_state), dev->nodename, dev->otherend);
561
562         /*
563          * Ignore duplicate state changes.  This can happen if the
564          * backend changes state twice in quick succession and the
565          * first watch fires in the frontend after the second
566          * transition has completed.
567          */
568         if (vnic->backend_state == backend_state)
569                 return;
570
571         vnic->backend_state = backend_state;
572         frontend_state = vnic->frontend_state;
573
574         switch (backend_state) {
575         case XenbusStateInitialising:
576                 /*
577                  * It's possible for us to miss the closed state from
578                  * dom0, so do the work here.
579                  */
580                 if (vnic->domU_state_is_setup) {
581                         vnic_remove_domU_shared_state(dev, vnic);
582                         vnic->domU_state_is_setup = 0;
583                 }
584
585                 if (frontend_state != XenbusStateInitialising) {
586                         /* Make sure the backend doesn't go away. */
587                         frontend_state = XenbusStateInitialising;
588                         net_accel_update_state(dev, frontend_state);
589                         xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d", &state);
590                         backend_state = (XenbusState)state;
591                         if (backend_state != XenbusStateInitialising)
592                                 break;
593                 }
594
595                 /* Start the new connection. */
596                 if (!vnic->removing) {
597                         BUG_ON(vnic->domU_state_is_setup);
598                         if (vnic_setup_domU_shared_state(dev, vnic) == 0) {
599                                 vnic->domU_state_is_setup = 1;
600                                 frontend_state = XenbusStateConnected;
601                         } else
602                                 frontend_state = XenbusStateClosing;
603                 }
604                 break;
605         case XenbusStateConnected:
606                 if (vnic->domU_state_is_setup &&
607                     !vnic->dom0_state_is_setup) {
608                         vnic_setup_dom0_shared_state(dev, vnic);
609                         vnic->dom0_state_is_setup = 1;
610                 }
611                 break;
612         default:
613         case XenbusStateClosing:
614                 if (vnic->dom0_state_is_setup) {
615                         vnic_remove_dom0_shared_state(dev, vnic);
616                         vnic->dom0_state_is_setup = 0;
617                 }
618                 frontend_state = XenbusStateClosed;
619                 break;
620         case XenbusStateUnknown:
621         case XenbusStateClosed:
622                 if (vnic->domU_state_is_setup) {
623                         vnic_remove_domU_shared_state(dev, vnic);
624                         vnic->domU_state_is_setup = 0;
625                 }
626                 break;
627         }
628
629         if (frontend_state != vnic->frontend_state) {
630                 DPRINTK("Switching from state %s (%d) to %s (%d)\n",
631                         xenbus_strstate(vnic->frontend_state),
632                         vnic->frontend_state,
633                         xenbus_strstate(frontend_state), frontend_state);
634                 vnic->frontend_state = frontend_state;
635                 net_accel_update_state(dev, frontend_state);
636         }
637
638         wake_up(&vnic->state_wait_queue);
639 }
640
641
642 static void backend_accel_state_change(struct xenbus_watch *watch,
643                                        const char **vec, unsigned int len)
644 {
645         int state;
646         netfront_accel_vnic *vnic;
647         struct xenbus_device *dev;
648
649         DPRINTK("%s\n", __FUNCTION__);
650
651         vnic = container_of(watch, struct netfront_accel_vnic,
652                                 backend_accel_watch);
653
654         mutex_lock(&vnic->vnic_mutex);
655
656         dev = vnic->dev;
657
658         state = (int)XenbusStateUnknown;
659         xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d", &state);
660         netfront_accel_backend_accel_changed(vnic, state);
661
662         mutex_unlock(&vnic->vnic_mutex);
663 }
664
665
666 static int setup_dom0_accel_watch(struct xenbus_device *dev,
667                                   netfront_accel_vnic *vnic)
668 {
669         int err;
670
671         DPRINTK("Setting watch on %s/%s\n", dev->otherend, "accelstate");
672
673         err = xenbus_watch_path2(dev, dev->otherend, "accelstate", 
674                                  &vnic->backend_accel_watch, 
675                                  backend_accel_state_change);
676         if (err) {
677                 EPRINTK("%s: Failed to register xenbus watch: %d\n",
678                         __FUNCTION__, err);
679                 goto fail;
680         }
681         return 0;
682  fail:
683         vnic->backend_accel_watch.node = NULL;
684         return err;
685 }
686
687
688 int netfront_accel_probe(struct net_device *net_dev, struct xenbus_device *dev)
689 {
690         netfront_accel_vnic *vnic;
691         int err;
692
693         DPRINTK("Probe passed device %s\n", dev->nodename);
694
695         vnic = netfront_accel_vnic_ctor(net_dev, dev);
696         if (IS_ERR(vnic))
697                 return PTR_ERR(vnic);
698
699         /*
700          * Setup a watch on the backend accel state.  This sets things
701          * going.
702          */
703         err = setup_dom0_accel_watch(dev, vnic);
704         if (err) {
705                 netfront_accel_vnic_dtor(vnic);
706                 EPRINTK("%s: probe failed with code %d\n", __FUNCTION__, err);
707                 return err;
708         }
709
710         /*
711          * Indicate to the other end that we're ready to start unless
712          * the watch has already fired.
713          */
714         mutex_lock(&vnic->vnic_mutex);
715         VPRINTK("setup success, updating accelstate\n");
716         if (vnic->frontend_state == XenbusStateClosed) {
717                 vnic->frontend_state = XenbusStateInitialising;
718                 net_accel_update_state(dev, XenbusStateInitialising);
719         }
720         mutex_unlock(&vnic->vnic_mutex);
721
722         DPRINTK("Probe done device %s\n", dev->nodename);
723
724         return 0;
725 }
726
727
728 int netfront_accel_remove(struct xenbus_device *dev)
729 {
730         struct netfront_info *np = dev_get_drvdata(&dev->dev);
731         netfront_accel_vnic *vnic = (netfront_accel_vnic *)np->accel_priv;
732
733         DPRINTK("%s %s\n", __FUNCTION__, dev->nodename);
734
735         BUG_ON(vnic == NULL);
736
737         mutex_lock(&vnic->vnic_mutex);
738
739         /* Reject any attempts to connect. */
740         vnic->removing = 1;
741
742         /* Close any existing connection. */
743         if (vnic->frontend_state == XenbusStateConnected) {
744                 vnic->frontend_state = XenbusStateClosing;
745                 net_accel_update_state(dev, XenbusStateClosing);
746         }
747
748         mutex_unlock(&vnic->vnic_mutex);
749
750         DPRINTK("%s waiting for release of %s\n", __FUNCTION__, dev->nodename);
751
752         /*
753          * Wait for the xenbus watch to release the shared resources.
754          * This indicates that dom0 has made the transition
755          * Closing->Closed or that dom0 was in Closed or Init and no
756          * resources were mapped.
757          */
758         wait_event(vnic->state_wait_queue,
759                    !vnic->domU_state_is_setup);
760
761         /*
762          * Now we don't need this watch anymore it is safe to remove
763          * it (and so synchronise with it completing if outstanding)
764          */
765         DPRINTK("%s: unregistering xenbus accel watch\n",
766                 __FUNCTION__);
767         unregister_xenbus_watch(&vnic->backend_accel_watch);
768         kfree(vnic->backend_accel_watch.node);
769
770         netfront_accel_vnic_dtor(vnic);
771
772         DPRINTK("%s done %s\n", __FUNCTION__, dev->nodename);
773
774         return 0;
775 }