ia64/xen-unstable

annotate linux-2.6-xen-sparse/drivers/xen/netback/interface.c @ 6435:b4b3f6be5226

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