direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/netback/interface.c @ 11730:fd80b7e1e333

[NET] back: Refcount fixes to vif rate-limiting code.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Oct 09 17:08:18 2006 +0100 (2006-10-09)
parents 224b80785d02
children cb337b2f817b
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 (which flushes the
48 * 'tx_queue').
49 *
50 * Only set this parameter to non-zero value if you know what you are doing!
51 */
52 static unsigned long netbk_queue_length = 0;
53 module_param_named(queue_length, netbk_queue_length, ulong, 0);
55 static void __netif_up(netif_t *netif)
56 {
57 enable_irq(netif->irq);
58 netif_schedule_work(netif);
59 }
61 static void __netif_down(netif_t *netif)
62 {
63 disable_irq(netif->irq);
64 netif_deschedule_work(netif);
65 del_timer_sync(&netif->credit_timeout);
66 }
68 static int net_open(struct net_device *dev)
69 {
70 netif_t *netif = netdev_priv(dev);
71 if (netif_carrier_ok(dev))
72 __netif_up(netif);
73 return 0;
74 }
76 static int net_close(struct net_device *dev)
77 {
78 netif_t *netif = netdev_priv(dev);
79 if (netif_carrier_ok(dev))
80 __netif_down(netif);
81 return 0;
82 }
84 static int netbk_change_mtu(struct net_device *dev, int mtu)
85 {
86 int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
88 if (mtu > max)
89 return -EINVAL;
90 dev->mtu = mtu;
91 return 0;
92 }
94 static int netbk_set_sg(struct net_device *dev, u32 data)
95 {
96 if (data) {
97 netif_t *netif = netdev_priv(dev);
99 if (!(netif->features & NETIF_F_SG))
100 return -ENOSYS;
101 }
103 return ethtool_op_set_sg(dev, data);
104 }
106 static int netbk_set_tso(struct net_device *dev, u32 data)
107 {
108 if (data) {
109 netif_t *netif = netdev_priv(dev);
111 if (!(netif->features & NETIF_F_TSO))
112 return -ENOSYS;
113 }
115 return ethtool_op_set_tso(dev, data);
116 }
118 static struct ethtool_ops network_ethtool_ops =
119 {
120 .get_tx_csum = ethtool_op_get_tx_csum,
121 .set_tx_csum = ethtool_op_set_tx_csum,
122 .get_sg = ethtool_op_get_sg,
123 .set_sg = netbk_set_sg,
124 .get_tso = ethtool_op_get_tso,
125 .set_tso = netbk_set_tso,
126 .get_link = ethtool_op_get_link,
127 };
129 netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
130 {
131 int err = 0, i;
132 struct net_device *dev;
133 netif_t *netif;
134 char name[IFNAMSIZ] = {};
136 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
137 dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
138 if (dev == NULL) {
139 DPRINTK("Could not create netif: out of memory\n");
140 return ERR_PTR(-ENOMEM);
141 }
143 netif_carrier_off(dev);
145 netif = netdev_priv(dev);
146 memset(netif, 0, sizeof(*netif));
147 netif->domid = domid;
148 netif->handle = handle;
149 atomic_set(&netif->refcnt, 1);
150 init_waitqueue_head(&netif->waiting_to_free);
151 netif->dev = dev;
153 netif->credit_bytes = netif->remaining_credit = ~0UL;
154 netif->credit_usec = 0UL;
155 init_timer(&netif->credit_timeout);
157 dev->hard_start_xmit = netif_be_start_xmit;
158 dev->get_stats = netif_be_get_stats;
159 dev->open = net_open;
160 dev->stop = net_close;
161 dev->change_mtu = netbk_change_mtu;
162 dev->features = NETIF_F_IP_CSUM;
164 SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
166 dev->tx_queue_len = netbk_queue_length;
167 if (dev->tx_queue_len != 0)
168 printk(KERN_WARNING "netbk: WARNING: device '%s' has non-zero "
169 "queue length (%lu)!\n", dev->name, dev->tx_queue_len);
171 for (i = 0; i < ETH_ALEN; i++)
172 if (be_mac[i] != 0)
173 break;
174 if (i == ETH_ALEN) {
175 /*
176 * Initialise a dummy MAC address. We choose the numerically
177 * largest non-broadcast address to prevent the address getting
178 * stolen by an Ethernet bridge for STP purposes.
179 * (FE:FF:FF:FF:FF:FF)
180 */
181 memset(dev->dev_addr, 0xFF, ETH_ALEN);
182 dev->dev_addr[0] &= ~0x01;
183 } else
184 memcpy(dev->dev_addr, be_mac, ETH_ALEN);
186 rtnl_lock();
187 err = register_netdevice(dev);
188 rtnl_unlock();
189 if (err) {
190 DPRINTK("Could not register new net device %s: err=%d\n",
191 dev->name, err);
192 free_netdev(dev);
193 return ERR_PTR(err);
194 }
196 DPRINTK("Successfully created netif\n");
197 return netif;
198 }
200 static int map_frontend_pages(
201 netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
202 {
203 struct gnttab_map_grant_ref op;
204 int ret;
206 gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
207 GNTMAP_host_map, tx_ring_ref, netif->domid);
209 lock_vm_area(netif->tx_comms_area);
210 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
211 unlock_vm_area(netif->tx_comms_area);
212 BUG_ON(ret);
214 if (op.status) {
215 DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
216 return op.status;
217 }
219 netif->tx_shmem_ref = tx_ring_ref;
220 netif->tx_shmem_handle = op.handle;
222 gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
223 GNTMAP_host_map, rx_ring_ref, netif->domid);
225 lock_vm_area(netif->rx_comms_area);
226 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
227 unlock_vm_area(netif->rx_comms_area);
228 BUG_ON(ret);
230 if (op.status) {
231 DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
232 return op.status;
233 }
235 netif->rx_shmem_ref = rx_ring_ref;
236 netif->rx_shmem_handle = op.handle;
238 return 0;
239 }
241 static void unmap_frontend_pages(netif_t *netif)
242 {
243 struct gnttab_unmap_grant_ref op;
244 int ret;
246 gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
247 GNTMAP_host_map, netif->tx_shmem_handle);
249 lock_vm_area(netif->tx_comms_area);
250 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
251 unlock_vm_area(netif->tx_comms_area);
252 BUG_ON(ret);
254 gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
255 GNTMAP_host_map, netif->rx_shmem_handle);
257 lock_vm_area(netif->rx_comms_area);
258 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
259 unlock_vm_area(netif->rx_comms_area);
260 BUG_ON(ret);
261 }
263 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
264 unsigned long rx_ring_ref, unsigned int evtchn)
265 {
266 int err = -ENOMEM;
267 netif_tx_sring_t *txs;
268 netif_rx_sring_t *rxs;
269 struct evtchn_bind_interdomain bind_interdomain;
271 /* Already connected through? */
272 if (netif->irq)
273 return 0;
275 netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
276 if (netif->tx_comms_area == NULL)
277 return -ENOMEM;
278 netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
279 if (netif->rx_comms_area == NULL)
280 goto err_rx;
282 err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
283 if (err)
284 goto err_map;
286 bind_interdomain.remote_dom = netif->domid;
287 bind_interdomain.remote_port = evtchn;
289 err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
290 &bind_interdomain);
291 if (err)
292 goto err_hypervisor;
294 netif->evtchn = bind_interdomain.local_port;
296 netif->irq = bind_evtchn_to_irqhandler(
297 netif->evtchn, netif_be_int, 0, netif->dev->name, netif);
298 disable_irq(netif->irq);
300 txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
301 BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
303 rxs = (netif_rx_sring_t *)
304 ((char *)netif->rx_comms_area->addr);
305 BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
307 netif->rx_req_cons_peek = 0;
309 netif_get(netif);
311 rtnl_lock();
312 netif_carrier_on(netif->dev);
313 if (netif_running(netif->dev))
314 __netif_up(netif);
315 rtnl_unlock();
317 return 0;
318 err_hypervisor:
319 unmap_frontend_pages(netif);
320 err_map:
321 free_vm_area(netif->rx_comms_area);
322 err_rx:
323 free_vm_area(netif->tx_comms_area);
324 return err;
325 }
327 static void netif_free(netif_t *netif)
328 {
329 atomic_dec(&netif->refcnt);
330 wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
332 if (netif->irq)
333 unbind_from_irqhandler(netif->irq, netif);
335 unregister_netdev(netif->dev);
337 if (netif->tx.sring) {
338 unmap_frontend_pages(netif);
339 free_vm_area(netif->tx_comms_area);
340 free_vm_area(netif->rx_comms_area);
341 }
343 free_netdev(netif->dev);
344 }
346 void netif_disconnect(netif_t *netif)
347 {
348 if (netif_carrier_ok(netif->dev)) {
349 rtnl_lock();
350 netif_carrier_off(netif->dev);
351 if (netif_running(netif->dev))
352 __netif_down(netif);
353 rtnl_unlock();
354 netif_put(netif);
355 }
356 netif_free(netif);
357 }