- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / sfc_netback / accel.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 "accel.h"
26 #include "accel_msg_iface.h"
27 #include "accel_solarflare.h"
28
29 #include <linux/notifier.h>
30
31 #ifdef EFX_GCOV
32 #include "gcov.h"
33 #endif
34
35 static int netback_accel_netdev_event(struct notifier_block *nb,
36                                       unsigned long event, void *ptr)
37 {
38         struct net_device *net_dev = (struct net_device *)ptr;
39         struct netback_accel *bend;
40
41         if ((event == NETDEV_UP) || 
42             (event == NETDEV_DOWN) ||
43             (event == NETDEV_CHANGE)) {
44                 mutex_lock(&bend_list_mutex);
45                 bend = bend_list;
46                 while (bend != NULL) {
47                         mutex_lock(&bend->bend_mutex);
48                         /*
49                          * This happens when the shared pages have
50                          * been unmapped, but the bend not yet removed
51                          * from list
52                          */
53                         if (bend->shared_page == NULL)
54                                 goto next;
55
56                         if (bend->net_dev->ifindex == net_dev->ifindex) {
57                                 int ok;
58                                 if (event == NETDEV_CHANGE)
59                                         ok = (netif_carrier_ok(net_dev) && 
60                                               (net_dev->flags & IFF_UP));
61                                 else
62                                         ok = (netif_carrier_ok(net_dev) && 
63                                               (event == NETDEV_UP));
64                                 netback_accel_set_interface_state(bend, ok);
65                         }
66
67                 next:
68                         mutex_unlock(&bend->bend_mutex);
69                         bend = bend->next_bend;
70                 }
71                 mutex_unlock(&bend_list_mutex);
72         }
73
74         return NOTIFY_DONE;
75 }
76
77
78 static struct notifier_block netback_accel_netdev_notifier = {
79         .notifier_call = netback_accel_netdev_event,
80 };
81
82
83 unsigned sfc_netback_max_pages = NETBACK_ACCEL_DEFAULT_MAX_BUF_PAGES;
84 module_param_named(max_pages, sfc_netback_max_pages, uint, 0644);
85 MODULE_PARM_DESC(max_pages, 
86                  "The number of buffer pages to enforce on each guest");
87
88 /* Initialise subsystems need for the accelerated fast path */
89 static int __init netback_accel_init(void)
90 {
91         int rc = 0;
92
93 #ifdef EFX_GCOV
94         gcov_provider_init(THIS_MODULE);
95 #endif
96
97         rc = netback_accel_init_fwd();
98         if (rc != 0)
99                 goto fail0;
100
101         netback_accel_debugfs_init();
102
103         rc = netback_accel_sf_init();
104         if (rc != 0)
105                 goto fail1;
106
107         rc = register_netdevice_notifier
108                 (&netback_accel_netdev_notifier);
109         if (rc != 0)
110                 goto fail2;
111
112         return 0;
113
114  fail2:
115         netback_accel_sf_shutdown();
116  fail1:
117         netback_accel_debugfs_fini();
118         netback_accel_shutdown_fwd();
119  fail0:
120 #ifdef EFX_GCOV
121         gcov_provider_fini(THIS_MODULE);
122 #endif
123         return rc;
124 }
125
126 module_init(netback_accel_init);
127
128 static void __exit netback_accel_exit(void)
129 {
130         unregister_netdevice_notifier(&netback_accel_netdev_notifier);
131
132         netback_accel_sf_shutdown();
133
134         netback_accel_shutdown_bends();
135
136         netback_accel_debugfs_fini();
137
138         netback_accel_shutdown_fwd();
139
140 #ifdef EFX_GCOV
141         gcov_provider_fini(THIS_MODULE);
142 #endif
143 }
144
145 module_exit(netback_accel_exit);
146
147 MODULE_LICENSE("GPL");