[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Move net split driver onto ring.h generic rings.
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID c55ac1858bbce73be3be7ee436765cf25d33bdbf # Parent 310746cf9f27512be6520cf60c083e1726a26106 Move net split driver onto ring.h generic rings. No backend should SHARED_RING_INIT(): that's the frontend's job. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/Kconfig --- a/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Dec 1 10:27:27 2005 @@ -70,57 +70,12 @@ network devices to other guests via a high-performance shared-memory interface. -config XEN_TPMDEV_FRONTEND - bool "TPM-device frontend driver" - default n - select TCG_TPM - select TCG_XEN - help - The TPM-device frontend driver. - -config XEN_TPMDEV_BACKEND - bool "TPM-device backend driver" - default n - help - The TPM-device backend driver - -config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS - bool "TPM backend closes upon vTPM failure" - depends on XEN_TPMDEV_BACKEND - default n - help - The TPM backend closes the channel if the vTPM in userspace indicates - a failure. The corresponding domain's channel will be closed. - Say Y if you want this feature. - -config XEN_BLKDEV_FRONTEND - tristate "Block-device frontend driver" - default y - help - The block-device frontend driver allows the kernel to access block - devices mounted within another guest OS. Unless you are building a - dedicated device-driver domain, or your master control domain - (domain 0), then you almost certainly want to say Y here. - -config XEN_NETDEV_FRONTEND - tristate "Network-device frontend driver" - default y - help - The network-device frontend driver allows the kernel to access - network interfaces within another guest OS. Unless you are building a - dedicated device-driver domain, or your master control domain - (domain 0), then you almost certainly want to say Y here. - -config XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER +config XEN_NETDEV_PIPELINED_TRANSMITTER bool "Pipelined transmitter (DANGEROUS)" - depends on XEN_NETDEV_FRONTEND - default n - help - The driver will assume that the backend is pipelining packets for - transmission: whenever packets are pending in the remote backend, - the driver will not send asynchronous notifications when it queues - additional packets for transmission. - If the backend is a dumb domain, such as a transparent Ethernet + depends on XEN_NETDEV_BACKEND + default n + help + If the net backend is a dumb domain, such as a transparent Ethernet bridge with no local IP interface, it is safe to say Y here to get slightly lower network overhead. If the backend has a local IP interface; or may be doing smart things @@ -128,6 +83,47 @@ are unsure; or if you experience network hangs when this option is enabled; then you must say N here. +config XEN_TPMDEV_FRONTEND + bool "TPM-device frontend driver" + default n + select TCG_TPM + select TCG_XEN + help + The TPM-device frontend driver. + +config XEN_TPMDEV_BACKEND + bool "TPM-device backend driver" + default n + help + The TPM-device backend driver + +config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS + bool "TPM backend closes upon vTPM failure" + depends on XEN_TPMDEV_BACKEND + default n + help + The TPM backend closes the channel if the vTPM in userspace indicates + a failure. The corresponding domain's channel will be closed. + Say Y if you want this feature. + +config XEN_BLKDEV_FRONTEND + tristate "Block-device frontend driver" + default y + help + The block-device frontend driver allows the kernel to access block + devices mounted within another guest OS. Unless you are building a + dedicated device-driver domain, or your master control domain + (domain 0), then you almost certainly want to say Y here. + +config XEN_NETDEV_FRONTEND + tristate "Network-device frontend driver" + default y + help + The network-device frontend driver allows the kernel to access + network interfaces within another guest OS. Unless you are building a + dedicated device-driver domain, or your master control domain + (domain 0), then you almost certainly want to say Y here. + config XEN_BLKDEV_TAP bool "Block device tap driver" default n diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Dec 1 10:27:27 2005 @@ -15,11 +15,11 @@ CONFIG_XEN_BLKDEV_BACKEND=y # CONFIG_XEN_BLKDEV_TAP_BE is not set CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_TPMDEV_FRONTEND is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set CONFIG_XEN_SCRUB_PAGES=y diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Dec 1 10:27:27 2005 @@ -15,11 +15,11 @@ CONFIG_XEN_BLKDEV_BACKEND=y # CONFIG_XEN_BLKDEV_TAP_BE is not set CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_TPMDEV_FRONTEND is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set CONFIG_XEN_SCRUB_PAGES=y diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Dec 1 10:27:27 2005 @@ -16,7 +16,6 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set CONFIG_XEN_SCRUB_PAGES=y diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Dec 1 10:27:27 2005 @@ -16,7 +16,6 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set CONFIG_XEN_SCRUB_PAGES=y diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Dec 1 10:27:27 2005 @@ -15,11 +15,11 @@ CONFIG_XEN_BLKDEV_BACKEND=y # CONFIG_XEN_BLKDEV_TAP_BE is not set CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_TPMDEV_FRONTEND is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set CONFIG_XEN_SCRUB_PAGES=y diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Dec 1 10:27:27 2005 @@ -15,11 +15,11 @@ CONFIG_XEN_BLKDEV_BACKEND=y # CONFIG_XEN_BLKDEV_TAP_BE is not set CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_TPMDEV_FRONTEND is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set CONFIG_XEN_SCRUB_PAGES=y diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/drivers/xen/blkback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Dec 1 10:27:27 2005 @@ -107,7 +107,6 @@ blkif->evtchn = op.u.bind_interdomain.local_port; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; - SHARED_RING_INIT(sring); BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); blkif->irq = bind_evtchn_to_irqhandler( diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/drivers/xen/blktap/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Thu Dec 1 10:27:27 2005 @@ -97,7 +97,6 @@ blkif->evtchn = op.u.bind_interdomain.local_port; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; - SHARED_RING_INIT(sring); BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); blkif->irq = bind_evtchn_to_irqhandler( diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Dec 1 10:27:27 2005 @@ -53,16 +53,12 @@ unsigned int irq; /* The shared rings and indexes. */ - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; + netif_tx_back_ring_t tx; + netif_rx_back_ring_t rx; struct vm_struct *comms_area; - /* Private indexes into shared ring. */ - NETIF_RING_IDX rx_req_cons; - NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */ - NETIF_RING_IDX rx_resp_prod_copy; - NETIF_RING_IDX tx_req_cons; - NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */ + /* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */ + RING_IDX rx_req_cons_peek; /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ unsigned long credit_bytes; @@ -80,6 +76,9 @@ struct work_struct free_work; } netif_t; + +#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) void netif_creditlimit(netif_t *netif); int netif_disconnect(netif_t *netif); diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Dec 1 10:27:27 2005 @@ -184,6 +184,8 @@ unsigned long rx_ring_ref, unsigned int evtchn) { int err; + netif_tx_sring_t *txs; + netif_rx_sring_t *rxs; evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain, .u.bind_interdomain.remote_dom = netif->domid, @@ -216,10 +218,15 @@ netif->evtchn, netif_be_int, 0, netif->dev->name, netif); disable_irq(netif->irq); - netif->tx = (netif_tx_interface_t *)netif->comms_area->addr; - netif->rx = (netif_rx_interface_t *) + txs = (netif_tx_sring_t *)netif->comms_area->addr; + BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE); + + rxs = (netif_rx_sring_t *) ((char *)netif->comms_area->addr + PAGE_SIZE); - netif->tx->resp_prod = netif->rx->resp_prod = 0; + BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE); + + netif->rx_req_cons_peek = 0; + netif_get(netif); wmb(); /* Other CPUs see new state before interface is started. */ @@ -246,7 +253,7 @@ unregister_netdev(netif->dev); - if (netif->tx) { + if (netif->tx.sring) { unmap_frontend_pages(netif); free_vm_area(netif->comms_area); } diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Dec 1 10:27:27 2005 @@ -38,8 +38,8 @@ #define MAX_PENDING_REQS 256 static struct sk_buff_head rx_queue; -static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1]; -static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; +static multicall_entry_t rx_mcl[NET_RX_RING_SIZE*2+1]; +static mmu_update_t rx_mmu[NET_RX_RING_SIZE]; static gnttab_transfer_t grant_rx_op[MAX_PENDING_REQS]; static unsigned char rx_notify[NR_IRQS]; @@ -126,8 +126,9 @@ /* Drop the packet if the target domain has no receive buffers. */ if (!netif->active || - (netif->rx_req_cons == netif->rx->req_prod) || - ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE)) + (netif->rx_req_cons_peek == netif->rx.sring->req_prod) || + ((netif->rx_req_cons_peek - netif->rx.rsp_prod_pvt) == + NET_RX_RING_SIZE)) goto drop; /* @@ -154,7 +155,7 @@ skb = nskb; } - netif->rx_req_cons++; + netif->rx_req_cons_peek++; netif_get(netif); skb_queue_tail(&rx_queue, skb); @@ -198,7 +199,7 @@ unsigned long vdata, old_mfn, new_mfn; struct sk_buff_head rxq; struct sk_buff *skb; - u16 notify_list[NETIF_RX_RING_SIZE]; + u16 notify_list[NET_RX_RING_SIZE]; int notify_nr = 0; int ret; @@ -233,9 +234,9 @@ gop->mfn = old_mfn; gop->domid = netif->domid; - gop->ref = netif->rx->ring[ - MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref; - netif->rx_resp_prod_copy++; + gop->ref = RING_GET_REQUEST( + &netif->rx, netif->rx.req_cons)->gref; + netif->rx.req_cons++; gop++; mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) | @@ -300,8 +301,7 @@ status = NETIF_RSP_ERROR; } irq = netif->irq; - id = netif->rx->ring[ - MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; + id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id; if (make_rx_response(netif, id, status, (unsigned long)skb->data & ~PAGE_MASK, size, skb->proto_csum_valid) && @@ -371,13 +371,31 @@ spin_unlock_irq(&net_schedule_list_lock); } +/* + * Note on CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER: + * If this driver is pipelining transmit requests then we can be very + * aggressive in avoiding new-packet notifications -- frontend only needs to + * send a notification if there are no outstanding unreceived responses. + * If we may be buffer transmit buffers for any reason then we must be rather + * more conservative and advertise that we are 'sleeping' this connection here. + */ void netif_schedule_work(netif_t *netif) { - if ((netif->tx_req_cons != netif->tx->req_prod) && - ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE)) { + if (RING_HAS_UNCONSUMED_REQUESTS(&netif->tx)) { add_to_net_schedule_list_tail(netif); maybe_schedule_tx_action(); } +#ifndef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER + else { + netif->tx.sring->server_is_sleeping = 1; + mb(); + if (RING_HAS_UNCONSUMED_REQUESTS(&netif->tx)) { + netif->tx.sring->server_is_sleeping = 0; + add_to_net_schedule_list_tail(netif); + maybe_schedule_tx_action(); + } + } +#endif } void netif_deschedule_work(netif_t *netif) @@ -437,11 +455,18 @@ * packets. */ mb(); - if ((netif->tx_req_cons != netif->tx->req_prod) && - ((netif->tx_req_cons-netif->tx_resp_prod) != - NETIF_TX_RING_SIZE)) + + if (RING_HAS_UNCONSUMED_REQUESTS(&netif->tx)) { add_to_net_schedule_list_tail(netif); - + } else { + netif->tx.sring->server_is_sleeping = 1; + mb(); + if (RING_HAS_UNCONSUMED_REQUESTS(&netif->tx)) { + netif->tx.sring->server_is_sleeping = 0; + add_to_net_schedule_list_tail(netif); + } + } + netif_put(netif); } } @@ -454,7 +479,7 @@ netif_t *netif; netif_tx_request_t txreq; u16 pending_idx; - NETIF_RING_IDX i; + RING_IDX i; gnttab_map_grant_ref_t *mop; unsigned int data_len; int ret; @@ -472,16 +497,14 @@ remove_from_net_schedule_list(netif); /* Work to do? */ - i = netif->tx_req_cons; - if ((i == netif->tx->req_prod) || - ((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE)) { + if (!RING_HAS_UNCONSUMED_REQUESTS(&netif->tx)) { netif_put(netif); continue; } + i = netif->tx.req_cons; rmb(); /* Ensure that we see the request before we copy it. */ - memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, - sizeof(txreq)); + memcpy(&txreq, RING_GET_REQUEST(&netif->tx, i), sizeof(txreq)); /* Credit-based scheduling. */ if (txreq.size > netif->remaining_credit) { unsigned long now = jiffies; @@ -515,12 +538,7 @@ } netif->remaining_credit -= txreq.size; - /* - * Why the barrier? It ensures that the frontend sees updated - * req_cons before we check for more work to schedule. - */ - netif->tx->req_cons = ++netif->tx_req_cons; - mb(); + netif->tx.req_cons++; netif_schedule_work(netif); @@ -688,17 +706,18 @@ u16 id, s8 st) { - NETIF_RING_IDX i = netif->tx_resp_prod; + RING_IDX i = netif->tx.rsp_prod_pvt; netif_tx_response_t *resp; - resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp; + resp = RING_GET_RESPONSE(&netif->tx, i); resp->id = id; resp->status = st; wmb(); - netif->tx->resp_prod = netif->tx_resp_prod = ++i; + netif->tx.rsp_prod_pvt = ++i; + RING_PUSH_RESPONSES(&netif->tx); mb(); /* Update producer before checking event threshold. */ - if (i == netif->tx->event) + if (i == netif->tx.sring->rsp_event) notify_remote_via_irq(netif->irq); } @@ -709,10 +728,10 @@ u16 size, u16 csum_valid) { - NETIF_RING_IDX i = netif->rx_resp_prod; + RING_IDX i = netif->rx.rsp_prod_pvt; netif_rx_response_t *resp; - resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp; + resp = RING_GET_RESPONSE(&netif->rx, i); resp->offset = offset; resp->csum_valid = csum_valid; resp->id = id; @@ -720,10 +739,11 @@ if (st < 0) resp->status = (s16)st; wmb(); - netif->rx->resp_prod = netif->rx_resp_prod = ++i; + netif->rx.rsp_prod_pvt = ++i; + RING_PUSH_RESPONSES(&netif->rx); mb(); /* Update producer before checking event threshold. */ - return (i == netif->rx->event); + return (i == netif->rx.sring->rsp_event); } static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs) @@ -739,16 +759,16 @@ netif = list_entry(ent, netif_t, list); printk(KERN_ALERT " %d: private(rx_req_cons=%08x " "rx_resp_prod=%08x\n", - i, netif->rx_req_cons, netif->rx_resp_prod); + i, netif->rx.req_cons, netif->rx.rsp_prod_pvt); printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", - netif->tx_req_cons, netif->tx_resp_prod); + netif->tx.req_cons, netif->tx.rsp_prod_pvt); printk(KERN_ALERT " shared(rx_req_prod=%08x " "rx_resp_prod=%08x\n", - netif->rx->req_prod, netif->rx->resp_prod); + netif->rx.sring->req_prod, netif->rx.sring->rsp_prod); printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", - netif->rx->event, netif->tx->req_prod); + netif->rx.sring->rsp_event, netif->tx.sring->req_prod); printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", - netif->tx->resp_prod, netif->tx->event); + netif->tx.sring->rsp_prod, netif->tx.sring->rsp_event); i++; } @@ -764,7 +784,7 @@ struct page *page; /* We can increase reservation by this much in net_rx_action(). */ - balloon_update_driver_allowance(NETIF_RX_RING_SIZE); + balloon_update_driver_allowance(NET_RX_RING_SIZE); skb_queue_head_init(&rx_queue); skb_queue_head_init(&tx_queue); diff -r 310746cf9f27 -r c55ac1858bbc linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Dec 1 10:10:40 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Dec 1 10:27:27 2005 @@ -61,6 +61,9 @@ #define GRANT_INVALID_REF 0 +#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) + #ifndef __GFP_NOWARN #define __GFP_NOWARN 0 #endif @@ -76,22 +79,9 @@ /* Allow headroom on each rx pkt for Ethernet header, alignment padding, ... */ #define RX_HEADROOM 200 -/* - * If the backend driver is pipelining transmit requests then we can be very - * aggressive in avoiding new-packet notifications -- only need to send a - * notification if there are no outstanding unreceived responses. - * If the backend may be buffering our transmit buffers for any reason then we - * are rather more conservative. - */ -#ifdef CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER -#define TX_TEST_IDX resp_prod /* aggressive: any outstanding responses? */ -#else -#define TX_TEST_IDX req_cons /* conservative: not seen all our requests? */ -#endif - -static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE]; -static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1]; -static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; +static unsigned long rx_pfn_array[NET_RX_RING_SIZE]; +static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1]; +static mmu_update_t rx_mmu[NET_RX_RING_SIZE]; struct netfront_info { @@ -99,11 +89,10 @@ struct net_device *netdev; struct net_device_stats stats; - NETIF_RING_IDX rx_resp_cons, tx_resp_cons; unsigned int tx_full; - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; + netif_tx_front_ring_t tx; + netif_rx_front_ring_t rx; spinlock_t tx_lock; spinlock_t rx_lock; @@ -124,7 +113,7 @@ /* Receive-ring batched refills. */ #define RX_MIN_TARGET 8 -#define RX_MAX_TARGET NETIF_RX_RING_SIZE +#define RX_MAX_TARGET NET_RX_RING_SIZE int rx_min_target, rx_max_target, rx_target; struct sk_buff_head rx_batch; @@ -132,13 +121,13 @@ * {tx,rx}_skbs store outstanding skbuffs. The first entry in each * array is an index into a chain of free entries. */ - struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; + struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1]; + struct sk_buff *rx_skbs[NET_RX_RING_SIZE+1]; grant_ref_t gref_tx_head; - grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; + grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1]; grant_ref_t gref_rx_head; - grant_ref_t grant_rx_ref[NETIF_TX_RING_SIZE + 1]; + grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1]; struct xenbus_device *xbdev; int tx_ring_ref; @@ -337,37 +326,45 @@ static int setup_device(struct xenbus_device *dev, struct netfront_info *info) { + netif_tx_sring_t *txs; + netif_rx_sring_t *rxs; int err; struct net_device *netdev = info->netdev; info->tx_ring_ref = GRANT_INVALID_REF; info->rx_ring_ref = GRANT_INVALID_REF; - info->rx = NULL; - info->tx = NULL; + info->rx.sring = NULL; + info->tx.sring = NULL; info->irq = 0; - info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); - if (!info->tx) { + txs = (netif_tx_sring_t *)__get_free_page(GFP_KERNEL); + if (!txs) { err = -ENOMEM; xenbus_dev_fatal(dev, err, "allocating tx ring page"); goto fail; } - info->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); - if (!info->rx) { + rxs = (netif_rx_sring_t *)__get_free_page(GFP_KERNEL); + if (!rxs) { err = -ENOMEM; xenbus_dev_fatal(dev, err, "allocating rx ring page"); goto fail; } - memset(info->tx, 0, PAGE_SIZE); - memset(info->rx, 0, PAGE_SIZE); + memset(txs, 0, PAGE_SIZE); + memset(rxs, 0, PAGE_SIZE); info->backend_state = BEST_DISCONNECTED; - err = xenbus_grant_ring(dev, virt_to_mfn(info->tx)); + SHARED_RING_INIT(txs); + FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); + + SHARED_RING_INIT(rxs); + FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE); + + err = xenbus_grant_ring(dev, virt_to_mfn(txs)); if (err < 0) goto fail; info->tx_ring_ref = err; - err = xenbus_grant_ring(dev, virt_to_mfn(info->rx)); + err = xenbus_grant_ring(dev, virt_to_mfn(rxs)); if (err < 0) goto fail; info->rx_ring_ref = err; @@ -454,7 +451,7 @@ np->user_state = UST_OPEN; network_alloc_rx_buffers(dev); - np->rx->event = np->rx_resp_cons + 1; + np->rx.sring->rsp_event = np->rx.rsp_cons + 1; netif_start_queue(dev); @@ -463,7 +460,7 @@ static void network_tx_buf_gc(struct net_device *dev) { - NETIF_RING_IDX i, prod; + RING_IDX i, prod; unsigned short id; struct netfront_info *np = netdev_priv(dev); struct sk_buff *skb; @@ -472,11 +469,11 @@ return; do { - prod = np->tx->resp_prod; + prod = np->tx.sring->rsp_prod; rmb(); /* Ensure we see responses up to 'rp'. */ - for (i = np->tx_resp_cons; i != prod; i++) { - id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; + for (i = np->tx.rsp_cons; i != prod; i++) { + id = RING_GET_RESPONSE(&np->tx, i)->id; skb = np->tx_skbs[id]; if (unlikely(gnttab_query_foreign_access( np->grant_tx_ref[id]) != 0)) { @@ -494,7 +491,7 @@ dev_kfree_skb_irq(skb); } - np->tx_resp_cons = prod; + np->tx.rsp_cons = prod; /* * Set a new event, then check for race with update of tx_cons. @@ -504,12 +501,14 @@ * data is outstanding: in such cases notification from Xen is * likely to be the only kick that we'll get. */ - np->tx->event = prod + ((np->tx->req_prod - prod) >> 1) + 1; + np->tx.sring->rsp_event = + prod + ((np->tx.sring->req_prod - prod) >> 1) + 1; mb(); - } while (prod != np->tx->resp_prod); + } while (prod != np->tx.sring->rsp_prod); out: - if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) { + if (np->tx_full && + ((np->tx.sring->req_prod - prod) < NET_TX_RING_SIZE)) { np->tx_full = 0; if (np->user_state == UST_OPEN) netif_wake_queue(dev); @@ -523,7 +522,7 @@ struct netfront_info *np = netdev_priv(dev); struct sk_buff *skb; int i, batch_target; - NETIF_RING_IDX req_prod = np->rx->req_prod; + RING_IDX req_prod = np->rx.req_prod_pvt; struct xen_memory_reservation reservation; grant_ref_t ref; @@ -536,7 +535,7 @@ * allocator, so should reduce the chance of failed allocation requests * both for ourself and for other kernel subsystems. */ - batch_target = np->rx_target - (req_prod - np->rx_resp_cons); + batch_target = np->rx_target - (req_prod - np->rx.rsp_cons); for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { skb = alloc_xen_skb(dev->mtu + RX_HEADROOM); if (skb == NULL) @@ -558,13 +557,13 @@ np->rx_skbs[id] = skb; - np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id; + RING_GET_REQUEST(&np->rx, req_prod + i)->id = id; ref = gnttab_claim_grant_reference(&np->gref_rx_head); BUG_ON((signed short)ref < 0); np->grant_rx_ref[id] = ref; gnttab_grant_foreign_transfer_ref(ref, np->xbdev->otherend_id); - np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; + RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref; rx_pfn_array[i] = virt_to_mfn(skb->head); /* Remove this page from map before passing back to Xen. */ @@ -599,10 +598,11 @@ panic("Unable to reduce memory reservation\n"); /* Above is a suitable barrier to ensure backend will see requests. */ - np->rx->req_prod = req_prod + i; + np->rx.req_prod_pvt = req_prod + i; + RING_PUSH_REQUESTS(&np->rx); /* Adjust our fill target if we risked running out of buffers. */ - if (((req_prod - np->rx->resp_prod) < (np->rx_target / 4)) && + if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) && ((np->rx_target *= 2) > np->rx_max_target)) np->rx_target = np->rx_max_target; } @@ -613,7 +613,7 @@ unsigned short id; struct netfront_info *np = netdev_priv(dev); netif_tx_request_t *tx; - NETIF_RING_IDX i; + RING_IDX i; grant_ref_t ref; unsigned long mfn; @@ -643,12 +643,12 @@ goto drop; } - i = np->tx->req_prod; + i = np->tx.req_prod_pvt; id = GET_ID_FROM_FREELIST(np->tx_skbs); np->tx_skbs[id] = skb; - tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; + tx = RING_GET_REQUEST(&np->tx, i); tx->id = id; ref = gnttab_claim_grant_reference(&np->gref_tx_head); @@ -662,11 +662,12 @@ tx->csum_blank = (skb->ip_summed == CHECKSUM_HW); wmb(); /* Ensure that backend will see the request. */ - np->tx->req_prod = i + 1; + np->tx.req_prod_pvt = i + 1; + RING_PUSH_REQUESTS(&np->tx); network_tx_buf_gc(dev); - if ((i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1)) { + if (RING_FULL(&np->tx)) { np->tx_full = 1; netif_stop_queue(dev); } @@ -678,8 +679,10 @@ /* Only notify Xen if we really have to. */ mb(); - if (np->tx->TX_TEST_IDX == i) + if (np->tx.sring->server_is_sleeping) { + np->tx.sring->server_is_sleeping = 0; notify_remote_via_irq(np->irq); + } return 0; @@ -699,7 +702,7 @@ network_tx_buf_gc(dev); spin_unlock_irqrestore(&np->tx_lock, flags); - if ((np->rx_resp_cons != np->rx->resp_prod) && + if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx) && (np->user_state == UST_OPEN)) netif_rx_schedule(dev); @@ -712,7 +715,7 @@ struct netfront_info *np = netdev_priv(dev); struct sk_buff *skb, *nskb; netif_rx_response_t *rx; - NETIF_RING_IDX i, rp; + RING_IDX i, rp; mmu_update_t *mmu = rx_mmu; multicall_entry_t *mcl = rx_mcl; int work_done, budget, more_to_do = 1; @@ -732,13 +735,13 @@ if ((budget = *pbudget) > dev->quota) budget = dev->quota; - rp = np->rx->resp_prod; + rp = np->rx.sring->rsp_prod; rmb(); /* Ensure we see queued responses up to 'rp'. */ - for (i = np->rx_resp_cons, work_done = 0; + for (i = np->rx.rsp_cons, work_done = 0; (i != rp) && (work_done < budget); i++, work_done++) { - rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; + rx = RING_GET_RESPONSE(&np->rx, i); /* * This definitely indicates a bug, either in this driver or @@ -756,10 +759,11 @@ if (net_ratelimit()) WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n", rx->id, rx->status); - np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)]. - req.id = rx->id; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = + rx->id; wmb(); - np->rx->req_prod++; + np->rx.req_prod_pvt++; + RING_PUSH_REQUESTS(&np->rx); work_done--; continue; } @@ -861,11 +865,11 @@ dev->last_rx = jiffies; } - np->rx_resp_cons = i; + np->rx.rsp_cons = i; /* If we get a callback with very few responses, reduce fill target. */ /* NB. Note exponential increase, linear decrease. */ - if (((np->rx->req_prod - np->rx->resp_prod) > + if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) > ((3*np->rx_target) / 4)) && (--np->rx_target < np->rx_min_target)) np->rx_target = np->rx_min_target; @@ -878,11 +882,11 @@ if (work_done < budget) { local_irq_save(flags); - np->rx->event = i + 1; + np->rx.sring->rsp_event = i + 1; /* Deal with hypervisor racing our resetting of rx_event. */ mb(); - if (np->rx->resp_prod == i) { + if (np->rx.sring->rsp_prod == i) { __netif_rx_complete(dev); more_to_do = 0; } @@ -925,8 +929,8 @@ /* Recovery procedure: */ /* Step 1: Reinitialise variables. */ - np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; - np->rx->event = np->tx->event = 1; + np->tx_full = 0; + np->rx.sring->rsp_event = np->tx.sring->rsp_event = 1; /* * Step 2: Rebuild the RX and TX ring contents. @@ -946,13 +950,14 @@ * to avoid this but maybe it doesn't matter so much given the * interface has been down. */ - for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) { + for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) { if ((unsigned long)np->tx_skbs[i] < __PAGE_OFFSET) continue; skb = np->tx_skbs[i]; - tx = &np->tx->ring[requeue_idx++].req; + tx = RING_GET_REQUEST(&np->tx, requeue_idx); + requeue_idx++; tx->id = i; gnttab_grant_foreign_access_ref( @@ -968,21 +973,23 @@ np->stats.tx_packets++; } wmb(); - np->tx->req_prod = requeue_idx; + np->tx.req_prod_pvt = requeue_idx; + RING_PUSH_REQUESTS(&np->tx); /* Rebuild the RX buffer freelist and the RX ring itself. */ - for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { + for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) { if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET) continue; gnttab_grant_foreign_transfer_ref( np->grant_rx_ref[i], np->xbdev->otherend_id); - np->rx->ring[requeue_idx].req.gref = + RING_GET_REQUEST(&np->rx, requeue_idx)->gref = np->grant_rx_ref[i]; - np->rx->ring[requeue_idx].req.id = i; + RING_GET_REQUEST(&np->rx, requeue_idx)->id = i; requeue_idx++; } wmb(); - np->rx->req_prod = requeue_idx; + np->rx.req_prod_pvt = requeue_idx; + RING_PUSH_REQUESTS(&np->rx); /* * Step 3: All public and private state should now be sane. Get @@ -1066,25 +1073,25 @@ np->rx_max_target = RX_MAX_TARGET; /* Initialise {tx,rx}_skbs as a free chain containing every entry. */ - for (i = 0; i <= NETIF_TX_RING_SIZE; i++) { + for (i = 0; i <= NET_TX_RING_SIZE; i++) { np->tx_skbs[i] = (void *)((unsigned long) i+1); np->grant_tx_ref[i] = GRANT_INVALID_REF; } - for (i = 0; i <= NETIF_RX_RING_SIZE; i++) { + for (i = 0; i <= NET_RX_RING_SIZE; i++) { np->rx_skbs[i] = (void *)((unsigned long) i+1); np->grant_rx_ref[i] = GRANT_INVALID_REF; } /* A grant for every tx ring slot */ - if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, + if (gnttab_alloc_grant_references(NET_TX_RING_SIZE, &np->gref_tx_head) < 0) { printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); err = -ENOMEM; goto exit; } /* A grant for every rx ring slot */ - if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, + if (gnttab_alloc_grant_references(NET_RX_RING_SIZE, &np->gref_rx_head) < 0) { printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); gnttab_free_grant_references(np->gref_tx_head); @@ -1212,12 +1219,12 @@ spin_unlock(&info->rx_lock); spin_unlock_irq(&info->tx_lock); - end_access(info->tx_ring_ref, info->tx); - end_access(info->rx_ring_ref, info->rx); + end_access(info->tx_ring_ref, info->tx.sring); + end_access(info->rx_ring_ref, info->rx.sring); info->tx_ring_ref = GRANT_INVALID_REF; info->rx_ring_ref = GRANT_INVALID_REF; - info->tx = NULL; - info->rx = NULL; + info->tx.sring = NULL; + info->rx.sring = NULL; if (info->irq) unbind_from_irqhandler(info->irq, info->netdev); diff -r 310746cf9f27 -r c55ac1858bbc xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Thu Dec 1 10:10:40 2005 +++ b/xen/include/public/io/netif.h Thu Dec 1 10:27:27 2005 @@ -8,6 +8,8 @@ #ifndef __XEN_PUBLIC_IO_NETIF_H__ #define __XEN_PUBLIC_IO_NETIF_H__ + +#include "ring.h" typedef struct netif_tx_request { grant_ref_t gref; /* Reference to buffer page */ @@ -35,57 +37,12 @@ } netif_rx_response_t; /* - * We use a special capitalised type name because it is _essential_ that all - * arithmetic on indexes is done on an integer type of the correct size. + * Generate netif ring structures and types. */ -typedef uint32_t NETIF_RING_IDX; -/* - * Ring indexes are 'free running'. That is, they are not stored modulo the - * size of the ring buffer. The following macros convert a free-running counter - * into a value that can directly index a ring-buffer array. - */ -#define MASK_NETIF_RX_IDX(_i) ((_i)&(NETIF_RX_RING_SIZE-1)) -#define MASK_NETIF_TX_IDX(_i) ((_i)&(NETIF_TX_RING_SIZE-1)) +DEFINE_RING_TYPES(netif_tx, netif_tx_request_t, netif_tx_response_t); +DEFINE_RING_TYPES(netif_rx, netif_rx_request_t, netif_rx_response_t); -#define NETIF_TX_RING_SIZE 256 -#define NETIF_RX_RING_SIZE 256 - -/* This structure must fit in a memory page. */ -typedef struct netif_tx_interface { - /* - * Frontend places packets into ring at tx_req_prod. - * Frontend receives event when tx_resp_prod passes tx_event. - * 'req_cons' is a shadow of the backend's request consumer -- the frontend - * may use it to determine if all queued packets have been seen by the - * backend. - */ - NETIF_RING_IDX req_prod; - NETIF_RING_IDX req_cons; - NETIF_RING_IDX resp_prod; - NETIF_RING_IDX event; - union { - netif_tx_request_t req; - netif_tx_response_t resp; - } ring[NETIF_TX_RING_SIZE]; -} netif_tx_interface_t; - -/* This structure must fit in a memory page. */ -typedef struct netif_rx_interface { - /* - * Frontend places empty buffers into ring at rx_req_prod. - * Frontend receives event when rx_resp_prod passes rx_event. - */ - NETIF_RING_IDX req_prod; - NETIF_RING_IDX resp_prod; - NETIF_RING_IDX event; - union { - netif_rx_request_t req; - netif_rx_response_t resp; - } ring[NETIF_RX_RING_SIZE]; -} netif_rx_interface_t; - -/* Descriptor status values */ #define NETIF_RSP_DROPPED -2 #define NETIF_RSP_ERROR -1 #define NETIF_RSP_OKAY 0 diff -r 310746cf9f27 -r c55ac1858bbc xen/include/public/io/ring.h --- a/xen/include/public/io/ring.h Thu Dec 1 10:10:40 2005 +++ b/xen/include/public/io/ring.h Thu Dec 1 10:27:27 2005 @@ -1,3 +1,6 @@ + + + /* * Shared producer-consumer ring macros. * Tim Deegan and Andrew Warfield November 2004. @@ -22,7 +25,7 @@ * power of two (so we can mask with (size-1) to loop around). */ #define __RING_SIZE(_s, _sz) \ - (__RD32(((_sz) - 2*sizeof(RING_IDX)) / sizeof((_s)->ring[0]))) + (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0]))) /* * Macros to make the correct C datatypes for a new kind of ring. @@ -65,6 +68,8 @@ struct __name##_sring { \ RING_IDX req_prod; \ RING_IDX rsp_prod; \ + RING_IDX rsp_event; /* notify client when rsp_prod == rsp_event */ \ + uint8_t server_is_sleeping; /* notify server to kick off work */ \ union __name##_sring_entry ring[1]; /* variable-length */ \ }; \ \ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |