WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [NET] front: Allow packets to be copied o

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [NET] front: Allow packets to be copied on the receive path instead of flipped.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 19 Aug 2006 02:40:26 +0000
Delivery-date: Fri, 18 Aug 2006 19:42:13 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID d4efff1beedbabd379a620586e56adc2800b9cb8
# Parent  6217dbbba0affcb64aeae7803fc1d3cadf231d51
[NET] front: Allow packets to be copied on the receive path instead of flipped.
Signed-off-by: Steven Smith <ssmith@xxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c |  253 +++++++++++--------
 1 files changed, 158 insertions(+), 95 deletions(-)

diff -r 6217dbbba0af -r d4efff1beedb 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Wed Aug 16 
16:11:12 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Wed Aug 16 
16:11:53 2006 +0100
@@ -83,6 +83,7 @@ struct netfront_info {
 
        unsigned int handle;
        unsigned int evtchn, irq;
+       unsigned int copying_receiver;
 
        /* Receive-ring batched refills. */
 #define RX_MIN_TARGET 8
@@ -171,7 +172,7 @@ static inline grant_ref_t xennet_get_rx_
 
 static int talk_to_backend(struct xenbus_device *, struct netfront_info *);
 static int setup_device(struct xenbus_device *, struct netfront_info *);
-static struct net_device *create_netdev(int, struct xenbus_device *);
+static struct net_device *create_netdev(int, int, struct xenbus_device *);
 
 static void netfront_closing(struct xenbus_device *);
 
@@ -213,6 +214,7 @@ static int __devinit netfront_probe(stru
        struct net_device *netdev;
        struct netfront_info *info;
        unsigned int handle;
+       unsigned feature_rx_copy;
 
        err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%u", &handle);
        if (err != 1) {
@@ -220,7 +222,22 @@ static int __devinit netfront_probe(stru
                return err;
        }
 
-       netdev = create_netdev(handle, dev);
+#ifndef CONFIG_XEN
+       err = xenbus_scanf(XBT_NIL, dev->otherend, "feature-rx-copy", "%u",
+                          &feature_rx_copy);
+       if (err != 1) {
+               xenbus_dev_fatal(dev, err, "reading feature-rx-copy");
+               return err;
+       }
+       if (!feature_rx_copy) {
+               xenbus_dev_fatal(dev, 0, "need a copy-capable backend");
+               return -EINVAL;
+       }
+#else
+       feature_rx_copy = 0;
+#endif
+
+       netdev = create_netdev(handle, feature_rx_copy, dev);
        if (IS_ERR(netdev)) {
                err = PTR_ERR(netdev);
                xenbus_dev_fatal(dev, err, "creating netdev");
@@ -323,6 +340,13 @@ again:
                            "event-channel", "%u", info->evtchn);
        if (err) {
                message = "writing event-channel";
+               goto abort_transaction;
+       }
+
+       err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
+                           info->copying_receiver);
+       if (err) {
+               message = "writing request-rx-copy";
                goto abort_transaction;
        }
 
@@ -597,6 +621,8 @@ static void network_alloc_rx_buffers(str
        grant_ref_t ref;
        unsigned long pfn;
        void *vaddr;
+       int nr_flips;
+       netif_rx_request_t *req;
 
        if (unlikely(!netif_carrier_ok(dev)))
                return;
@@ -652,7 +678,7 @@ no_skb:
                np->rx_target = np->rx_max_target;
 
  refill:
-       for (i = 0; ; i++) {
+       for (nr_flips = i = 0; ; i++) {
                if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
                        break;
 
@@ -663,7 +689,6 @@ no_skb:
                BUG_ON(np->rx_skbs[id]);
                np->rx_skbs[id] = skb;
 
-               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;
@@ -671,49 +696,67 @@ no_skb:
                pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
                vaddr = page_address(skb_shinfo(skb)->frags[0].page);
 
-               gnttab_grant_foreign_transfer_ref(ref,
-                                                 np->xbdev->otherend_id, pfn);
-               RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref;
-               np->rx_pfn_array[i] = pfn_to_mfn(pfn);
+               req = RING_GET_REQUEST(&np->rx, req_prod + i);
+               if (!np->copying_receiver) {
+                       gnttab_grant_foreign_transfer_ref(ref,
+                                                         
np->xbdev->otherend_id,
+                                                         pfn);
+                       np->rx_pfn_array[nr_flips] = pfn_to_mfn(pfn);
+                       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+                               /* Remove this page before passing
+                                * back to Xen. */
+                               set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+                               MULTI_update_va_mapping(np->rx_mcl+i,
+                                                       (unsigned long)vaddr,
+                                                       __pte(0), 0);
+                       }
+               } else {
+                       gnttab_grant_foreign_access_ref(ref,
+                                                       np->xbdev->otherend_id,
+                                                       pfn,
+                                                       0);
+               }
+
+               req->id = id;
+               req->gref = ref;
+       }
+
+       if ( nr_flips != 0 ) {
+               /* Tell the ballon driver what is going on. */
+               balloon_update_driver_allowance(i);
+
+               set_xen_guest_handle(reservation.extent_start,
+                                    np->rx_pfn_array);
+               reservation.nr_extents   = nr_flips;
+               reservation.extent_order = 0;
+               reservation.address_bits = 0;
+               reservation.domid        = DOMID_SELF;
 
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-                       /* Remove this page before passing back to Xen. */
-                       set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
-                       MULTI_update_va_mapping(np->rx_mcl+i,
-                                               (unsigned long)vaddr,
-                                               __pte(0), 0);
+                       /* After all PTEs have been zapped, flush the TLB. */
+                       np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
+                               UVMF_TLB_FLUSH|UVMF_ALL;
+
+                       /* Give away a batch of pages. */
+                       np->rx_mcl[i].op = __HYPERVISOR_memory_op;
+                       np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
+                       np->rx_mcl[i].args[1] = (unsigned long)&reservation;
+
+                       /* Zap PTEs and give away pages in one big
+                        * multicall. */
+                       (void)HYPERVISOR_multicall(np->rx_mcl, i+1);
+
+                       /* Check return status of HYPERVISOR_memory_op(). */
+                       if (unlikely(np->rx_mcl[i].result != i))
+                               panic("Unable to reduce memory reservation\n");
+               } else {
+                       if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                                &reservation) != i)
+                               panic("Unable to reduce memory reservation\n");
                }
-       }
-
-       /* Tell the ballon driver what is going on. */
-       balloon_update_driver_allowance(i);
-
-       set_xen_guest_handle(reservation.extent_start, np->rx_pfn_array);
-       reservation.nr_extents   = i;
-       reservation.extent_order = 0;
-       reservation.address_bits = 0;
-       reservation.domid        = DOMID_SELF;
-
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               /* After all PTEs have been zapped, flush the TLB. */
-               np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
-                       UVMF_TLB_FLUSH|UVMF_ALL;
-
-               /* Give away a batch of pages. */
-               np->rx_mcl[i].op = __HYPERVISOR_memory_op;
-               np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
-               np->rx_mcl[i].args[1] = (unsigned long)&reservation;
-
-               /* Zap PTEs and give away pages in one big multicall. */
-               (void)HYPERVISOR_multicall(np->rx_mcl, i+1);
-
-               /* Check return status of HYPERVISOR_memory_op(). */
-               if (unlikely(np->rx_mcl[i].result != i))
-                       panic("Unable to reduce memory reservation\n");
-       } else
-               if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
-                                        &reservation) != i)
-                       panic("Unable to reduce memory reservation\n");
+       } else {
+               wmb();
+       }
 
        /* Above is a suitable barrier to ensure backend will see requests. */
        np->rx.req_prod_pvt = req_prod + i;
@@ -961,10 +1004,11 @@ int xennet_get_extras(struct netfront_in
 
 static int xennet_get_responses(struct netfront_info *np,
                                struct netfront_rx_info *rinfo, RING_IDX rp,
-                               struct sk_buff_head *list, int count)
-{
-       struct mmu_update *mmu = np->rx_mmu + count;
-       struct multicall_entry *mcl = np->rx_mcl + count;
+                               struct sk_buff_head *list, int *mcl_offset_p)
+{
+       int mcl_offset = *mcl_offset_p;
+       struct mmu_update *mmu;
+       struct multicall_entry *mcl;
        struct netif_rx_response *rx = &rinfo->rx;
        struct netif_extra_info *extras = rinfo->extras;
        RING_IDX cons = np->rx.rsp_cons;
@@ -973,6 +1017,7 @@ static int xennet_get_responses(struct n
        int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
        int frags = 1;
        int err = 0;
+       unsigned long ret;
 
        if (rx->flags & NETRXF_extra_info) {
                err = xennet_get_extras(np, extras, rp);
@@ -988,6 +1033,7 @@ static int xennet_get_responses(struct n
                                WPRINTK("rx->offset: %x, size: %u\n",
                                        rx->offset, rx->status);
                        err = -EINVAL;
+                       goto next;
                }
 
                /*
@@ -1001,35 +1047,47 @@ static int xennet_get_responses(struct n
                        goto next;
                }
 
-               /* Memory pressure, insufficient buffer headroom, ... */
-               if ((mfn = gnttab_end_foreign_transfer_ref(ref)) == 0) {
-                       if (net_ratelimit())
-                               WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n",
-                                       rx->id, rx->status);
-                       xennet_move_rx_slot(np, skb, ref);
-                       err = -ENOMEM;
-                       goto next;
+               if (!np->copying_receiver) {
+                       /* Memory pressure, insufficient buffer
+                        * headroom, ... */
+                       if (!(mfn = gnttab_end_foreign_transfer_ref(ref))) {
+                               if (net_ratelimit())
+                                       WPRINTK("Unfulfilled rx req (id=%d, 
st=%d).\n",
+                                               rx->id, rx->status);
+                               xennet_move_rx_slot(np, skb, ref);
+                               err = -ENOMEM;
+                               goto next;
+                       }
+
+                       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+                               /* Remap the page. */
+                               struct page *page =
+                                       skb_shinfo(skb)->frags[0].page;
+                               unsigned long pfn = page_to_pfn(page);
+                               void *vaddr = page_address(page);
+
+                               mcl = np->rx_mcl + mcl_offset;
+                               mmu = np->rx_mmu + mcl_offset;
+
+                               MULTI_update_va_mapping(mcl,
+                                                       (unsigned long)vaddr,
+                                                       pfn_pte_ma(mfn,
+                                                                  PAGE_KERNEL),
+                                                       0);
+                               mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
+                                       | MMU_MACHPHYS_UPDATE;
+                               mmu->val = pfn;
+
+                               mcl_offset++;
+
+                               set_phys_to_machine(pfn, mfn);
+                       }
+               } else {
+                       ret = gnttab_end_foreign_access_ref(ref, 0);
+                       BUG_ON(!ret);
                }
 
                gnttab_release_grant_reference(&np->gref_rx_head, ref);
-
-               if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-                       /* Remap the page. */
-                       struct page *page = skb_shinfo(skb)->frags[0].page;
-                       unsigned long pfn = page_to_pfn(page);
-                       void *vaddr = page_address(page);
-
-                       MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
-                                               pfn_pte_ma(mfn, PAGE_KERNEL),
-                                               0);
-                       mcl++;
-                       mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
-                               | MMU_MACHPHYS_UPDATE;
-                       mmu->val = pfn;
-                       mmu++;
-
-                       set_phys_to_machine(pfn, mfn);
-               }
 
                __skb_queue_tail(list, skb);
 
@@ -1055,6 +1113,8 @@ next:
                        WPRINTK("Too many frags\n");
                err = -E2BIG;
        }
+
+       *mcl_offset_p = mcl_offset;
 
        return err;
 }
@@ -1155,8 +1215,7 @@ static int netif_poll(struct net_device 
                memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
                memset(extras, 0, sizeof(extras));
 
-               err = xennet_get_responses(np, &rinfo, rp, &tmpq, pages_done);
-               pages_done += skb_queue_len(&tmpq);
+               err = xennet_get_responses(np, &rinfo, rp, &tmpq, &pages_done);
 
                if (unlikely(err)) {
 err:
@@ -1383,6 +1442,7 @@ static void network_connect(struct net_d
        int i, requeue_idx;
        struct sk_buff *skb;
        grant_ref_t ref;
+       netif_rx_request_t *req;
 
        xennet_set_features(dev);
 
@@ -1390,12 +1450,12 @@ static void network_connect(struct net_d
        spin_lock(&np->rx_lock);
 
        /*
-         * Recovery procedure:
+        * Recovery procedure:
         *  NB. Freelist index entries are always going to be less than
         *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
         *  greater than PAGE_OFFSET: we use this property to distinguish
         *  them.
-         */
+        */
 
        /* Step 1: Discard all pending TX packet fragments. */
        for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) {
@@ -1419,13 +1479,20 @@ static void network_connect(struct net_d
 
                skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i);
                ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
-
-               gnttab_grant_foreign_transfer_ref(
-                       ref, np->xbdev->otherend_id,
-                       page_to_pfn(skb_shinfo(skb)->frags->page));
-
-               RING_GET_REQUEST(&np->rx, requeue_idx)->gref = ref;
-               RING_GET_REQUEST(&np->rx, requeue_idx)->id   = requeue_idx;
+               req = RING_GET_REQUEST(&np->rx, requeue_idx);
+
+               if (!np->copying_receiver) {
+                       gnttab_grant_foreign_transfer_ref(
+                               ref, np->xbdev->otherend_id,
+                               page_to_pfn(skb_shinfo(skb)->frags->page));
+               } else {
+                       gnttab_grant_foreign_access_ref(
+                               ref, np->xbdev->otherend_id,
+                               page_to_pfn(skb_shinfo(skb)->frags->page),
+                               0);
+               }
+               req->gref = ref;
+               req->id   = requeue_idx;
 
                requeue_idx++;
        }
@@ -1608,13 +1675,8 @@ static void network_set_multicast_list(s
 {
 }
 
-/** Create a network device.
- * @param handle device handle
- * @param val return parameter for created device
- * @return 0 on success, error code otherwise
- */
-static struct net_device * __devinit create_netdev(int handle,
-                                                  struct xenbus_device *dev)
+static struct net_device * __devinit
+create_netdev(int handle, int copying_receiver, struct xenbus_device *dev)
 {
        int i, err = 0;
        struct net_device *netdev = NULL;
@@ -1627,9 +1689,10 @@ static struct net_device * __devinit cre
                return ERR_PTR(-ENOMEM);
        }
 
-       np                = netdev_priv(netdev);
-       np->handle        = handle;
-       np->xbdev         = dev;
+       np                   = netdev_priv(netdev);
+       np->handle           = handle;
+       np->xbdev            = dev;
+       np->copying_receiver = copying_receiver;
 
        netif_carrier_off(netdev);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [NET] front: Allow packets to be copied on the receive path instead of flipped., Xen patchbot-unstable <=