1 /* $NetBSD: if_xennet_xenbus.c,v 1.22 2007/12/03 15:34:30 ad Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Manuel Bouyer. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Manuel Bouyer. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33 /* 34 * Copyright (c) 2004 Christian Limpach. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by Christian Limpach. 48 * 4. The name of the author may not be used to endorse or promote products 49 * derived from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 53 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 54 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 55 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 60 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.22 2007/12/03 15:34:30 ad Exp $"); 65 66 #include "opt_xen.h" 67 #include "opt_nfs_boot.h" 68 #include "rnd.h" 69 #include "bpfilter.h" 70 71 #include <sys/param.h> 72 #include <sys/device.h> 73 #include <sys/conf.h> 74 #include <sys/kernel.h> 75 #include <sys/proc.h> 76 #include <sys/systm.h> 77 #include <sys/intr.h> 78 #if NRND > 0 79 #include <sys/rnd.h> 80 #endif 81 82 #include <net/if.h> 83 #include <net/if_dl.h> 84 #include <net/if_ether.h> 85 #if NBPFILTER > 0 86 #include <net/bpf.h> 87 #include <net/bpfdesc.h> 88 #endif 89 90 #if defined(NFS_BOOT_BOOTSTATIC) 91 #include <sys/fstypes.h> 92 #include <sys/mount.h> 93 #include <sys/statvfs.h> 94 #include <netinet/in.h> 95 #include <nfs/rpcv2.h> 96 #include <nfs/nfsproto.h> 97 #include <nfs/nfs.h> 98 #include <nfs/nfsmount.h> 99 #include <nfs/nfsdiskless.h> 100 #include <xen/if_xennetvar.h> 101 #endif /* defined(NFS_BOOT_BOOTSTATIC) */ 102 103 #include <xen/xennet_checksum.h> 104 105 #include <uvm/uvm.h> 106 107 #include <xen/xen3-public/io/ring.h> 108 109 #include <xen/granttables.h> 110 #include <xen/xenbus.h> 111 #include "locators.h" 112 113 #undef XENNET_DEBUG_DUMP 114 #undef XENNET_DEBUG 115 #ifdef XENNET_DEBUG 116 #define XEDB_FOLLOW 0x01 117 #define XEDB_INIT 0x02 118 #define XEDB_EVENT 0x04 119 #define XEDB_MBUF 0x08 120 #define XEDB_MEM 0x10 121 int xennet_debug = 0xff; 122 #define DPRINTF(x) if (xennet_debug) printf x; 123 #define DPRINTFN(n,x) if (xennet_debug & (n)) printf x; 124 #else 125 #define DPRINTF(x) 126 #define DPRINTFN(n,x) 127 #endif 128 129 #define GRANT_INVALID_REF -1 /* entry is free */ 130 #define GRANT_STACK_REF -2 /* entry owned by the network stack */ 131 132 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) 133 #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) 134 135 struct xennet_txreq { 136 SLIST_ENTRY(xennet_txreq) txreq_next; 137 uint16_t txreq_id; /* ID passed to backed */ 138 grant_ref_t txreq_gntref; /* grant ref of this request */ 139 struct mbuf *txreq_m; /* mbuf being transmitted */ 140 }; 141 142 struct xennet_rxreq { 143 SLIST_ENTRY(xennet_rxreq) rxreq_next; 144 uint16_t rxreq_id; /* ID passed to backed */ 145 grant_ref_t rxreq_gntref; /* grant ref of this request */ 146 /* va/pa for this receive buf. ma will be provided by backend */ 147 paddr_t rxreq_pa; 148 vaddr_t rxreq_va; 149 struct xennet_xenbus_softc *rxreq_sc; /* pointer to our interface */ 150 }; 151 152 struct xennet_xenbus_softc { 153 struct device sc_dev; 154 struct ethercom sc_ethercom; 155 uint8_t sc_enaddr[6]; 156 struct xenbus_device *sc_xbusd; 157 158 netif_tx_front_ring_t sc_tx_ring; 159 netif_rx_front_ring_t sc_rx_ring; 160 161 unsigned int sc_evtchn; 162 void *sc_softintr; 163 164 grant_ref_t sc_tx_ring_gntref; 165 grant_ref_t sc_rx_ring_gntref; 166 167 struct xennet_txreq sc_txreqs[NET_TX_RING_SIZE]; 168 struct xennet_rxreq sc_rxreqs[NET_RX_RING_SIZE]; 169 SLIST_HEAD(,xennet_txreq) sc_txreq_head; /* list of free TX requests */ 170 SLIST_HEAD(,xennet_rxreq) sc_rxreq_head; /* list of free RX requests */ 171 int sc_free_rxreql; /* number of free receive request struct */ 172 173 int sc_backend_status; /* our status with backend */ 174 #define BEST_CLOSED 0 175 #define BEST_DISCONNECTED 1 176 #define BEST_CONNECTED 2 177 #if NRND > 0 178 rndsource_element_t sc_rnd_source; 179 #endif 180 }; 181 #define SC_NLIVEREQ(sc) ((sc)->sc_rx_ring.req_prod_pvt - \ 182 (sc)->sc_rx_ring.sring->rsp_prod) 183 184 /* too big to be on stack */ 185 static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1]; 186 static paddr_t xennet_pages[NET_RX_RING_SIZE]; 187 188 static int xennet_xenbus_match(struct device *, struct cfdata *, void *); 189 static void xennet_xenbus_attach(struct device *, struct device *, void *); 190 static int xennet_xenbus_detach(struct device *, int); 191 static void xennet_backend_changed(void *, XenbusState); 192 193 static int xennet_xenbus_resume(void *); 194 static void xennet_alloc_rx_buffer(struct xennet_xenbus_softc *); 195 static void xennet_free_rx_buffer(struct xennet_xenbus_softc *); 196 static void xennet_tx_complete(struct xennet_xenbus_softc *); 197 static void xennet_rx_mbuf_free(struct mbuf *, void *, size_t, void *); 198 static int xennet_handler(void *); 199 #ifdef XENNET_DEBUG_DUMP 200 static void xennet_hex_dump(const unsigned char *, size_t, const char *, int); 201 #endif 202 203 static int xennet_init(struct ifnet *); 204 static void xennet_stop(struct ifnet *, int); 205 static void xennet_reset(struct xennet_xenbus_softc *); 206 static void xennet_softstart(void *); 207 static void xennet_start(struct ifnet *); 208 static int xennet_ioctl(struct ifnet *, u_long, void *); 209 static void xennet_watchdog(struct ifnet *); 210 211 CFATTACH_DECL(xennet_xenbus, sizeof(struct xennet_xenbus_softc), 212 xennet_xenbus_match, xennet_xenbus_attach, xennet_xenbus_detach, NULL); 213 214 static int 215 xennet_xenbus_match(struct device *parent, struct cfdata *match, void *aux) 216 { 217 struct xenbusdev_attach_args *xa = aux; 218 219 if (strcmp(xa->xa_type, "vif") != 0) 220 return 0; 221 222 if (match->cf_loc[XENBUSCF_ID] != XENBUSCF_ID_DEFAULT && 223 match->cf_loc[XENBUSCF_ID] != xa->xa_id) 224 return 0; 225 226 return 1; 227 } 228 229 static void 230 xennet_xenbus_attach(struct device *parent, struct device *self, void *aux) 231 { 232 struct xennet_xenbus_softc *sc = (void *)self; 233 struct xenbusdev_attach_args *xa = aux; 234 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 235 int err; 236 RING_IDX i; 237 char *val, *e, *p; 238 int s; 239 extern int ifqmaxlen; /* XXX */ 240 #ifdef XENNET_DEBUG 241 char **dir; 242 int dir_n = 0; 243 char id_str[20]; 244 #endif 245 246 aprint_normal(": Xen Virtual Network Interface\n"); 247 #ifdef XENNET_DEBUG 248 printf("path: %s\n", xa->xa_xbusd->xbusd_path); 249 snprintf(id_str, sizeof(id_str), "%d", xa->xa_id); 250 err = xenbus_directory(NULL, "device/vif", id_str, &dir_n, &dir); 251 if (err) { 252 printf("%s: xenbus_directory err %d\n", 253 sc->sc_dev.dv_xname, err); 254 } else { 255 printf("%s/\n", xa->xa_xbusd->xbusd_path); 256 for (i = 0; i < dir_n; i++) { 257 printf("\t/%s", dir[i]); 258 err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, dir[i], 259 NULL, &val); 260 if (err) { 261 printf("%s: xenbus_read err %d\n", 262 sc->sc_dev.dv_xname, err); 263 } else { 264 printf(" = %s\n", val); 265 free(val, M_DEVBUF); 266 } 267 } 268 } 269 #endif /* XENNET_DEBUG */ 270 sc->sc_xbusd = xa->xa_xbusd; 271 sc->sc_xbusd->xbusd_otherend_changed = xennet_backend_changed; 272 273 /* initialize free RX and RX request lists */ 274 SLIST_INIT(&sc->sc_txreq_head); 275 for (i = 0; i < NET_TX_RING_SIZE; i++) { 276 sc->sc_txreqs[i].txreq_id = i; 277 SLIST_INSERT_HEAD(&sc->sc_txreq_head, &sc->sc_txreqs[i], 278 txreq_next); 279 } 280 SLIST_INIT(&sc->sc_rxreq_head); 281 s = splvm(); 282 for (i = 0; i < NET_RX_RING_SIZE; i++) { 283 struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; 284 rxreq->rxreq_id = i; 285 rxreq->rxreq_sc = sc; 286 rxreq->rxreq_va = uvm_km_alloc(kernel_map, 287 PAGE_SIZE, PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_ZERO); 288 if (rxreq->rxreq_va == 0) 289 break; 290 if (!pmap_extract(pmap_kernel(), rxreq->rxreq_va, 291 &rxreq->rxreq_pa)) 292 panic("xennet: no pa for mapped va ?"); 293 rxreq->rxreq_gntref = GRANT_INVALID_REF; 294 SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, rxreq_next); 295 } 296 splx(s); 297 sc->sc_free_rxreql = i; 298 if (sc->sc_free_rxreql == 0) { 299 aprint_error("%s: failed to allocate rx memory\n", 300 sc->sc_dev.dv_xname); 301 return; 302 } 303 304 /* read mac address */ 305 err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, "mac", NULL, &val); 306 if (err) { 307 aprint_error("%s: can't read mac address, err %d\n", 308 sc->sc_dev.dv_xname, err); 309 return; 310 } 311 /* read mac address */ 312 for (i = 0, p = val; i < 6; i++) { 313 sc->sc_enaddr[i] = strtoul(p, &e, 16); 314 if ((e[0] == '\0' && i != 5) && e[0] != ':') { 315 aprint_error("%s: %s is not a valid mac address\n", 316 sc->sc_dev.dv_xname, val); 317 free(val, M_DEVBUF); 318 return; 319 } 320 p = &e[1]; 321 } 322 free(val, M_DEVBUF); 323 aprint_normal("%s: MAC address %s\n", sc->sc_dev.dv_xname, 324 ether_sprintf(sc->sc_enaddr)); 325 /* Initialize ifnet structure and attach interface */ 326 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 327 ifp->if_softc = sc; 328 ifp->if_start = xennet_start; 329 ifp->if_ioctl = xennet_ioctl; 330 ifp->if_watchdog = xennet_watchdog; 331 ifp->if_init = xennet_init; 332 ifp->if_stop = xennet_stop; 333 ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; 334 ifp->if_timer = 0; 335 ifp->if_snd.ifq_maxlen = max(ifqmaxlen, NET_TX_RING_SIZE * 2); 336 ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; 337 IFQ_SET_READY(&ifp->if_snd); 338 if_attach(ifp); 339 ether_ifattach(ifp, sc->sc_enaddr); 340 sc->sc_softintr = softint_establish(SOFTINT_NET, xennet_softstart, sc); 341 if (sc->sc_softintr == NULL) 342 panic(" xennet: can't establish soft interrupt"); 343 344 /* initialise shared structures and tell backend that we are ready */ 345 xennet_xenbus_resume(sc); 346 } 347 348 static int 349 xennet_xenbus_detach(struct device *self, int flags) 350 { 351 struct xennet_xenbus_softc *sc = (void *)self; 352 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 353 int s0, s1; 354 RING_IDX i; 355 356 DPRINTF(("%s: xennet_xenbus_detach\n", sc->sc_dev.dv_xname)); 357 s0 = splnet(); 358 xennet_stop(ifp, 1); 359 /* wait for pending TX to complete, and collect pending RX packets */ 360 xennet_handler(sc); 361 while (sc->sc_tx_ring.sring->rsp_prod != sc->sc_tx_ring.rsp_cons) { 362 tsleep(xennet_xenbus_detach, PRIBIO, "xnet_detach", hz/2); 363 xennet_handler(sc); 364 } 365 xennet_free_rx_buffer(sc); 366 367 s1 = splvm(); 368 for (i = 0; i < NET_RX_RING_SIZE; i++) { 369 struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; 370 uvm_km_free(kernel_map, rxreq->rxreq_va, PAGE_SIZE, 371 UVM_KMF_WIRED); 372 } 373 splx(s1); 374 375 ether_ifdetach(ifp); 376 if_detach(ifp); 377 while (xengnt_status(sc->sc_tx_ring_gntref)) { 378 tsleep(xennet_xenbus_detach, PRIBIO, "xnet_txref", hz/2); 379 } 380 xengnt_revoke_access(sc->sc_tx_ring_gntref); 381 uvm_km_free(kernel_map, (vaddr_t)sc->sc_tx_ring.sring, PAGE_SIZE, 382 UVM_KMF_WIRED); 383 while (xengnt_status(sc->sc_rx_ring_gntref)) { 384 tsleep(xennet_xenbus_detach, PRIBIO, "xnet_rxref", hz/2); 385 } 386 xengnt_revoke_access(sc->sc_rx_ring_gntref); 387 uvm_km_free(kernel_map, (vaddr_t)sc->sc_rx_ring.sring, PAGE_SIZE, 388 UVM_KMF_WIRED); 389 softint_disestablish(sc->sc_softintr); 390 event_remove_handler(sc->sc_evtchn, &xennet_handler, sc); 391 splx(s0); 392 DPRINTF(("%s: xennet_xenbus_detach done\n", sc->sc_dev.dv_xname)); 393 return 0; 394 } 395 396 static int 397 xennet_xenbus_resume(void *p) 398 { 399 struct xennet_xenbus_softc *sc = p; 400 struct xenbus_transaction *xbt; 401 int error; 402 netif_tx_sring_t *tx_ring; 403 netif_rx_sring_t *rx_ring; 404 paddr_t ma; 405 const char *errmsg; 406 407 sc->sc_tx_ring_gntref = GRANT_INVALID_REF; 408 sc->sc_rx_ring_gntref = GRANT_INVALID_REF; 409 410 411 /* setup device: alloc event channel and shared rings */ 412 tx_ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 413 UVM_KMF_WIRED | UVM_KMF_ZERO); 414 rx_ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 415 UVM_KMF_WIRED | UVM_KMF_ZERO); 416 if (tx_ring == NULL || rx_ring == NULL) 417 panic("xennet_xenbus_resume: can't alloc rings"); 418 419 SHARED_RING_INIT(tx_ring); 420 FRONT_RING_INIT(&sc->sc_tx_ring, tx_ring, PAGE_SIZE); 421 SHARED_RING_INIT(rx_ring); 422 FRONT_RING_INIT(&sc->sc_rx_ring, rx_ring, PAGE_SIZE); 423 424 (void)pmap_extract_ma(pmap_kernel(), (vaddr_t)tx_ring, &ma); 425 error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_tx_ring_gntref); 426 if (error) 427 return error; 428 (void)pmap_extract_ma(pmap_kernel(), (vaddr_t)rx_ring, &ma); 429 error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_rx_ring_gntref); 430 if (error) 431 return error; 432 error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn); 433 if (error) 434 return error; 435 aprint_verbose("%s: using event channel %d\n", 436 sc->sc_dev.dv_xname, sc->sc_evtchn); 437 event_set_handler(sc->sc_evtchn, &xennet_handler, sc, 438 IPL_NET, sc->sc_dev.dv_xname); 439 440 again: 441 xbt = xenbus_transaction_start(); 442 if (xbt == NULL) 443 return ENOMEM; 444 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 445 "tx-ring-ref","%u", sc->sc_tx_ring_gntref); 446 if (error) { 447 errmsg = "writing tx ring-ref"; 448 goto abort_transaction; 449 } 450 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 451 "rx-ring-ref","%u", sc->sc_rx_ring_gntref); 452 if (error) { 453 errmsg = "writing rx ring-ref"; 454 goto abort_transaction; 455 } 456 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 457 "event-channel", "%u", sc->sc_evtchn); 458 if (error) { 459 errmsg = "writing event channel"; 460 goto abort_transaction; 461 } 462 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 463 "state", "%d", XenbusStateConnected); 464 if (error) { 465 errmsg = "writing frontend XenbusStateConnected"; 466 goto abort_transaction; 467 } 468 error = xenbus_transaction_end(xbt, 0); 469 if (error == EAGAIN) 470 goto again; 471 if (error) { 472 xenbus_dev_fatal(sc->sc_xbusd, error, "completing transaction"); 473 return -1; 474 } 475 xennet_alloc_rx_buffer(sc); 476 sc->sc_backend_status = BEST_CONNECTED; 477 return 0; 478 479 abort_transaction: 480 xenbus_transaction_end(xbt, 1); 481 xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg); 482 return error; 483 } 484 485 static void xennet_backend_changed(void *arg, XenbusState new_state) 486 { 487 struct xennet_xenbus_softc *sc = arg; 488 DPRINTF(("%s: new backend state %d\n", sc->sc_dev.dv_xname, new_state)); 489 490 switch (new_state) { 491 case XenbusStateInitialising: 492 case XenbusStateInitWait: 493 case XenbusStateInitialised: 494 break; 495 case XenbusStateClosing: 496 sc->sc_backend_status = BEST_CLOSED; 497 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed); 498 break; 499 case XenbusStateConnected: 500 break; 501 case XenbusStateUnknown: 502 default: 503 panic("bad backend state %d", new_state); 504 } 505 } 506 507 static void 508 xennet_alloc_rx_buffer(struct xennet_xenbus_softc *sc) 509 { 510 RING_IDX req_prod = sc->sc_rx_ring.req_prod_pvt; 511 RING_IDX i; 512 struct xennet_rxreq *req; 513 struct xen_memory_reservation reservation; 514 int s1, s2; 515 paddr_t pfn; 516 517 s1 = splnet(); 518 for (i = 0; sc->sc_free_rxreql != 0; i++) { 519 req = SLIST_FIRST(&sc->sc_rxreq_head); 520 KASSERT(req != NULL); 521 KASSERT(req == &sc->sc_rxreqs[req->rxreq_id]); 522 RING_GET_REQUEST(&sc->sc_rx_ring, req_prod + i)->id = 523 req->rxreq_id; 524 if (xengnt_grant_transfer(sc->sc_xbusd->xbusd_otherend_id, 525 &req->rxreq_gntref) != 0) { 526 break; 527 } 528 RING_GET_REQUEST(&sc->sc_rx_ring, req_prod + i)->gref = 529 req->rxreq_gntref; 530 531 SLIST_REMOVE_HEAD(&sc->sc_rxreq_head, rxreq_next); 532 sc->sc_free_rxreql--; 533 534 /* unmap the page */ 535 MULTI_update_va_mapping(&rx_mcl[i], req->rxreq_va, 0, 0); 536 /* 537 * Remove this page from pseudo phys map before 538 * passing back to Xen. 539 */ 540 pfn = (req->rxreq_pa - XPMAP_OFFSET) >> PAGE_SHIFT; 541 xennet_pages[i] = xpmap_phys_to_machine_mapping[pfn]; 542 xpmap_phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; 543 } 544 if (i == 0) { 545 splx(s1); 546 return; 547 } 548 /* also make sure to flush all TLB entries */ 549 rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; 550 /* 551 * We may have allocated buffers which have entries 552 * outstanding in the page update queue -- make sure we flush 553 * those first! 554 */ 555 s2 = splvm(); 556 xpq_flush_queue(); 557 splx(s2); 558 /* now decrease reservation */ 559 reservation.extent_start = xennet_pages; 560 reservation.nr_extents = i; 561 reservation.extent_order = 0; 562 reservation.address_bits = 0; 563 reservation.domid = DOMID_SELF; 564 rx_mcl[i].op = __HYPERVISOR_memory_op; 565 rx_mcl[i].args[0] = XENMEM_decrease_reservation; 566 rx_mcl[i].args[1] = (unsigned long)&reservation; 567 HYPERVISOR_multicall(rx_mcl, i+1); 568 if (__predict_false(rx_mcl[i].result != i)) { 569 panic("xennet_alloc_rx_buffer: XENMEM_decrease_reservation"); 570 } 571 sc->sc_rx_ring.req_prod_pvt = req_prod + i; 572 RING_PUSH_REQUESTS(&sc->sc_rx_ring); 573 574 splx(s1); 575 return; 576 } 577 578 static void 579 xennet_free_rx_buffer(struct xennet_xenbus_softc *sc) 580 { 581 paddr_t ma, pa; 582 vaddr_t va; 583 RING_IDX i; 584 mmu_update_t mmu[1]; 585 multicall_entry_t mcl[2]; 586 587 int s = splbio(); 588 589 DPRINTF(("%s: xennet_free_rx_buffer\n", sc->sc_dev.dv_xname)); 590 /* get back memory from RX ring */ 591 for (i = 0; i < NET_RX_RING_SIZE; i++) { 592 struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; 593 594 /* 595 * if the buffer is in transit in the network stack, wait for 596 * the network stack to free it. 597 */ 598 while ((volatile grant_ref_t)rxreq->rxreq_gntref == 599 GRANT_STACK_REF) 600 tsleep(xennet_xenbus_detach, PRIBIO, "xnet_free", hz/2); 601 602 if (rxreq->rxreq_gntref != GRANT_INVALID_REF) { 603 /* 604 * this req is still granted. Get back the page or 605 * allocate a new one, and remap it. 606 */ 607 SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, 608 rxreq_next); 609 sc->sc_free_rxreql++; 610 ma = xengnt_revoke_transfer(rxreq->rxreq_gntref); 611 rxreq->rxreq_gntref = GRANT_INVALID_REF; 612 if (ma == 0) { 613 struct xen_memory_reservation xenres; 614 /* 615 * transfer not complete, we lost the page. 616 * Get one from hypervisor 617 */ 618 xenres.extent_start = &ma; 619 xenres.nr_extents = 1; 620 xenres.extent_order = 0; 621 xenres.address_bits = 31; 622 xenres.domid = DOMID_SELF; 623 if (HYPERVISOR_memory_op( 624 XENMEM_increase_reservation, &xenres) < 0) { 625 panic("xennet_free_rx_buffer: " 626 "can't get memory back"); 627 } 628 KASSERT(ma != 0); 629 } 630 pa = rxreq->rxreq_pa; 631 va = rxreq->rxreq_va; 632 /* remap the page */ 633 mmu[0].ptr = (ma << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; 634 mmu[0].val = ((pa - XPMAP_OFFSET) >> PAGE_SHIFT); 635 MULTI_update_va_mapping(&mcl[0], va, 636 (ma << PAGE_SHIFT) | PG_V | PG_KW, 637 UVMF_TLB_FLUSH|UVMF_ALL); 638 xpmap_phys_to_machine_mapping[ 639 (pa - XPMAP_OFFSET) >> PAGE_SHIFT] = ma; 640 mcl[1].op = __HYPERVISOR_mmu_update; 641 mcl[1].args[0] = (unsigned long)mmu; 642 mcl[1].args[1] = 1; 643 mcl[1].args[2] = 0; 644 mcl[1].args[3] = DOMID_SELF; 645 HYPERVISOR_multicall(mcl, 2); 646 } 647 648 } 649 splx(s); 650 DPRINTF(("%s: xennet_free_rx_buffer done\n", sc->sc_dev.dv_xname)); 651 } 652 653 static void 654 xennet_rx_mbuf_free(struct mbuf *m, void *buf, size_t size, void *arg) 655 { 656 struct xennet_rxreq *req = arg; 657 struct xennet_xenbus_softc *sc = req->rxreq_sc; 658 659 int s = splnet(); 660 661 SLIST_INSERT_HEAD(&sc->sc_rxreq_head, req, rxreq_next); 662 sc->sc_free_rxreql++; 663 664 req->rxreq_gntref = GRANT_INVALID_REF; 665 if (sc->sc_free_rxreql >= SC_NLIVEREQ(sc) && 666 __predict_true(sc->sc_backend_status == BEST_CONNECTED)) { 667 xennet_alloc_rx_buffer(sc); 668 } 669 670 if (m) 671 pool_cache_put(mb_cache, m); 672 splx(s); 673 } 674 675 676 static void 677 xennet_tx_complete(struct xennet_xenbus_softc *sc) 678 { 679 struct xennet_txreq *req; 680 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 681 RING_IDX resp_prod, i; 682 683 DPRINTFN(XEDB_EVENT, ("xennet_tx_complete prod %d cons %d\n", 684 sc->sc_tx_ring.sring->rsp_prod, sc->sc_tx_ring.rsp_cons)); 685 686 again: 687 resp_prod = sc->sc_tx_ring.sring->rsp_prod; 688 x86_lfence(); 689 for (i = sc->sc_tx_ring.rsp_cons; i != resp_prod; i++) { 690 req = &sc->sc_txreqs[RING_GET_RESPONSE(&sc->sc_tx_ring, i)->id]; 691 KASSERT(req->txreq_id == 692 RING_GET_RESPONSE(&sc->sc_tx_ring, i)->id); 693 if (__predict_false(xengnt_status(req->txreq_gntref))) { 694 printf("%s: grant still used by backend\n", 695 sc->sc_dev.dv_xname); 696 sc->sc_tx_ring.rsp_cons = i; 697 goto end; 698 } 699 if (__predict_false( 700 RING_GET_RESPONSE(&sc->sc_tx_ring, i)->status != 701 NETIF_RSP_OKAY)) 702 ifp->if_oerrors++; 703 else 704 ifp->if_opackets++; 705 xengnt_revoke_access(req->txreq_gntref); 706 m_freem(req->txreq_m); 707 SLIST_INSERT_HEAD(&sc->sc_txreq_head, req, txreq_next); 708 } 709 sc->sc_tx_ring.rsp_cons = resp_prod; 710 /* set new event and check fopr race with rsp_cons update */ 711 sc->sc_tx_ring.sring->rsp_event = 712 resp_prod + ((sc->sc_tx_ring.sring->req_prod - resp_prod) >> 1) + 1; 713 ifp->if_timer = 0; 714 x86_sfence(); 715 if (resp_prod != sc->sc_tx_ring.sring->rsp_prod) 716 goto again; 717 end: 718 if (ifp->if_flags & IFF_OACTIVE) { 719 ifp->if_flags &= ~IFF_OACTIVE; 720 xennet_softstart(sc); 721 } 722 } 723 724 static int 725 xennet_handler(void *arg) 726 { 727 struct xennet_xenbus_softc *sc = arg; 728 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 729 RING_IDX resp_prod, i; 730 struct xennet_rxreq *req; 731 paddr_t ma, pa; 732 vaddr_t va; 733 mmu_update_t mmu[1]; 734 multicall_entry_t mcl[2]; 735 struct mbuf *m; 736 void *pktp; 737 int more_to_do; 738 739 if (sc->sc_backend_status != BEST_CONNECTED) 740 return 1; 741 742 xennet_tx_complete(sc); 743 744 again: 745 DPRINTFN(XEDB_EVENT, ("xennet_handler prod %d cons %d\n", 746 sc->sc_rx_ring.sring->rsp_prod, sc->sc_rx_ring.rsp_cons)); 747 748 resp_prod = sc->sc_rx_ring.sring->rsp_prod; 749 x86_lfence(); /* ensure we see replies up to resp_prod */ 750 for (i = sc->sc_rx_ring.rsp_cons; i != resp_prod; i++) { 751 netif_rx_response_t *rx = RING_GET_RESPONSE(&sc->sc_rx_ring, i); 752 req = &sc->sc_rxreqs[rx->id]; 753 KASSERT(req->rxreq_gntref != GRANT_INVALID_REF); 754 KASSERT(req->rxreq_id == rx->id); 755 ma = xengnt_revoke_transfer(req->rxreq_gntref); 756 if (ma == 0) { 757 DPRINTFN(XEDB_EVENT, ("xennet_handler ma == 0\n")); 758 /* 759 * the remote could't send us a packet. 760 * we can't free this rxreq as no page will be mapped 761 * here. Instead give it back immediatly to backend. 762 */ 763 ifp->if_ierrors++; 764 RING_GET_REQUEST(&sc->sc_rx_ring, 765 sc->sc_rx_ring.req_prod_pvt)->id = req->rxreq_id; 766 RING_GET_REQUEST(&sc->sc_rx_ring, 767 sc->sc_rx_ring.req_prod_pvt)->gref = 768 req->rxreq_gntref; 769 sc->sc_rx_ring.req_prod_pvt++; 770 RING_PUSH_REQUESTS(&sc->sc_rx_ring); 771 continue; 772 } 773 req->rxreq_gntref = GRANT_INVALID_REF; 774 775 pa = req->rxreq_pa; 776 va = req->rxreq_va; 777 /* remap the page */ 778 mmu[0].ptr = (ma << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; 779 mmu[0].val = ((pa - XPMAP_OFFSET) >> PAGE_SHIFT); 780 MULTI_update_va_mapping(&mcl[0], va, 781 (ma << PAGE_SHIFT) | PG_V | PG_KW, UVMF_TLB_FLUSH|UVMF_ALL); 782 xpmap_phys_to_machine_mapping[ 783 (pa - XPMAP_OFFSET) >> PAGE_SHIFT] = ma; 784 mcl[1].op = __HYPERVISOR_mmu_update; 785 mcl[1].args[0] = (unsigned long)mmu; 786 mcl[1].args[1] = 1; 787 mcl[1].args[2] = 0; 788 mcl[1].args[3] = DOMID_SELF; 789 HYPERVISOR_multicall(mcl, 2); 790 pktp = (void *)(va + rx->offset); 791 #ifdef XENNET_DEBUG_DUMP 792 xennet_hex_dump(pktp, rx->status, "r", rx->id); 793 #endif 794 if ((ifp->if_flags & IFF_PROMISC) == 0) { 795 struct ether_header *eh = pktp; 796 if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 && 797 memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, 798 ETHER_ADDR_LEN) != 0) { 799 DPRINTFN(XEDB_EVENT, 800 ("xennet_handler bad dest\n")); 801 /* packet not for us */ 802 xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, 803 req); 804 continue; 805 } 806 } 807 MGETHDR(m, M_DONTWAIT, MT_DATA); 808 if (__predict_false(m == NULL)) { 809 printf("xennet: rx no mbuf\n"); 810 ifp->if_ierrors++; 811 xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req); 812 continue; 813 } 814 MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 815 816 m->m_pkthdr.rcvif = ifp; 817 if (__predict_true(sc->sc_rx_ring.req_prod_pvt != 818 sc->sc_rx_ring.sring->rsp_prod)) { 819 m->m_len = m->m_pkthdr.len = rx->status; 820 MEXTADD(m, pktp, rx->status, 821 M_DEVBUF, xennet_rx_mbuf_free, req); 822 m->m_flags |= M_EXT_RW; /* we own the buffer */ 823 req->rxreq_gntref = GRANT_STACK_REF; 824 } else { 825 /* 826 * This was our last receive buffer, allocate 827 * memory, copy data and push the receive 828 * buffer back to the hypervisor. 829 */ 830 m->m_len = min(MHLEN, rx->status); 831 m->m_pkthdr.len = 0; 832 m_copyback(m, 0, rx->status, pktp); 833 xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req); 834 if (m->m_pkthdr.len < rx->status) { 835 /* out of memory, just drop packets */ 836 ifp->if_ierrors++; 837 m_freem(m); 838 continue; 839 } 840 } 841 if ((rx->flags & NETRXF_csum_blank) != 0) { 842 xennet_checksum_fill(&m); 843 if (m == NULL) { 844 ifp->if_ierrors++; 845 continue; 846 } 847 } 848 #if NBPFILTER > 0 849 /* 850 * Pass packet to bpf if there is a listener. 851 */ 852 if (ifp->if_bpf) 853 bpf_mtap(ifp->if_bpf, m); 854 #endif 855 856 ifp->if_ipackets++; 857 858 /* Pass the packet up. */ 859 (*ifp->if_input)(ifp, m); 860 } 861 x86_lfence(); 862 sc->sc_rx_ring.rsp_cons = i; 863 RING_FINAL_CHECK_FOR_RESPONSES(&sc->sc_rx_ring, more_to_do); 864 if (more_to_do) 865 goto again; 866 return 1; 867 } 868 869 /* 870 * Called at splnet. 871 */ 872 void 873 xennet_start(struct ifnet *ifp) 874 { 875 struct xennet_xenbus_softc *sc = ifp->if_softc; 876 877 DPRINTFN(XEDB_FOLLOW, ("%s: xennet_start()\n", sc->sc_dev.dv_xname)); 878 879 #if NRND > 0 880 rnd_add_uint32(&sc->sc_rnd_source, sc->sc_tx_ring.req_prod_pvt); 881 #endif 882 883 xennet_tx_complete(sc); 884 885 if (__predict_false( 886 (ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)) 887 return; 888 889 /* 890 * The Xen communication channel is much more efficient if we can 891 * schedule batch of packets for domain0. To achieve this, we 892 * schedule a soft interrupt, and just return. This way, the network 893 * stack will enqueue all pending mbufs in the interface's send queue 894 * before it is processed by xennet_softstart(). 895 */ 896 softint_schedule(sc->sc_softintr); 897 return; 898 } 899 900 /* 901 * called at splsoftnet 902 */ 903 void 904 xennet_softstart(void *arg) 905 { 906 struct xennet_xenbus_softc *sc = arg; 907 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 908 struct mbuf *m, *new_m; 909 netif_tx_request_t *txreq; 910 RING_IDX req_prod; 911 paddr_t pa, pa2; 912 struct xennet_txreq *req; 913 int notify; 914 int do_notify = 0; 915 int s; 916 917 s = splnet(); 918 if (__predict_false( 919 (ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)) { 920 splx(s); 921 return; 922 } 923 924 req_prod = sc->sc_tx_ring.req_prod_pvt; 925 while (/*CONSTCOND*/1) { 926 uint16_t txflags; 927 928 req = SLIST_FIRST(&sc->sc_txreq_head); 929 if (__predict_false(req == NULL)) { 930 ifp->if_flags |= IFF_OACTIVE; 931 break; 932 } 933 IFQ_POLL(&ifp->if_snd, m); 934 if (m == NULL) 935 break; 936 937 switch (m->m_flags & (M_EXT|M_EXT_CLUSTER)) { 938 case M_EXT|M_EXT_CLUSTER: 939 KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID); 940 pa = m->m_ext.ext_paddr + 941 (m->m_data - m->m_ext.ext_buf); 942 break; 943 case 0: 944 KASSERT(m->m_paddr != M_PADDR_INVALID); 945 pa = m->m_paddr + M_BUFOFFSET(m) + 946 (m->m_data - M_BUFADDR(m)); 947 break; 948 default: 949 if (__predict_false( 950 !pmap_extract(pmap_kernel(), (vaddr_t)m->m_data, 951 &pa))) { 952 panic("xennet_start: no pa"); 953 } 954 break; 955 } 956 957 if ((m->m_pkthdr.csum_flags & 958 (M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) { 959 txflags = NETTXF_csum_blank; 960 } else { 961 txflags = 0; 962 } 963 964 if (m->m_pkthdr.len != m->m_len || 965 (pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) { 966 967 MGETHDR(new_m, M_DONTWAIT, MT_DATA); 968 if (__predict_false(new_m == NULL)) { 969 printf("xennet: no mbuf\n"); 970 break; 971 } 972 if (m->m_pkthdr.len > MHLEN) { 973 MCLGET(new_m, M_DONTWAIT); 974 if (__predict_false( 975 (new_m->m_flags & M_EXT) == 0)) { 976 DPRINTF(("xennet: no mbuf cluster\n")); 977 m_freem(new_m); 978 break; 979 } 980 } 981 982 m_copydata(m, 0, m->m_pkthdr.len, mtod(new_m, void *)); 983 new_m->m_len = new_m->m_pkthdr.len = m->m_pkthdr.len; 984 985 if ((new_m->m_flags & M_EXT) != 0) { 986 pa = new_m->m_ext.ext_paddr; 987 KASSERT(new_m->m_data == new_m->m_ext.ext_buf); 988 KASSERT(pa != M_PADDR_INVALID); 989 } else { 990 pa = new_m->m_paddr; 991 KASSERT(pa != M_PADDR_INVALID); 992 KASSERT(new_m->m_data == M_BUFADDR(new_m)); 993 pa += M_BUFOFFSET(new_m); 994 } 995 if (__predict_false(xengnt_grant_access( 996 sc->sc_xbusd->xbusd_otherend_id, 997 xpmap_ptom_masked(pa), 998 GNTMAP_readonly, &req->txreq_gntref) != 0)) { 999 m_freem(new_m); 1000 ifp->if_flags |= IFF_OACTIVE; 1001 break; 1002 } 1003 /* we will be able to send new_m */ 1004 IFQ_DEQUEUE(&ifp->if_snd, m); 1005 m_freem(m); 1006 m = new_m; 1007 } else { 1008 if (__predict_false(xengnt_grant_access( 1009 sc->sc_xbusd->xbusd_otherend_id, 1010 xpmap_ptom_masked(pa), 1011 GNTMAP_readonly, &req->txreq_gntref) != 0)) { 1012 ifp->if_flags |= IFF_OACTIVE; 1013 break; 1014 } 1015 /* we will be able to send m */ 1016 IFQ_DEQUEUE(&ifp->if_snd, m); 1017 } 1018 MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); 1019 1020 KASSERT(((pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) == 0); 1021 1022 SLIST_REMOVE_HEAD(&sc->sc_txreq_head, txreq_next); 1023 req->txreq_m = m; 1024 1025 DPRINTFN(XEDB_MBUF, ("xennet_start id %d, " 1026 "mbuf %p, buf %p/%p/%p, size %d\n", 1027 req->txreq_id, m, mtod(m, void *), (void *)pa, 1028 (void *)xpmap_ptom_masked(pa), m->m_pkthdr.len)); 1029 pmap_extract_ma(pmap_kernel(), mtod(m, vaddr_t), &pa2); 1030 DPRINTFN(XEDB_MBUF, ("xennet_start pa %p ma %p/%p\n", 1031 (void *)pa, (void *)xpmap_ptom_masked(pa), (void *)pa2)); 1032 #ifdef XENNET_DEBUG_DUMP 1033 xennet_hex_dump(mtod(m, u_char *), m->m_pkthdr.len, "s", req->txreq_id); 1034 #endif 1035 1036 txreq = RING_GET_REQUEST(&sc->sc_tx_ring, req_prod); 1037 txreq->id = req->txreq_id; 1038 txreq->gref = req->txreq_gntref; 1039 txreq->offset = pa & ~PG_FRAME; 1040 txreq->size = m->m_pkthdr.len; 1041 txreq->flags = txflags; 1042 1043 req_prod++; 1044 sc->sc_tx_ring.req_prod_pvt = req_prod; 1045 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_tx_ring, notify); 1046 if (notify) 1047 do_notify = 1; 1048 1049 #ifdef XENNET_DEBUG 1050 DPRINTFN(XEDB_MEM, ("packet addr %p/%p, physical %p/%p, " 1051 "m_paddr %p, len %d/%d\n", M_BUFADDR(m), mtod(m, void *), 1052 (void *)*kvtopte(mtod(m, vaddr_t)), 1053 (void *)xpmap_mtop(*kvtopte(mtod(m, vaddr_t))), 1054 (void *)m->m_paddr, m->m_pkthdr.len, m->m_len)); 1055 DPRINTFN(XEDB_MEM, ("id %d gref %d offset %d size %d flags %d" 1056 " prod %d\n", 1057 txreq->id, txreq->gref, txreq->offset, txreq->size, 1058 txreq->flags, req_prod)); 1059 #endif 1060 1061 #if NBPFILTER > 0 1062 /* 1063 * Pass packet to bpf if there is a listener. 1064 */ 1065 if (ifp->if_bpf) { 1066 bpf_mtap(ifp->if_bpf, m); 1067 } 1068 #endif 1069 } 1070 1071 x86_lfence(); 1072 if (do_notify) { 1073 hypervisor_notify_via_evtchn(sc->sc_evtchn); 1074 ifp->if_timer = 5; 1075 } 1076 splx(s); 1077 1078 DPRINTFN(XEDB_FOLLOW, ("%s: xennet_start() done\n", 1079 sc->sc_dev.dv_xname)); 1080 } 1081 1082 int 1083 xennet_ioctl(struct ifnet *ifp, u_long cmd, void *data) 1084 { 1085 #ifdef XENNET_DEBUG 1086 struct xennet_xenbus_softc *sc = ifp->if_softc; 1087 #endif 1088 int s, error = 0; 1089 1090 s = splnet(); 1091 1092 DPRINTFN(XEDB_FOLLOW, ("%s: xennet_ioctl()\n", sc->sc_dev.dv_xname)); 1093 error = ether_ioctl(ifp, cmd, data); 1094 if (error == ENETRESET) 1095 error = 0; 1096 splx(s); 1097 1098 DPRINTFN(XEDB_FOLLOW, ("%s: xennet_ioctl() returning %d\n", 1099 sc->sc_dev.dv_xname, error)); 1100 1101 return error; 1102 } 1103 1104 void 1105 xennet_watchdog(struct ifnet *ifp) 1106 { 1107 struct xennet_xenbus_softc *sc = ifp->if_softc; 1108 1109 printf("%s: xennet_watchdog\n", sc->sc_dev.dv_xname); 1110 } 1111 1112 int 1113 xennet_init(struct ifnet *ifp) 1114 { 1115 struct xennet_xenbus_softc *sc = ifp->if_softc; 1116 int s = splnet(); 1117 1118 DPRINTFN(XEDB_FOLLOW, ("%s: xennet_init()\n", sc->sc_dev.dv_xname)); 1119 1120 if ((ifp->if_flags & IFF_RUNNING) == 0) { 1121 sc->sc_rx_ring.sring->rsp_event = 1122 sc->sc_rx_ring.rsp_cons + 1; 1123 hypervisor_enable_event(sc->sc_evtchn); 1124 hypervisor_notify_via_evtchn(sc->sc_evtchn); 1125 xennet_reset(sc); 1126 } 1127 ifp->if_flags |= IFF_RUNNING; 1128 ifp->if_flags &= ~IFF_OACTIVE; 1129 ifp->if_timer = 0; 1130 splx(s); 1131 return 0; 1132 } 1133 1134 void 1135 xennet_stop(struct ifnet *ifp, int disable) 1136 { 1137 struct xennet_xenbus_softc *sc = ifp->if_softc; 1138 int s = splnet(); 1139 1140 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1141 hypervisor_mask_event(sc->sc_evtchn); 1142 xennet_reset(sc); 1143 splx(s); 1144 } 1145 1146 void 1147 xennet_reset(struct xennet_xenbus_softc *sc) 1148 { 1149 1150 DPRINTFN(XEDB_FOLLOW, ("%s: xennet_reset()\n", sc->sc_dev.dv_xname)); 1151 } 1152 1153 #if defined(NFS_BOOT_BOOTSTATIC) 1154 int 1155 xennet_bootstatic_callback(struct nfs_diskless *nd) 1156 { 1157 #if 0 1158 struct ifnet *ifp = nd->nd_ifp; 1159 struct xennet_xenbus_softc *sc = 1160 (struct xennet_xenbus_softc *)ifp->if_softc; 1161 #endif 1162 union xen_cmdline_parseinfo xcp; 1163 struct sockaddr_in *sin; 1164 1165 memset(&xcp, 0, sizeof(xcp.xcp_netinfo)); 1166 xcp.xcp_netinfo.xi_ifno = /* XXX sc->sc_ifno */ 0; 1167 xcp.xcp_netinfo.xi_root = nd->nd_root.ndm_host; 1168 xen_parse_cmdline(XEN_PARSE_NETINFO, &xcp); 1169 1170 nd->nd_myip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[0]); 1171 nd->nd_gwip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[2]); 1172 nd->nd_mask.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[3]); 1173 1174 sin = (struct sockaddr_in *) &nd->nd_root.ndm_saddr; 1175 memset((void *)sin, 0, sizeof(*sin)); 1176 sin->sin_len = sizeof(*sin); 1177 sin->sin_family = AF_INET; 1178 sin->sin_addr.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[1]); 1179 if (nd->nd_myip.s_addr == 0) 1180 return NFS_BOOTSTATIC_NOSTATIC; 1181 else 1182 return (NFS_BOOTSTATIC_HAS_MYIP|NFS_BOOTSTATIC_HAS_GWIP| 1183 NFS_BOOTSTATIC_HAS_MASK|NFS_BOOTSTATIC_HAS_SERVADDR| 1184 NFS_BOOTSTATIC_HAS_SERVER); 1185 } 1186 #endif /* defined(NFS_BOOT_BOOTSTATIC) */ 1187 1188 #ifdef XENNET_DEBUG_DUMP 1189 #define XCHR(x) hexdigits[(x) & 0xf] 1190 static void 1191 xennet_hex_dump(const unsigned char *pkt, size_t len, const char *type, int id) 1192 { 1193 size_t i, j; 1194 1195 printf("pkt %p len %d/%x type %s id %d\n", pkt, len, len, type, id); 1196 printf("00000000 "); 1197 for(i=0; i<len; i++) { 1198 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i])); 1199 if ((i+1) % 16 == 8) 1200 printf(" "); 1201 if ((i+1) % 16 == 0) { 1202 printf(" %c", '|'); 1203 for(j=0; j<16; j++) 1204 printf("%c", pkt[i-15+j]>=32 && 1205 pkt[i-15+j]<127?pkt[i-15+j]:'.'); 1206 printf("%c\n%c%c%c%c%c%c%c%c ", '|', 1207 XCHR((i+1)>>28), XCHR((i+1)>>24), 1208 XCHR((i+1)>>20), XCHR((i+1)>>16), 1209 XCHR((i+1)>>12), XCHR((i+1)>>8), 1210 XCHR((i+1)>>4), XCHR(i+1)); 1211 } 1212 } 1213 printf("\n"); 1214 } 1215 #undef XCHR 1216 #endif 1217