ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/netback/interface.c @ 6697:a9a78ca76cd2

Replace direct_remap_area_pages with direct_remap_pfn_range to help fix PAE domain building.
Signed-off-by: ian@xensource.com
author iap10@freefall.cl.cam.ac.uk
date Wed Sep 07 23:10:49 2005 +0000 (2005-09-07)
parents 291e816acbf4
children 4cdf880c9463
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 */
9 #include "common.h"
10 #include <linux/rtnetlink.h>
12 static void __netif_up(netif_t *netif)
13 {
14 struct net_device *dev = netif->dev;
15 spin_lock_bh(&dev->xmit_lock);
16 netif->active = 1;
17 spin_unlock_bh(&dev->xmit_lock);
18 (void)bind_evtchn_to_irqhandler(
19 netif->evtchn, netif_be_int, 0, dev->name, netif);
20 netif_schedule_work(netif);
21 }
23 static void __netif_down(netif_t *netif)
24 {
25 struct net_device *dev = netif->dev;
26 spin_lock_bh(&dev->xmit_lock);
27 netif->active = 0;
28 spin_unlock_bh(&dev->xmit_lock);
29 unbind_evtchn_from_irqhandler(netif->evtchn, netif);
30 netif_deschedule_work(netif);
31 }
33 static int net_open(struct net_device *dev)
34 {
35 netif_t *netif = netdev_priv(dev);
36 if (netif->status == CONNECTED)
37 __netif_up(netif);
38 netif_start_queue(dev);
39 return 0;
40 }
42 static int net_close(struct net_device *dev)
43 {
44 netif_t *netif = netdev_priv(dev);
45 netif_stop_queue(dev);
46 if (netif->status == CONNECTED)
47 __netif_down(netif);
48 return 0;
49 }
51 netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
52 {
53 int err = 0, i;
54 struct net_device *dev;
55 netif_t *netif;
56 char name[IFNAMSIZ] = {};
58 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
59 dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
60 if (dev == NULL) {
61 DPRINTK("Could not create netif: out of memory\n");
62 return NULL;
63 }
65 netif = netdev_priv(dev);
66 memset(netif, 0, sizeof(*netif));
67 netif->domid = domid;
68 netif->handle = handle;
69 netif->status = DISCONNECTED;
70 atomic_set(&netif->refcnt, 0);
71 netif->dev = dev;
73 netif->credit_bytes = netif->remaining_credit = ~0UL;
74 netif->credit_usec = 0UL;
75 init_timer(&netif->credit_timeout);
77 dev->hard_start_xmit = netif_be_start_xmit;
78 dev->get_stats = netif_be_get_stats;
79 dev->open = net_open;
80 dev->stop = net_close;
81 dev->features = NETIF_F_NO_CSUM;
83 /* Disable queuing. */
84 dev->tx_queue_len = 0;
86 for (i = 0; i < ETH_ALEN; i++)
87 if (be_mac[i] != 0)
88 break;
89 if (i == ETH_ALEN) {
90 /*
91 * Initialise a dummy MAC address. We choose the numerically largest
92 * non-broadcast address to prevent the address getting stolen by an
93 * Ethernet bridge for STP purposes. (FE:FF:FF:FF:FF:FF)
94 */
95 memset(dev->dev_addr, 0xFF, ETH_ALEN);
96 dev->dev_addr[0] &= ~0x01;
97 } else
98 memcpy(dev->dev_addr, be_mac, ETH_ALEN);
100 rtnl_lock();
101 err = register_netdevice(dev);
102 rtnl_unlock();
103 if (err) {
104 DPRINTK("Could not register new net device %s: err=%d\n",
105 dev->name, err);
106 free_netdev(dev);
107 return NULL;
108 }
110 DPRINTK("Successfully created netif\n");
111 return netif;
112 }
114 static int map_frontend_pages(netif_t *netif, unsigned long localaddr,
115 unsigned long tx_ring_ref,
116 unsigned long rx_ring_ref)
117 {
118 #ifdef CONFIG_XEN_NETDEV_GRANT
119 struct gnttab_map_grant_ref op;
121 /* Map: Use the Grant table reference */
122 op.host_addr = localaddr;
123 op.flags = GNTMAP_host_map;
124 op.ref = tx_ring_ref;
125 op.dom = netif->domid;
127 BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
128 if (op.handle < 0) {
129 DPRINTK(" Grant table operation failure mapping tx_ring_ref!\n");
130 return op.handle;
131 }
133 netif->tx_shmem_ref = tx_ring_ref;
134 netif->tx_shmem_handle = op.handle;
135 netif->tx_shmem_vaddr = localaddr;
137 /* Map: Use the Grant table reference */
138 op.host_addr = localaddr + PAGE_SIZE;
139 op.flags = GNTMAP_host_map;
140 op.ref = rx_ring_ref;
141 op.dom = netif->domid;
143 BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
144 if (op.handle < 0) {
145 DPRINTK(" Grant table operation failure mapping rx_ring_ref!\n");
146 return op.handle;
147 }
149 netif->rx_shmem_ref = rx_ring_ref;
150 netif->rx_shmem_handle = op.handle;
151 netif->rx_shmem_vaddr = localaddr + PAGE_SIZE;
153 #else
154 pgprot_t prot = __pgprot(_KERNPG_TABLE);
155 int err;
157 err = direct_remap_pfn_range(&init_mm, localaddr,
158 tx_ring_ref, PAGE_SIZE,
159 prot, netif->domid);
161 err |= direct_remap_pfn_range(&init_mm, localaddr + PAGE_SIZE,
162 rx_ring_ref, PAGE_SIZE,
163 prot, netif->domid);
165 if (err)
166 return err;
167 #endif
169 return 0;
170 }
172 static void unmap_frontend_pages(netif_t *netif)
173 {
174 #ifdef CONFIG_XEN_NETDEV_GRANT
175 struct gnttab_unmap_grant_ref op;
177 op.host_addr = netif->tx_shmem_vaddr;
178 op.handle = netif->tx_shmem_handle;
179 op.dev_bus_addr = 0;
180 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
182 op.host_addr = netif->rx_shmem_vaddr;
183 op.handle = netif->rx_shmem_handle;
184 op.dev_bus_addr = 0;
185 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
186 #endif
188 return;
189 }
191 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
192 unsigned long rx_ring_ref, unsigned int evtchn)
193 {
194 struct vm_struct *vma;
195 evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
196 int err;
198 vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP);
199 if (vma == NULL)
200 return -ENOMEM;
202 err = map_frontend_pages(netif, (unsigned long)vma->addr, tx_ring_ref,
203 rx_ring_ref);
204 if (err) {
205 vfree(vma->addr);
206 return err;
207 }
209 op.u.bind_interdomain.dom1 = DOMID_SELF;
210 op.u.bind_interdomain.dom2 = netif->domid;
211 op.u.bind_interdomain.port1 = 0;
212 op.u.bind_interdomain.port2 = evtchn;
213 err = HYPERVISOR_event_channel_op(&op);
214 if (err) {
215 unmap_frontend_pages(netif);
216 vfree(vma->addr);
217 return err;
218 }
220 netif->evtchn = op.u.bind_interdomain.port1;
221 netif->remote_evtchn = evtchn;
223 netif->tx = (netif_tx_interface_t *)vma->addr;
224 netif->rx = (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
225 netif->tx->resp_prod = netif->rx->resp_prod = 0;
226 netif_get(netif);
227 wmb(); /* Other CPUs see new state before interface is started. */
229 rtnl_lock();
230 netif->status = CONNECTED;
231 wmb();
232 if (netif_running(netif->dev))
233 __netif_up(netif);
234 rtnl_unlock();
236 return 0;
237 }
239 static void free_netif(void *arg)
240 {
241 evtchn_op_t op = { .cmd = EVTCHNOP_close };
242 netif_t *netif = (netif_t *)arg;
244 /*
245 * These can't be done in netif_disconnect() because at that point there
246 * may be outstanding requests in the network stack whose asynchronous
247 * responses must still be notified to the remote driver.
248 */
250 op.u.close.port = netif->evtchn;
251 op.u.close.dom = DOMID_SELF;
252 HYPERVISOR_event_channel_op(&op);
253 op.u.close.port = netif->remote_evtchn;
254 op.u.close.dom = netif->domid;
255 HYPERVISOR_event_channel_op(&op);
257 unregister_netdev(netif->dev);
259 if (netif->tx) {
260 unmap_frontend_pages(netif);
261 vfree(netif->tx); /* Frees netif->rx as well. */
262 }
264 free_netdev(netif->dev);
265 }
267 void free_netif_callback(netif_t *netif)
268 {
269 INIT_WORK(&netif->free_work, free_netif, (void *)netif);
270 schedule_work(&netif->free_work);
271 }
273 void netif_creditlimit(netif_t *netif)
274 {
275 #if 0
276 /* Set the credit limit (reset remaining credit to new limit). */
277 netif->credit_bytes = netif->remaining_credit = creditlimit->credit_bytes;
278 netif->credit_usec = creditlimit->period_usec;
280 if (netif->status == CONNECTED) {
281 /*
282 * Schedule work so that any packets waiting under previous credit
283 * limit are dealt with (acts like a replenishment point).
284 */
285 netif->credit_timeout.expires = jiffies;
286 netif_schedule_work(netif);
287 }
288 #endif
289 }
291 int netif_disconnect(netif_t *netif)
292 {
294 if (netif->status == CONNECTED) {
295 rtnl_lock();
296 netif->status = DISCONNECTING;
297 wmb();
298 if (netif_running(netif->dev))
299 __netif_down(netif);
300 rtnl_unlock();
301 netif_put(netif);
302 return 0; /* Caller should not send response message. */
303 }
305 return 1;
306 }