Merge to Fedora kernel-2.6.17-1.2187_FC5 patched with stable patch-2.6.17.13-vs2...
[linux-2.6.git] / drivers / xen / netback / interface.c
1 /******************************************************************************
2  * arch/xen/drivers/netif/backend/interface.c
3  * 
4  * Network-device interface management.
5  * 
6  * Copyright (c) 2004-2005, Keir Fraser
7  * 
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation; or, when distributed
11  * separately from the Linux kernel or incorporated into other
12  * software packages, subject to the following license:
13  * 
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this source file (the "Software"), to deal in the Software without
16  * restriction, including without limitation the rights to use, copy, modify,
17  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18  * and to permit persons to whom the Software is furnished to do so, subject to
19  * the following conditions:
20  * 
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  * 
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * IN THE SOFTWARE.
31  */
32
33 #include "common.h"
34 #include <linux/ethtool.h>
35 #include <linux/rtnetlink.h>
36
37 static void __netif_up(netif_t *netif)
38 {
39         enable_irq(netif->irq);
40         netif_schedule_work(netif);
41 }
42
43 static void __netif_down(netif_t *netif)
44 {
45         disable_irq(netif->irq);
46         netif_deschedule_work(netif);
47 }
48
49 static int net_open(struct net_device *dev)
50 {
51         netif_t *netif = netdev_priv(dev);
52         if (netif_carrier_ok(dev))
53                 __netif_up(netif);
54         return 0;
55 }
56
57 static int net_close(struct net_device *dev)
58 {
59         netif_t *netif = netdev_priv(dev);
60         if (netif_carrier_ok(dev))
61                 __netif_down(netif);
62         return 0;
63 }
64
65 static int netbk_change_mtu(struct net_device *dev, int mtu)
66 {
67         int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
68
69         if (mtu > max)
70                 return -EINVAL;
71         dev->mtu = mtu;
72         return 0;
73 }
74
75 static int netbk_set_sg(struct net_device *dev, u32 data)
76 {
77         if (data) {
78                 netif_t *netif = netdev_priv(dev);
79
80                 if (!(netif->features & NETIF_F_SG))
81                         return -ENOSYS;
82         }
83
84         return ethtool_op_set_sg(dev, data);
85 }
86
87 static int netbk_set_tso(struct net_device *dev, u32 data)
88 {
89         if (data) {
90                 netif_t *netif = netdev_priv(dev);
91
92                 if (!(netif->features & NETIF_F_TSO))
93                         return -ENOSYS;
94         }
95
96         return ethtool_op_set_tso(dev, data);
97 }
98
99 static struct ethtool_ops network_ethtool_ops =
100 {
101         .get_tx_csum = ethtool_op_get_tx_csum,
102         .set_tx_csum = ethtool_op_set_tx_csum,
103         .get_sg = ethtool_op_get_sg,
104         .set_sg = netbk_set_sg,
105         .get_tso = ethtool_op_get_tso,
106         .set_tso = netbk_set_tso,
107         .get_link = ethtool_op_get_link,
108 };
109
110 netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
111 {
112         int err = 0, i;
113         struct net_device *dev;
114         netif_t *netif;
115         char name[IFNAMSIZ] = {};
116
117         snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
118         dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
119         if (dev == NULL) {
120                 DPRINTK("Could not create netif: out of memory\n");
121                 return ERR_PTR(-ENOMEM);
122         }
123
124         netif_carrier_off(dev);
125
126         netif = netdev_priv(dev);
127         memset(netif, 0, sizeof(*netif));
128         netif->domid  = domid;
129         netif->handle = handle;
130         atomic_set(&netif->refcnt, 1);
131         init_waitqueue_head(&netif->waiting_to_free);
132         netif->dev = dev;
133
134         netif->credit_bytes = netif->remaining_credit = ~0UL;
135         netif->credit_usec  = 0UL;
136         init_timer(&netif->credit_timeout);
137
138         dev->hard_start_xmit = netif_be_start_xmit;
139         dev->get_stats       = netif_be_get_stats;
140         dev->open            = net_open;
141         dev->stop            = net_close;
142         dev->change_mtu      = netbk_change_mtu;
143         dev->features        = NETIF_F_IP_CSUM;
144
145         SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
146
147         /*
148          * Reduce default TX queuelen so that each guest interface only
149          * allows it to eat around 6.4MB of host memory.
150          */
151         dev->tx_queue_len = 100;
152
153         for (i = 0; i < ETH_ALEN; i++)
154                 if (be_mac[i] != 0)
155                         break;
156         if (i == ETH_ALEN) {
157                 /*
158                  * Initialise a dummy MAC address. We choose the numerically
159                  * largest non-broadcast address to prevent the address getting
160                  * stolen by an Ethernet bridge for STP purposes.
161                  * (FE:FF:FF:FF:FF:FF)
162                  */ 
163                 memset(dev->dev_addr, 0xFF, ETH_ALEN);
164                 dev->dev_addr[0] &= ~0x01;
165         } else
166                 memcpy(dev->dev_addr, be_mac, ETH_ALEN);
167
168         rtnl_lock();
169         err = register_netdevice(dev);
170         rtnl_unlock();
171         if (err) {
172                 DPRINTK("Could not register new net device %s: err=%d\n",
173                         dev->name, err);
174                 free_netdev(dev);
175                 return ERR_PTR(err);
176         }
177
178         DPRINTK("Successfully created netif\n");
179         return netif;
180 }
181
182 static int map_frontend_pages(
183         netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
184 {
185         struct gnttab_map_grant_ref op;
186         int ret;
187
188         gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
189                           GNTMAP_host_map, tx_ring_ref, netif->domid);
190     
191         lock_vm_area(netif->tx_comms_area);
192         ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
193         unlock_vm_area(netif->tx_comms_area);
194         BUG_ON(ret);
195
196         if (op.status) { 
197                 DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
198                 return op.status;
199         }
200
201         netif->tx_shmem_ref    = tx_ring_ref;
202         netif->tx_shmem_handle = op.handle;
203
204         gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
205                           GNTMAP_host_map, rx_ring_ref, netif->domid);
206
207         lock_vm_area(netif->rx_comms_area);
208         ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
209         unlock_vm_area(netif->rx_comms_area);
210         BUG_ON(ret);
211
212         if (op.status) {
213                 DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
214                 return op.status;
215         }
216
217         netif->rx_shmem_ref    = rx_ring_ref;
218         netif->rx_shmem_handle = op.handle;
219
220         return 0;
221 }
222
223 static void unmap_frontend_pages(netif_t *netif)
224 {
225         struct gnttab_unmap_grant_ref op;
226         int ret;
227
228         gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
229                             GNTMAP_host_map, netif->tx_shmem_handle);
230
231         lock_vm_area(netif->tx_comms_area);
232         ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
233         unlock_vm_area(netif->tx_comms_area);
234         BUG_ON(ret);
235
236         gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
237                             GNTMAP_host_map, netif->rx_shmem_handle);
238
239         lock_vm_area(netif->rx_comms_area);
240         ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
241         unlock_vm_area(netif->rx_comms_area);
242         BUG_ON(ret);
243 }
244
245 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
246               unsigned long rx_ring_ref, unsigned int evtchn)
247 {
248         int err = -ENOMEM;
249         netif_tx_sring_t *txs;
250         netif_rx_sring_t *rxs;
251         struct evtchn_bind_interdomain bind_interdomain;
252
253         /* Already connected through? */
254         if (netif->irq)
255                 return 0;
256
257         netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
258         if (netif->tx_comms_area == NULL)
259                 return -ENOMEM;
260         netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
261         if (netif->rx_comms_area == NULL)
262                 goto err_rx;
263
264         err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
265         if (err)
266                 goto err_map;
267
268         bind_interdomain.remote_dom = netif->domid;
269         bind_interdomain.remote_port = evtchn;
270
271         err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
272                                           &bind_interdomain);
273         if (err)
274                 goto err_hypervisor;
275
276         netif->evtchn = bind_interdomain.local_port;
277
278         netif->irq = bind_evtchn_to_irqhandler(
279                 netif->evtchn, netif_be_int, 0, netif->dev->name, netif);
280         disable_irq(netif->irq);
281
282         txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
283         BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
284
285         rxs = (netif_rx_sring_t *)
286                 ((char *)netif->rx_comms_area->addr);
287         BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
288
289         netif->rx_req_cons_peek = 0;
290
291         netif_get(netif);
292
293         rtnl_lock();
294         netif_carrier_on(netif->dev);
295         if (netif_running(netif->dev))
296                 __netif_up(netif);
297         rtnl_unlock();
298
299         return 0;
300 err_hypervisor:
301         unmap_frontend_pages(netif);
302 err_map:
303         free_vm_area(netif->rx_comms_area);
304 err_rx:
305         free_vm_area(netif->tx_comms_area);
306         return err;
307 }
308
309 static void netif_free(netif_t *netif)
310 {
311         atomic_dec(&netif->refcnt);
312         wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
313
314         if (netif->irq)
315                 unbind_from_irqhandler(netif->irq, netif);
316         
317         unregister_netdev(netif->dev);
318
319         if (netif->tx.sring) {
320                 unmap_frontend_pages(netif);
321                 free_vm_area(netif->tx_comms_area);
322                 free_vm_area(netif->rx_comms_area);
323         }
324
325         free_netdev(netif->dev);
326 }
327
328 void netif_disconnect(netif_t *netif)
329 {
330         if (netif_carrier_ok(netif->dev)) {
331                 rtnl_lock();
332                 netif_carrier_off(netif->dev);
333                 if (netif_running(netif->dev))
334                         __netif_down(netif);
335                 rtnl_unlock();
336                 netif_put(netif);
337         }
338         netif_free(netif);
339 }