ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/netback/interface.c @ 13233:d275951acf10

[LINUX] Extend the event-channel interfaces to provide helper methods
for creating interdomain event channels bound to IRQ handlers.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@localhost.localdomain
date Sat Dec 30 18:23:27 2006 +0000 (2006-12-30)
parents d9a0690399e0
children c4ed5b740a8d
line source
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 */
33 #include "common.h"
34 #include <linux/ethtool.h>
35 #include <linux/rtnetlink.h>
37 /*
38 * Module parameter 'queue_length':
39 *
40 * Enables queuing in the network stack when a client has run out of receive
41 * descriptors. Although this feature can improve receive bandwidth by avoiding
42 * packet loss, it can also result in packets sitting in the 'tx_queue' for
43 * unbounded time. This is bad if those packets hold onto foreign resources.
44 * For example, consider a packet that holds onto resources belonging to the
45 * guest for which it is queued (e.g., packet received on vif1.0, destined for
46 * vif1.1 which is not activated in the guest): in this situation the guest
47 * will never be destroyed, unless vif1.1 is taken down. To avoid this, we
48 * run a timer (tx_queue_timeout) to drain the queue when the interface is
49 * blocked.
50 */
51 static unsigned long netbk_queue_length = 32;
52 module_param_named(queue_length, netbk_queue_length, ulong, 0);
54 static void __netif_up(netif_t *netif)
55 {
56 enable_irq(netif->irq);
57 netif_schedule_work(netif);
58 }
60 static void __netif_down(netif_t *netif)
61 {
62 disable_irq(netif->irq);
63 netif_deschedule_work(netif);
64 }
66 static int net_open(struct net_device *dev)
67 {
68 netif_t *netif = netdev_priv(dev);
69 if (netif_carrier_ok(dev))
70 __netif_up(netif);
71 return 0;
72 }
74 static int net_close(struct net_device *dev)
75 {
76 netif_t *netif = netdev_priv(dev);
77 if (netif_carrier_ok(dev))
78 __netif_down(netif);
79 return 0;
80 }
82 static int netbk_change_mtu(struct net_device *dev, int mtu)
83 {
84 int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
86 if (mtu > max)
87 return -EINVAL;
88 dev->mtu = mtu;
89 return 0;
90 }
92 static int netbk_set_sg(struct net_device *dev, u32 data)
93 {
94 if (data) {
95 netif_t *netif = netdev_priv(dev);
97 if (!(netif->features & NETIF_F_SG))
98 return -ENOSYS;
99 }
101 return ethtool_op_set_sg(dev, data);
102 }
104 static int netbk_set_tso(struct net_device *dev, u32 data)
105 {
106 if (data) {
107 netif_t *netif = netdev_priv(dev);
109 if (!(netif->features & NETIF_F_TSO))
110 return -ENOSYS;
111 }
113 return ethtool_op_set_tso(dev, data);
114 }
116 static struct ethtool_ops network_ethtool_ops =
117 {
118 .get_tx_csum = ethtool_op_get_tx_csum,
119 .set_tx_csum = ethtool_op_set_tx_csum,
120 .get_sg = ethtool_op_get_sg,
121 .set_sg = netbk_set_sg,
122 .get_tso = ethtool_op_get_tso,
123 .set_tso = netbk_set_tso,
124 .get_link = ethtool_op_get_link,
125 };
127 netif_t *netif_alloc(domid_t domid, unsigned int handle)
128 {
129 int err = 0;
130 struct net_device *dev;
131 netif_t *netif;
132 char name[IFNAMSIZ] = {};
134 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
135 dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
136 if (dev == NULL) {
137 DPRINTK("Could not create netif: out of memory\n");
138 return ERR_PTR(-ENOMEM);
139 }
141 netif_carrier_off(dev);
143 netif = netdev_priv(dev);
144 memset(netif, 0, sizeof(*netif));
145 netif->domid = domid;
146 netif->handle = handle;
147 atomic_set(&netif->refcnt, 1);
148 init_waitqueue_head(&netif->waiting_to_free);
149 netif->dev = dev;
151 netif->credit_bytes = netif->remaining_credit = ~0UL;
152 netif->credit_usec = 0UL;
153 init_timer(&netif->credit_timeout);
154 /* Initialize 'expires' now: it's used to track the credit window. */
155 netif->credit_timeout.expires = jiffies;
157 init_timer(&netif->tx_queue_timeout);
159 dev->hard_start_xmit = netif_be_start_xmit;
160 dev->get_stats = netif_be_get_stats;
161 dev->open = net_open;
162 dev->stop = net_close;
163 dev->change_mtu = netbk_change_mtu;
164 dev->features = NETIF_F_IP_CSUM;
166 SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
168 dev->tx_queue_len = netbk_queue_length;
170 /*
171 * Initialise a dummy MAC address. We choose the numerically
172 * largest non-broadcast address to prevent the address getting
173 * stolen by an Ethernet bridge for STP purposes.
174 * (FE:FF:FF:FF:FF:FF)
175 */
176 memset(dev->dev_addr, 0xFF, ETH_ALEN);
177 dev->dev_addr[0] &= ~0x01;
179 rtnl_lock();
180 err = register_netdevice(dev);
181 rtnl_unlock();
182 if (err) {
183 DPRINTK("Could not register new net device %s: err=%d\n",
184 dev->name, err);
185 free_netdev(dev);
186 return ERR_PTR(err);
187 }
189 DPRINTK("Successfully created netif\n");
190 return netif;
191 }
193 static int map_frontend_pages(
194 netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
195 {
196 struct gnttab_map_grant_ref op;
197 int ret;
199 gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
200 GNTMAP_host_map, tx_ring_ref, netif->domid);
202 lock_vm_area(netif->tx_comms_area);
203 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
204 unlock_vm_area(netif->tx_comms_area);
205 BUG_ON(ret);
207 if (op.status) {
208 DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
209 return op.status;
210 }
212 netif->tx_shmem_ref = tx_ring_ref;
213 netif->tx_shmem_handle = op.handle;
215 gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
216 GNTMAP_host_map, rx_ring_ref, netif->domid);
218 lock_vm_area(netif->rx_comms_area);
219 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
220 unlock_vm_area(netif->rx_comms_area);
221 BUG_ON(ret);
223 if (op.status) {
224 DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
225 return op.status;
226 }
228 netif->rx_shmem_ref = rx_ring_ref;
229 netif->rx_shmem_handle = op.handle;
231 return 0;
232 }
234 static void unmap_frontend_pages(netif_t *netif)
235 {
236 struct gnttab_unmap_grant_ref op;
237 int ret;
239 gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
240 GNTMAP_host_map, netif->tx_shmem_handle);
242 lock_vm_area(netif->tx_comms_area);
243 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
244 unlock_vm_area(netif->tx_comms_area);
245 BUG_ON(ret);
247 gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
248 GNTMAP_host_map, netif->rx_shmem_handle);
250 lock_vm_area(netif->rx_comms_area);
251 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
252 unlock_vm_area(netif->rx_comms_area);
253 BUG_ON(ret);
254 }
256 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
257 unsigned long rx_ring_ref, unsigned int evtchn)
258 {
259 int err = -ENOMEM;
260 netif_tx_sring_t *txs;
261 netif_rx_sring_t *rxs;
263 /* Already connected through? */
264 if (netif->irq)
265 return 0;
267 netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
268 if (netif->tx_comms_area == NULL)
269 return -ENOMEM;
270 netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
271 if (netif->rx_comms_area == NULL)
272 goto err_rx;
274 err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
275 if (err)
276 goto err_map;
278 err = bind_interdomain_evtchn_to_irqhandler(
279 netif->domid, evtchn, netif_be_int, 0,
280 netif->dev->name, netif);
281 if (err < 0)
282 goto err_hypervisor;
283 netif->irq = err;
284 disable_irq(netif->irq);
286 txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
287 BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
289 rxs = (netif_rx_sring_t *)
290 ((char *)netif->rx_comms_area->addr);
291 BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
293 netif->rx_req_cons_peek = 0;
295 netif_get(netif);
297 rtnl_lock();
298 netif_carrier_on(netif->dev);
299 if (netif_running(netif->dev))
300 __netif_up(netif);
301 rtnl_unlock();
303 return 0;
304 err_hypervisor:
305 unmap_frontend_pages(netif);
306 err_map:
307 free_vm_area(netif->rx_comms_area);
308 err_rx:
309 free_vm_area(netif->tx_comms_area);
310 return err;
311 }
313 void netif_disconnect(netif_t *netif)
314 {
315 if (netif_carrier_ok(netif->dev)) {
316 rtnl_lock();
317 netif_carrier_off(netif->dev);
318 if (netif_running(netif->dev))
319 __netif_down(netif);
320 rtnl_unlock();
321 netif_put(netif);
322 }
324 atomic_dec(&netif->refcnt);
325 wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
327 del_timer_sync(&netif->credit_timeout);
328 del_timer_sync(&netif->tx_queue_timeout);
330 if (netif->irq)
331 unbind_from_irqhandler(netif->irq, netif);
333 unregister_netdev(netif->dev);
335 if (netif->tx.sring) {
336 unmap_frontend_pages(netif);
337 free_vm_area(netif->tx_comms_area);
338 free_vm_area(netif->rx_comms_area);
339 }
341 free_netdev(netif->dev);
342 }