direct-io.hg

view xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c @ 1443:180c1407b64f

bitkeeper revision 1.943 (40c6c10f90gVdztSEe31gGHbItwLwg)

interface.c:
Net backend rename
author kaf24@scramble.cl.cam.ac.uk
date Wed Jun 09 07:49:35 2004 +0000 (2004-06-09)
parents 00e1d3ae9894
children
line source
1 /******************************************************************************
2 * arch/xen/drivers/netif/backend/interface.c
3 *
4 * Network-device interface management.
5 *
6 * Copyright (c) 2004, Keir Fraser
7 */
9 #include "common.h"
10 #include <linux/rtnetlink.h>
12 #define NETIF_HASHSZ 1024
13 #define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1))
15 static netif_t *netif_hash[NETIF_HASHSZ];
16 static struct net_device *bridge_dev;
17 static struct net_bridge *bridge_br;
19 netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
20 {
21 netif_t *netif = netif_hash[NETIF_HASH(domid, handle)];
22 while ( (netif != NULL) &&
23 ((netif->domid != domid) || (netif->handle != handle)) )
24 netif = netif->hash_next;
25 return netif;
26 }
28 void __netif_disconnect_complete(netif_t *netif)
29 {
30 ctrl_msg_t cmsg;
31 netif_be_disconnect_t disc;
33 /*
34 * These can't be done in __netif_disconnect() because at that point there
35 * may be outstanding requests at the disc whose asynchronous responses
36 * must still be notified to the remote driver.
37 */
38 unbind_evtchn_from_irq(netif->evtchn);
39 vfree(netif->tx); /* Frees netif->rx as well. */
40 rtnl_lock();
41 (void)br_del_if(bridge_br, netif->dev);
42 (void)dev_close(netif->dev);
43 rtnl_unlock();
45 /* Construct the deferred response message. */
46 cmsg.type = CMSG_NETIF_BE;
47 cmsg.subtype = CMSG_NETIF_BE_DISCONNECT;
48 cmsg.id = netif->disconnect_rspid;
49 cmsg.length = sizeof(netif_be_disconnect_t);
50 disc.domid = netif->domid;
51 disc.netif_handle = netif->handle;
52 disc.status = NETIF_BE_STATUS_OKAY;
53 memcpy(cmsg.msg, &disc, sizeof(disc));
55 /*
56 * Make sure message is constructed /before/ status change, because
57 * after the status change the 'netif' structure could be deallocated at
58 * any time. Also make sure we send the response /after/ status change,
59 * as otherwise a subsequent CONNECT request could spuriously fail if
60 * another CPU doesn't see the status change yet.
61 */
62 mb();
63 if ( netif->status != DISCONNECTING )
64 BUG();
65 netif->status = DISCONNECTED;
66 mb();
68 /* Send the successful response. */
69 ctrl_if_send_response(&cmsg);
70 }
72 void netif_create(netif_be_create_t *create)
73 {
74 domid_t domid = create->domid;
75 unsigned int handle = create->netif_handle;
76 struct net_device *dev;
77 netif_t **pnetif, *netif;
78 char name[IFNAMSIZ];
80 snprintf(name, IFNAMSIZ, "vif%u.%u", domid, handle);
81 dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
82 if ( dev == NULL )
83 {
84 DPRINTK("Could not create netif: out of memory\n");
85 create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
86 return;
87 }
89 netif = dev->priv;
90 memset(netif, 0, sizeof(*netif));
91 netif->domid = domid;
92 netif->handle = handle;
93 netif->status = DISCONNECTED;
94 spin_lock_init(&netif->rx_lock);
95 spin_lock_init(&netif->tx_lock);
96 atomic_set(&netif->refcnt, 0);
97 netif->dev = dev;
99 netif->credit_bytes = netif->remaining_credit = ~0UL;
100 netif->credit_usec = 0UL;
101 /*init_ac_timer(&new_vif->credit_timeout);*/
103 pnetif = &netif_hash[NETIF_HASH(domid, handle)];
104 while ( *pnetif != NULL )
105 {
106 if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
107 {
108 DPRINTK("Could not create netif: already exists\n");
109 create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
110 kfree(dev);
111 return;
112 }
113 pnetif = &(*pnetif)->hash_next;
114 }
116 dev->hard_start_xmit = netif_be_start_xmit;
117 dev->get_stats = netif_be_get_stats;
118 memcpy(dev->dev_addr, create->mac, ETH_ALEN);
120 /* Disable queuing. */
121 dev->tx_queue_len = 0;
123 /* XXX In bridge mode we should force a different MAC from remote end. */
124 dev->dev_addr[2] ^= 1;
126 if ( register_netdev(dev) != 0 )
127 {
128 DPRINTK("Could not register new net device\n");
129 create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
130 kfree(dev);
131 return;
132 }
134 netif->hash_next = *pnetif;
135 *pnetif = netif;
137 DPRINTK("Successfully created netif\n");
138 create->status = NETIF_BE_STATUS_OKAY;
139 }
141 void netif_destroy(netif_be_destroy_t *destroy)
142 {
143 domid_t domid = destroy->domid;
144 unsigned int handle = destroy->netif_handle;
145 netif_t **pnetif, *netif;
147 pnetif = &netif_hash[NETIF_HASH(domid, handle)];
148 while ( (netif = *pnetif) != NULL )
149 {
150 if ( (netif->domid == domid) && (netif->handle == handle) )
151 {
152 if ( netif->status != DISCONNECTED )
153 goto still_connected;
154 goto destroy;
155 }
156 pnetif = &netif->hash_next;
157 }
159 destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
160 return;
162 still_connected:
163 destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
164 return;
166 destroy:
167 *pnetif = netif->hash_next;
168 unregister_netdev(netif->dev);
169 kfree(netif->dev);
170 destroy->status = NETIF_BE_STATUS_OKAY;
171 }
173 void netif_connect(netif_be_connect_t *connect)
174 {
175 domid_t domid = connect->domid;
176 unsigned int handle = connect->netif_handle;
177 unsigned int evtchn = connect->evtchn;
178 unsigned long tx_shmem_frame = connect->tx_shmem_frame;
179 unsigned long rx_shmem_frame = connect->rx_shmem_frame;
180 struct vm_struct *vma;
181 pgprot_t prot;
182 int error;
183 netif_t *netif;
184 struct net_device *eth0_dev;
186 netif = netif_find_by_handle(domid, handle);
187 if ( unlikely(netif == NULL) )
188 {
189 DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n",
190 connect->domid, connect->netif_handle);
191 connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
192 return;
193 }
195 if ( netif->status != DISCONNECTED )
196 {
197 connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
198 return;
199 }
201 if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL )
202 {
203 connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
204 return;
205 }
207 prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
208 error = direct_remap_area_pages(&init_mm,
209 VMALLOC_VMADDR(vma->addr),
210 tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
211 prot, domid);
212 error |= direct_remap_area_pages(&init_mm,
213 VMALLOC_VMADDR(vma->addr) + PAGE_SIZE,
214 rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
215 prot, domid);
216 if ( error != 0 )
217 {
218 if ( error == -ENOMEM )
219 connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
220 else if ( error == -EFAULT )
221 connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
222 else
223 connect->status = NETIF_BE_STATUS_ERROR;
224 vfree(vma->addr);
225 return;
226 }
228 netif->evtchn = evtchn;
229 netif->irq = bind_evtchn_to_irq(evtchn);
230 netif->tx_shmem_frame = tx_shmem_frame;
231 netif->rx_shmem_frame = rx_shmem_frame;
232 netif->tx =
233 (netif_tx_interface_t *)vma->addr;
234 netif->rx =
235 (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
236 netif->status = CONNECTED;
237 netif_get(netif);
239 rtnl_lock();
241 (void)dev_open(netif->dev);
242 (void)br_add_if(bridge_br, netif->dev);
244 /*
245 * The default config is a very simple binding to eth0.
246 * If eth0 is being used as an IP interface by this OS then someone
247 * must add eth0's IP address to nbe-br, and change the routing table
248 * to refer to nbe-br instead of eth0.
249 */
250 (void)dev_open(bridge_dev);
251 if ( (eth0_dev = __dev_get_by_name("eth0")) != NULL )
252 {
253 (void)dev_open(eth0_dev);
254 (void)br_add_if(bridge_br, eth0_dev);
255 }
257 rtnl_unlock();
259 (void)request_irq(netif->irq, netif_be_int, 0, netif->dev->name, netif);
260 netif_start_queue(netif->dev);
262 connect->status = NETIF_BE_STATUS_OKAY;
263 }
265 int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
266 {
267 domid_t domid = disconnect->domid;
268 unsigned int handle = disconnect->netif_handle;
269 netif_t *netif;
271 netif = netif_find_by_handle(domid, handle);
272 if ( unlikely(netif == NULL) )
273 {
274 DPRINTK("netif_disconnect attempted for non-existent netif"
275 " (%u,%u)\n", disconnect->domid, disconnect->netif_handle);
276 disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
277 return 1; /* Caller will send response error message. */
278 }
280 if ( netif->status == CONNECTED )
281 {
282 netif->status = DISCONNECTING;
283 netif->disconnect_rspid = rsp_id;
284 wmb(); /* Let other CPUs see the status change. */
285 netif_stop_queue(netif->dev);
286 free_irq(netif->irq, NULL);
287 netif_deschedule(netif);
288 netif_put(netif);
289 }
291 return 0; /* Caller should not send response message. */
292 }
294 void netif_interface_init(void)
295 {
296 memset(netif_hash, 0, sizeof(netif_hash));
297 if ( br_add_bridge("nbe-br") != 0 )
298 BUG();
299 bridge_dev = __dev_get_by_name("nbe-br");
300 bridge_br = (struct net_bridge *)bridge_dev->priv;
301 bridge_br->bridge_hello_time = bridge_br->hello_time = 0;
302 bridge_br->bridge_forward_delay = bridge_br->forward_delay = 0;
303 bridge_br->stp_enabled = 0;
304 }