version 1.3, 2006/03/06 22:10:28 |
version 1.3.4.7, 2006/08/11 15:43:16 |
Line 66 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 66 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include "opt_xen.h" |
#include "opt_xen.h" |
#include "opt_nfs_boot.h" |
#include "opt_nfs_boot.h" |
#include "rnd.h" |
#include "rnd.h" |
|
#include "bpfilter.h" |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/device.h> |
#include <sys/device.h> |
Line 79 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 80 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_dl.h> |
#include <net/if_dl.h> |
#include <net/if_ether.h> |
#include <net/if_ether.h> |
|
#if NBPFILTER > 0 |
|
#include <net/bpf.h> |
|
#include <net/bpfdesc.h> |
|
#endif |
|
|
#if defined(NFS_BOOT_BOOTSTATIC) |
#if defined(NFS_BOOT_BOOTSTATIC) |
#include <sys/fstypes.h> |
#include <sys/fstypes.h> |
Line 93 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 98 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <machine/if_xennetvar.h> |
#include <machine/if_xennetvar.h> |
#endif /* defined(NFS_BOOT_BOOTSTATIC) */ |
#endif /* defined(NFS_BOOT_BOOTSTATIC) */ |
|
|
|
#include <machine/xennet_checksum.h> |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
|
#include <machine/xen3-public/io/ring.h> |
#include <machine/xen3-public/io/ring.h> |
Line 117 int xennet_debug = 0xff; |
|
Line 124 int xennet_debug = 0xff; |
|
#define DPRINTFN(n,x) |
#define DPRINTFN(n,x) |
#endif |
#endif |
|
|
#define GRANT_INVALID_REF -1 |
#define GRANT_INVALID_REF -1 /* entry is free */ |
|
#define GRANT_STACK_REF -2 /* entry owned by the network stack */ |
|
|
#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) |
#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) |
#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) |
#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) |
Line 175 static paddr_t xennet_pages[NET_RX_RING_ |
|
Line 183 static paddr_t xennet_pages[NET_RX_RING_ |
|
|
|
static int xennet_xenbus_match(struct device *, struct cfdata *, void *); |
static int xennet_xenbus_match(struct device *, struct cfdata *, void *); |
static void xennet_xenbus_attach(struct device *, struct device *, void *); |
static void xennet_xenbus_attach(struct device *, struct device *, void *); |
|
static int xennet_xenbus_detach(struct device *, int); |
|
static void xennet_backend_changed(void *, XenbusState); |
|
|
static int xennet_xenbus_resume(void *); |
static int xennet_xenbus_resume(void *); |
static void xennet_alloc_rx_buffer(struct xennet_xenbus_softc *); |
static void xennet_alloc_rx_buffer(struct xennet_xenbus_softc *); |
|
static void xennet_free_rx_buffer(struct xennet_xenbus_softc *); |
static void xennet_tx_complete(struct xennet_xenbus_softc *); |
static void xennet_tx_complete(struct xennet_xenbus_softc *); |
static void xennet_rx_mbuf_free(struct mbuf *, caddr_t, size_t, void *); |
static void xennet_rx_mbuf_free(struct mbuf *, caddr_t, size_t, void *); |
static int xennet_handler(void *); |
static int xennet_handler(void *); |
Line 194 static int xennet_ioctl(struct ifnet *, |
|
Line 205 static int xennet_ioctl(struct ifnet *, |
|
static void xennet_watchdog(struct ifnet *); |
static void xennet_watchdog(struct ifnet *); |
|
|
CFATTACH_DECL(xennet_xenbus, sizeof(struct xennet_xenbus_softc), |
CFATTACH_DECL(xennet_xenbus, sizeof(struct xennet_xenbus_softc), |
xennet_xenbus_match, xennet_xenbus_attach, NULL, NULL); |
xennet_xenbus_match, xennet_xenbus_attach, xennet_xenbus_detach, NULL); |
|
|
static int |
static int |
xennet_xenbus_match(struct device *parent, struct cfdata *match, void *aux) |
xennet_xenbus_match(struct device *parent, struct cfdata *match, void *aux) |
Line 222 xennet_xenbus_attach(struct device *pare |
|
Line 233 xennet_xenbus_attach(struct device *pare |
|
char *val, *e, *p; |
char *val, *e, *p; |
int s; |
int s; |
extern int ifqmaxlen; /* XXX */ |
extern int ifqmaxlen; /* XXX */ |
|
#ifdef XENNET_DEBUG |
|
char **dir; |
|
int dir_n = 0; |
|
char id_str[20]; |
|
#endif |
|
|
aprint_normal(": Xen Virtual Network Interface\n"); |
aprint_normal(": Xen Virtual Network Interface\n"); |
|
#ifdef XENNET_DEBUG |
|
printf("path: %s\n", xa->xa_xbusd->xbusd_path); |
|
snprintf(id_str, sizeof(id_str), "%d", xa->xa_id); |
|
err = xenbus_directory(NULL, "device/vif", id_str, &dir_n, &dir); |
|
if (err) { |
|
printf("%s: xenbus_directory err %d\n", |
|
sc->sc_dev.dv_xname, err); |
|
} else { |
|
printf("%s/\n", xa->xa_xbusd->xbusd_path); |
|
for (i = 0; i < dir_n; i++) { |
|
printf("\t/%s", dir[i]); |
|
err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, dir[i], |
|
NULL, &val); |
|
if (err) { |
|
printf("%s: xenbus_read err %d\n", |
|
sc->sc_dev.dv_xname, err); |
|
} else { |
|
printf(" = %s\n", val); |
|
free(val, M_DEVBUF); |
|
} |
|
} |
|
} |
|
#endif /* XENNET_DEBUG */ |
sc->sc_xbusd = xa->xa_xbusd; |
sc->sc_xbusd = xa->xa_xbusd; |
|
sc->sc_xbusd->xbusd_otherend_changed = xennet_backend_changed; |
|
|
/* initialize free RX and RX request lists */ |
/* initialize free RX and RX request lists */ |
SLIST_INIT(&sc->sc_txreq_head); |
SLIST_INIT(&sc->sc_txreq_head); |
for (i = 0; i < NET_TX_RING_SIZE; i++) { |
for (i = 0; i < NET_TX_RING_SIZE; i++) { |
Line 245 xennet_xenbus_attach(struct device *pare |
|
Line 286 xennet_xenbus_attach(struct device *pare |
|
if (!pmap_extract(pmap_kernel(), rxreq->rxreq_va, |
if (!pmap_extract(pmap_kernel(), rxreq->rxreq_va, |
&rxreq->rxreq_pa)) |
&rxreq->rxreq_pa)) |
panic("xennet: no pa for mapped va ?"); |
panic("xennet: no pa for mapped va ?"); |
|
rxreq->rxreq_gntref = GRANT_INVALID_REF; |
SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, rxreq_next); |
SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, rxreq_next); |
} |
} |
splx(s); |
splx(s); |
Line 288 xennet_xenbus_attach(struct device *pare |
|
Line 329 xennet_xenbus_attach(struct device *pare |
|
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; |
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; |
ifp->if_timer = 0; |
ifp->if_timer = 0; |
ifp->if_snd.ifq_maxlen = max(ifqmaxlen, NET_TX_RING_SIZE * 2); |
ifp->if_snd.ifq_maxlen = max(ifqmaxlen, NET_TX_RING_SIZE * 2); |
|
ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; |
IFQ_SET_READY(&ifp->if_snd); |
IFQ_SET_READY(&ifp->if_snd); |
if_attach(ifp); |
if_attach(ifp); |
ether_ifattach(ifp, sc->sc_enaddr); |
ether_ifattach(ifp, sc->sc_enaddr); |
Line 300 xennet_xenbus_attach(struct device *pare |
|
Line 342 xennet_xenbus_attach(struct device *pare |
|
} |
} |
|
|
static int |
static int |
|
xennet_xenbus_detach(struct device *self, int flags) |
|
{ |
|
struct xennet_xenbus_softc *sc = (void *)self; |
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
|
int s0, s1; |
|
RING_IDX i; |
|
|
|
DPRINTF(("%s: xennet_xenbus_detach\n", sc->sc_dev.dv_xname)); |
|
s0 = splnet(); |
|
xennet_stop(ifp, 1); |
|
/* wait for pending TX to complete, and collect pending RX packets */ |
|
xennet_handler(sc); |
|
while (sc->sc_tx_ring.sring->rsp_prod != sc->sc_tx_ring.rsp_cons) { |
|
tsleep(xennet_xenbus_detach, PRIBIO, "xnet_detach", hz/2); |
|
xennet_handler(sc); |
|
} |
|
xennet_free_rx_buffer(sc); |
|
|
|
s1 = splvm(); |
|
for (i = 0; i < NET_RX_RING_SIZE; i++) { |
|
struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; |
|
uvm_km_free(kernel_map, rxreq->rxreq_va, PAGE_SIZE, |
|
UVM_KMF_WIRED); |
|
} |
|
splx(s1); |
|
|
|
ether_ifdetach(ifp); |
|
if_detach(ifp); |
|
while (xengnt_status(sc->sc_tx_ring_gntref)) { |
|
tsleep(xennet_xenbus_detach, PRIBIO, "xnet_txref", hz/2); |
|
} |
|
xengnt_revoke_access(sc->sc_tx_ring_gntref); |
|
uvm_km_free(kernel_map, (vaddr_t)sc->sc_tx_ring.sring, PAGE_SIZE, |
|
UVM_KMF_WIRED); |
|
while (xengnt_status(sc->sc_rx_ring_gntref)) { |
|
tsleep(xennet_xenbus_detach, PRIBIO, "xnet_rxref", hz/2); |
|
} |
|
xengnt_revoke_access(sc->sc_rx_ring_gntref); |
|
uvm_km_free(kernel_map, (vaddr_t)sc->sc_rx_ring.sring, PAGE_SIZE, |
|
UVM_KMF_WIRED); |
|
softintr_disestablish(sc->sc_softintr); |
|
event_remove_handler(sc->sc_evtchn, &xennet_handler, sc); |
|
splx(s0); |
|
DPRINTF(("%s: xennet_xenbus_detach done\n", sc->sc_dev.dv_xname)); |
|
return 0; |
|
} |
|
|
|
static int |
xennet_xenbus_resume(void *p) |
xennet_xenbus_resume(void *p) |
{ |
{ |
struct xennet_xenbus_softc *sc = p; |
struct xennet_xenbus_softc *sc = p; |
|
|
xenbus_dev_fatal(sc->sc_xbusd, error, "completing transaction"); |
xenbus_dev_fatal(sc->sc_xbusd, error, "completing transaction"); |
return -1; |
return -1; |
} |
} |
|
xennet_alloc_rx_buffer(sc); |
sc->sc_backend_status = BEST_CONNECTED; |
sc->sc_backend_status = BEST_CONNECTED; |
return 0; |
return 0; |
|
|
Line 387 abort_transaction: |
|
Line 478 abort_transaction: |
|
return error; |
return error; |
} |
} |
|
|
|
static void xennet_backend_changed(void *arg, XenbusState new_state) |
|
{ |
|
struct xennet_xenbus_softc *sc = arg; |
|
DPRINTF(("%s: new backend state %d\n", sc->sc_dev.dv_xname, new_state)); |
|
|
|
switch (new_state) { |
|
case XenbusStateInitialising: |
|
case XenbusStateInitWait: |
|
case XenbusStateInitialised: |
|
break; |
|
case XenbusStateClosing: |
|
sc->sc_backend_status = BEST_CLOSED; |
|
xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed); |
|
break; |
|
case XenbusStateConnected: |
|
break; |
|
case XenbusStateUnknown: |
|
default: |
|
panic("bad backend state %d", new_state); |
|
} |
|
} |
|
|
static void |
static void |
xennet_alloc_rx_buffer(struct xennet_xenbus_softc *sc) |
xennet_alloc_rx_buffer(struct xennet_xenbus_softc *sc) |
{ |
{ |
Line 401 xennet_alloc_rx_buffer(struct xennet_xen |
|
Line 514 xennet_alloc_rx_buffer(struct xennet_xen |
|
for (i = 0; sc->sc_free_rxreql != 0; i++) { |
for (i = 0; sc->sc_free_rxreql != 0; i++) { |
req = SLIST_FIRST(&sc->sc_rxreq_head); |
req = SLIST_FIRST(&sc->sc_rxreq_head); |
KASSERT(req != NULL); |
KASSERT(req != NULL); |
|
KASSERT(req == &sc->sc_rxreqs[req->rxreq_id]); |
RING_GET_REQUEST(&sc->sc_rx_ring, req_prod + i)->id = |
RING_GET_REQUEST(&sc->sc_rx_ring, req_prod + i)->id = |
req->rxreq_id; |
req->rxreq_id; |
if (xengnt_grant_transfer(sc->sc_xbusd->xbusd_otherend_id, |
if (xengnt_grant_transfer(sc->sc_xbusd->xbusd_otherend_id, |
Line 458 xennet_alloc_rx_buffer(struct xennet_xen |
|
Line 572 xennet_alloc_rx_buffer(struct xennet_xen |
|
} |
} |
|
|
static void |
static void |
|
xennet_free_rx_buffer(struct xennet_xenbus_softc *sc) |
|
{ |
|
paddr_t ma, pa; |
|
vaddr_t va; |
|
RING_IDX i; |
|
mmu_update_t mmu[1]; |
|
multicall_entry_t mcl[2]; |
|
|
|
int s = splbio(); |
|
|
|
DPRINTF(("%s: xennet_free_rx_buffer\n", sc->sc_dev.dv_xname)); |
|
/* get back memory from RX ring */ |
|
for (i = 0; i < NET_RX_RING_SIZE; i++) { |
|
struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; |
|
|
|
/* |
|
* if the buffer is in transit in the network stack, wait for |
|
* the network stack to free it. |
|
*/ |
|
while ((volatile grant_ref_t)rxreq->rxreq_gntref == |
|
GRANT_STACK_REF) |
|
tsleep(xennet_xenbus_detach, PRIBIO, "xnet_free", hz/2); |
|
|
|
if (rxreq->rxreq_gntref != GRANT_INVALID_REF) { |
|
/* |
|
* this req is still granted. Get back the page or |
|
* allocate a new one, and remap it. |
|
*/ |
|
SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, |
|
rxreq_next); |
|
sc->sc_free_rxreql++; |
|
ma = xengnt_revoke_transfer(rxreq->rxreq_gntref); |
|
rxreq->rxreq_gntref = GRANT_INVALID_REF; |
|
if (ma == 0) { |
|
struct xen_memory_reservation xenres; |
|
/* |
|
* transfer not complete, we lost the page. |
|
* Get one from hypervisor |
|
*/ |
|
xenres.extent_start = &ma; |
|
xenres.nr_extents = 1; |
|
xenres.extent_order = 0; |
|
xenres.address_bits = 31; |
|
xenres.domid = DOMID_SELF; |
|
if (HYPERVISOR_memory_op( |
|
XENMEM_increase_reservation, &xenres) < 0) { |
|
panic("xennet_free_rx_buffer: " |
|
"can't get memory back"); |
|
} |
|
KASSERT(ma != 0); |
|
} |
|
pa = rxreq->rxreq_pa; |
|
va = rxreq->rxreq_va; |
|
/* remap the page */ |
|
mmu[0].ptr = (ma << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; |
|
mmu[0].val = ((pa - XPMAP_OFFSET) >> PAGE_SHIFT); |
|
MULTI_update_va_mapping(&mcl[0], va, |
|
(ma << PAGE_SHIFT) | PG_V | PG_KW, |
|
UVMF_TLB_FLUSH|UVMF_ALL); |
|
xpmap_phys_to_machine_mapping[ |
|
(pa - XPMAP_OFFSET) >> PAGE_SHIFT] = ma; |
|
mcl[1].op = __HYPERVISOR_mmu_update; |
|
mcl[1].args[0] = (unsigned long)mmu; |
|
mcl[1].args[1] = 1; |
|
mcl[1].args[2] = 0; |
|
mcl[1].args[3] = DOMID_SELF; |
|
HYPERVISOR_multicall(mcl, 2); |
|
} |
|
|
|
} |
|
splx(s); |
|
DPRINTF(("%s: xennet_free_rx_buffer done\n", sc->sc_dev.dv_xname)); |
|
} |
|
|
|
static void |
xennet_rx_mbuf_free(struct mbuf *m, caddr_t buf, size_t size, void *arg) |
xennet_rx_mbuf_free(struct mbuf *m, caddr_t buf, size_t size, void *arg) |
{ |
{ |
struct xennet_rxreq *req = arg; |
struct xennet_rxreq *req = arg; |
struct xennet_xenbus_softc *sc = req->rxreq_sc; |
struct xennet_xenbus_softc *sc = req->rxreq_sc; |
|
|
|
int s = splnet(); |
|
|
SLIST_INSERT_HEAD(&sc->sc_rxreq_head, req, rxreq_next); |
SLIST_INSERT_HEAD(&sc->sc_rxreq_head, req, rxreq_next); |
sc->sc_free_rxreql++; |
sc->sc_free_rxreql++; |
|
|
if (sc->sc_free_rxreql >= NET_RX_RING_SIZE / 2) |
req->rxreq_gntref = GRANT_INVALID_REF; |
|
if (sc->sc_free_rxreql >= NET_RX_RING_SIZE / 2 && |
|
__predict_true(sc->sc_backend_status == BEST_CONNECTED)) { |
xennet_alloc_rx_buffer(sc); |
xennet_alloc_rx_buffer(sc); |
|
} |
|
|
if (m) |
if (m) |
pool_cache_put(&mbpool_cache, m); |
pool_cache_put(&mbpool_cache, m); |
|
splx(s); |
} |
} |
|
|
|
|
static void |
static void |
xennet_tx_complete(struct xennet_xenbus_softc * sc) |
xennet_tx_complete(struct xennet_xenbus_softc *sc) |
{ |
{ |
struct xennet_txreq *req; |
struct xennet_txreq *req; |
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
|
|
sc->sc_tx_ring.rsp_cons = i; |
sc->sc_tx_ring.rsp_cons = i; |
goto end; |
goto end; |
} |
} |
|
if (__predict_false( |
|
RING_GET_RESPONSE(&sc->sc_tx_ring, i)->status != |
|
NETIF_RSP_OKAY)) |
|
ifp->if_oerrors++; |
|
else |
|
ifp->if_opackets++; |
xengnt_revoke_access(req->txreq_gntref); |
xengnt_revoke_access(req->txreq_gntref); |
m_freem(req->txreq_m); |
m_freem(req->txreq_m); |
SLIST_INSERT_HEAD(&sc->sc_txreq_head, req, txreq_next); |
SLIST_INSERT_HEAD(&sc->sc_txreq_head, req, txreq_next); |
|
|
netif_rx_response_t *rx = RING_GET_RESPONSE(&sc->sc_rx_ring, i); |
netif_rx_response_t *rx = RING_GET_RESPONSE(&sc->sc_rx_ring, i); |
req = &sc->sc_rxreqs[rx->id]; |
req = &sc->sc_rxreqs[rx->id]; |
KASSERT(req->rxreq_gntref != GRANT_INVALID_REF); |
KASSERT(req->rxreq_gntref != GRANT_INVALID_REF); |
|
KASSERT(req->rxreq_id == rx->id); |
ma = xengnt_revoke_transfer(req->rxreq_gntref); |
ma = xengnt_revoke_transfer(req->rxreq_gntref); |
if (ma == 0) { |
if (ma == 0) { |
|
DPRINTFN(XEDB_EVENT, ("xennet_handler ma == 0\n")); |
/* |
/* |
* the remote could't send us a packet. |
* the remote could't send us a packet. |
* we can't free this rxreq as no page will be mapped |
* we can't free this rxreq as no page will be mapped |
|
|
RING_PUSH_REQUESTS(&sc->sc_rx_ring); |
RING_PUSH_REQUESTS(&sc->sc_rx_ring); |
continue; |
continue; |
} |
} |
|
req->rxreq_gntref = GRANT_INVALID_REF; |
MGETHDR(m, M_DONTWAIT, MT_DATA); |
|
if (__predict_false(m == NULL)) { |
|
printf("xennet: rx no mbuf\n"); |
|
ifp->if_ierrors++; |
|
sc->sc_rx_ring.rsp_cons = i; |
|
return 1; |
|
} |
|
|
|
pa = req->rxreq_pa; |
pa = req->rxreq_pa; |
va = req->rxreq_va; |
va = req->rxreq_va; |
|
|
if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 && |
if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 && |
memcmp(LLADDR(ifp->if_sadl), eh->ether_dhost, |
memcmp(LLADDR(ifp->if_sadl), eh->ether_dhost, |
ETHER_ADDR_LEN) != 0) { |
ETHER_ADDR_LEN) != 0) { |
|
DPRINTFN(XEDB_EVENT, |
|
("xennet_handler bad dest\n")); |
/* packet not for us */ |
/* packet not for us */ |
xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, |
xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, |
req); |
req); |
m_freem(m); |
|
continue; |
continue; |
} |
} |
} |
} |
|
MGETHDR(m, M_DONTWAIT, MT_DATA); |
|
if (__predict_false(m == NULL)) { |
|
printf("xennet: rx no mbuf\n"); |
|
ifp->if_ierrors++; |
|
xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req); |
|
continue; |
|
} |
|
MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); |
|
|
m->m_pkthdr.rcvif = ifp; |
m->m_pkthdr.rcvif = ifp; |
if (__predict_true(sc->sc_rx_ring.req_prod_pvt != |
if (__predict_true(sc->sc_rx_ring.req_prod_pvt != |
sc->sc_rx_ring.sring->rsp_prod)) { |
sc->sc_rx_ring.sring->rsp_prod)) { |
m->m_len = m->m_pkthdr.len = rx->status; |
m->m_len = m->m_pkthdr.len = rx->status; |
MEXTADD(m, pktp, rx->status, |
MEXTADD(m, pktp, rx->status, |
M_DEVBUF, xennet_rx_mbuf_free, req); |
M_DEVBUF, xennet_rx_mbuf_free, req); |
|
m->m_flags |= M_EXT_RW; /* we own the buffer */ |
|
req->rxreq_gntref = GRANT_STACK_REF; |
} else { |
} else { |
/* |
/* |
* This was our last receive buffer, allocate |
* This was our last receive buffer, allocate |
* memory, copy data and push the receive |
* memory, copy data and push the receive |
* buffer back to the hypervisor. |
* buffer back to the hypervisor. |
*/ |
*/ |
m->m_len = MHLEN; |
m->m_len = min(MHLEN, rx->status); |
m->m_pkthdr.len = 0; |
m->m_pkthdr.len = 0; |
m_copyback(m, 0, rx->status, pktp); |
m_copyback(m, 0, rx->status, pktp); |
xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req); |
xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req); |
|
|
continue; |
continue; |
} |
} |
} |
} |
|
if ((rx->flags & NETRXF_csum_blank) != 0) { |
|
xennet_checksum_fill(&m); |
|
if (m == NULL) { |
|
ifp->if_ierrors++; |
|
continue; |
|
} |
|
} |
#if NBPFILTER > 0 |
#if NBPFILTER > 0 |
/* |
/* |
* Pass packet to bpf if there is a listener. |
* Pass packet to bpf if there is a listener. |
Line 704 xennet_softstart(void *arg) |
|
Line 919 xennet_softstart(void *arg) |
|
|
|
req_prod = sc->sc_tx_ring.req_prod_pvt; |
req_prod = sc->sc_tx_ring.req_prod_pvt; |
while (/*CONSTCOND*/1) { |
while (/*CONSTCOND*/1) { |
|
uint16_t txflags; |
|
|
req = SLIST_FIRST(&sc->sc_txreq_head); |
req = SLIST_FIRST(&sc->sc_txreq_head); |
if (__predict_false(req == NULL)) { |
if (__predict_false(req == NULL)) { |
ifp->if_flags |= IFF_OACTIVE; |
ifp->if_flags |= IFF_OACTIVE; |
Line 733 xennet_softstart(void *arg) |
|
Line 950 xennet_softstart(void *arg) |
|
break; |
break; |
} |
} |
|
|
|
if ((m->m_pkthdr.csum_flags & |
|
(M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) { |
|
txflags = NETTXF_csum_blank; |
|
} else { |
|
txflags = 0; |
|
} |
|
|
if (m->m_pkthdr.len != m->m_len || |
if (m->m_pkthdr.len != m->m_len || |
(pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) { |
(pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) { |
|
|
Line 787 xennet_softstart(void *arg) |
|
Line 1011 xennet_softstart(void *arg) |
|
/* we will be able to send m */ |
/* we will be able to send m */ |
IFQ_DEQUEUE(&ifp->if_snd, m); |
IFQ_DEQUEUE(&ifp->if_snd, m); |
} |
} |
|
MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); |
|
|
KASSERT(((pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) == 0); |
KASSERT(((pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) == 0); |
|
|
Line 809 xennet_softstart(void *arg) |
|
Line 1034 xennet_softstart(void *arg) |
|
txreq->gref = req->txreq_gntref; |
txreq->gref = req->txreq_gntref; |
txreq->offset = pa & ~PG_FRAME; |
txreq->offset = pa & ~PG_FRAME; |
txreq->size = m->m_pkthdr.len; |
txreq->size = m->m_pkthdr.len; |
txreq->flags = 0; |
txreq->flags = txflags; |
|
|
req_prod++; |
req_prod++; |
sc->sc_tx_ring.req_prod_pvt = req_prod; |
sc->sc_tx_ring.req_prod_pvt = req_prod; |
Line 888 xennet_init(struct ifnet *ifp) |
|
Line 1113 xennet_init(struct ifnet *ifp) |
|
|
|
DPRINTFN(XEDB_FOLLOW, ("%s: xennet_init()\n", sc->sc_dev.dv_xname)); |
DPRINTFN(XEDB_FOLLOW, ("%s: xennet_init()\n", sc->sc_dev.dv_xname)); |
|
|
if (ifp->if_flags & IFF_UP) { |
if ((ifp->if_flags & IFF_RUNNING) == 0) { |
if ((ifp->if_flags & IFF_RUNNING) == 0) { |
sc->sc_rx_ring.sring->rsp_event = |
xennet_alloc_rx_buffer(sc); |
sc->sc_rx_ring.rsp_cons + 1; |
sc->sc_rx_ring.sring->rsp_event = |
hypervisor_enable_event(sc->sc_evtchn); |
sc->sc_rx_ring.rsp_cons + 1; |
hypervisor_notify_via_evtchn(sc->sc_evtchn); |
hypervisor_enable_event(sc->sc_evtchn); |
|
hypervisor_notify_via_evtchn(sc->sc_evtchn); |
|
xennet_reset(sc); |
|
} |
|
ifp->if_flags |= IFF_RUNNING; |
|
ifp->if_flags &= ~IFF_OACTIVE; |
|
ifp->if_timer = 0; |
|
} else { |
|
ifp->if_flags &= ~IFF_RUNNING; |
|
xennet_reset(sc); |
xennet_reset(sc); |
} |
} |
|
ifp->if_flags |= IFF_RUNNING; |
|
ifp->if_flags &= ~IFF_OACTIVE; |
|
ifp->if_timer = 0; |
splx(s); |
splx(s); |
return 0; |
return 0; |
} |
} |
Line 911 xennet_init(struct ifnet *ifp) |
|
Line 1130 xennet_init(struct ifnet *ifp) |
|
void |
void |
xennet_stop(struct ifnet *ifp, int disable) |
xennet_stop(struct ifnet *ifp, int disable) |
{ |
{ |
|
struct xennet_xenbus_softc *sc = ifp->if_softc; |
|
int s = splnet(); |
|
|
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
|
hypervisor_mask_event(sc->sc_evtchn); |
|
xennet_reset(sc); |
|
splx(s); |
} |
} |
|
|
void |
void |