| @@ -1,41 +1,41 @@ | | | @@ -1,41 +1,41 @@ |
1 | /* $NetBSD: xennetback_xenbus.c,v 1.118 2023/08/09 08:38:05 riastradh Exp $ */ | | 1 | /* $NetBSD: xennetback_xenbus.c,v 1.119 2023/08/09 08:38:16 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 Manuel Bouyer. | | 4 | * Copyright (c) 2006 Manuel Bouyer. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ | | 25 | */ |
26 | | | 26 | |
27 | #include <sys/cdefs.h> | | 27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.118 2023/08/09 08:38:05 riastradh Exp $"); | | 28 | __KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.119 2023/08/09 08:38:16 riastradh Exp $"); |
29 | | | 29 | |
30 | #include <sys/types.h> | | 30 | #include <sys/types.h> |
31 | #include <sys/param.h> | | 31 | #include <sys/param.h> |
32 | #include <sys/systm.h> | | 32 | #include <sys/systm.h> |
33 | #include <sys/kmem.h> | | 33 | #include <sys/kmem.h> |
34 | #include <sys/queue.h> | | 34 | #include <sys/queue.h> |
35 | #include <sys/kernel.h> | | 35 | #include <sys/kernel.h> |
36 | #include <sys/mbuf.h> | | 36 | #include <sys/mbuf.h> |
37 | #include <sys/protosw.h> | | 37 | #include <sys/protosw.h> |
38 | #include <sys/socket.h> | | 38 | #include <sys/socket.h> |
39 | #include <sys/ioctl.h> | | 39 | #include <sys/ioctl.h> |
40 | #include <sys/errno.h> | | 40 | #include <sys/errno.h> |
41 | #include <sys/device.h> | | 41 | #include <sys/device.h> |
| @@ -801,44 +801,36 @@ static int | | | @@ -801,44 +801,36 @@ static int |
801 | xennetback_evthandler(void *arg) | | 801 | xennetback_evthandler(void *arg) |
802 | { | | 802 | { |
803 | struct xnetback_instance *xneti = arg; | | 803 | struct xnetback_instance *xneti = arg; |
804 | struct ifnet *ifp = &xneti->xni_if; | | 804 | struct ifnet *ifp = &xneti->xni_if; |
805 | netif_tx_request_t txreq; | | 805 | netif_tx_request_t txreq; |
806 | struct mbuf *m, *m0 = NULL, *mlast = NULL; | | 806 | struct mbuf *m, *m0 = NULL, *mlast = NULL; |
807 | int receive_pending; | | 807 | int receive_pending; |
808 | int queued = 0, m0_len = 0; | | 808 | int queued = 0, m0_len = 0; |
809 | struct xnetback_xstate *xst; | | 809 | struct xnetback_xstate *xst; |
810 | const bool discard = ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != | | 810 | const bool discard = ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != |
811 | (IFF_UP | IFF_RUNNING)); | | 811 | (IFF_UP | IFF_RUNNING)); |
812 | | | 812 | |
813 | XENPRINTF(("xennetback_evthandler ")); | | 813 | XENPRINTF(("xennetback_evthandler ")); |
| | | 814 | again: |
814 | while (1) { | | 815 | while (1) { |
815 | /* | | 816 | /* |
816 | * XXX The xen_rmb here and comment make no sense: | | 817 | * XXX The xen_rmb here and comment make no sense: |
817 | * xneti->xni_txring.req_cons is a private variable. | | 818 | * xneti->xni_txring.req_cons is a private variable. |
818 | */ | | 819 | */ |
819 | xen_rmb(); /* be sure to read the request before updating */ | | 820 | xen_rmb(); /* be sure to read the request before updating */ |
820 | /* XXX Unclear what this xen_wmb is for. */ | | 821 | /* XXX Unclear what this xen_wmb is for. */ |
821 | xen_wmb(); | | 822 | xen_wmb(); |
822 | /* | | 823 | if (!RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_txring)) |
823 | * XXX RING_FINAL_CHECK_FOR_REQUESTS issues the most | | | |
824 | * expensive memory barrier, xen_mb. This should be | | | |
825 | * used only at the end of the loop after we updating | | | |
826 | * the producer with the last index of the requests we | | | |
827 | * consumed in the queue. | | | |
828 | */ | | | |
829 | RING_FINAL_CHECK_FOR_REQUESTS(&xneti->xni_txring, | | | |
830 | receive_pending); | | | |
831 | if (receive_pending == 0) | | | |
832 | break; | | 824 | break; |
833 | /* | | 825 | /* |
834 | * Ensure we have read the producer's queue index in | | 826 | * Ensure we have read the producer's queue index in |
835 | * RING_FINAL_CHECK_FOR_REQUESTS before we read the | | 827 | * RING_FINAL_CHECK_FOR_REQUESTS before we read the |
836 | * content of the producer's next request in | | 828 | * content of the producer's next request in |
837 | * RING_COPY_REQUEST. | | 829 | * RING_COPY_REQUEST. |
838 | */ | | 830 | */ |
839 | xen_rmb(); | | 831 | xen_rmb(); |
840 | RING_COPY_REQUEST(&xneti->xni_txring, | | 832 | RING_COPY_REQUEST(&xneti->xni_txring, |
841 | xneti->xni_txring.req_cons, | | 833 | xneti->xni_txring.req_cons, |
842 | &txreq); | | 834 | &txreq); |
843 | /* XXX Unclear what this xen_rmb is for. */ | | 835 | /* XXX Unclear what this xen_rmb is for. */ |
844 | xen_rmb(); | | 836 | xen_rmb(); |
| @@ -971,26 +963,29 @@ mbuf_fail: | | | @@ -971,26 +963,29 @@ mbuf_fail: |
971 | | | 963 | |
972 | KASSERT(queued <= NB_XMIT_PAGES_BATCH); | | 964 | KASSERT(queued <= NB_XMIT_PAGES_BATCH); |
973 | if (__predict_false(m0 && | | 965 | if (__predict_false(m0 && |
974 | (txreq.flags & NETTXF_more_data) == 0)) { | | 966 | (txreq.flags & NETTXF_more_data) == 0)) { |
975 | /* Last fragment, stop appending mbufs */ | | 967 | /* Last fragment, stop appending mbufs */ |
976 | m0 = NULL; | | 968 | m0 = NULL; |
977 | } | | 969 | } |
978 | if (queued == NB_XMIT_PAGES_BATCH) { | | 970 | if (queued == NB_XMIT_PAGES_BATCH) { |
979 | KASSERT(m0 == NULL); | | 971 | KASSERT(m0 == NULL); |
980 | xennetback_tx_copy_process(ifp, xneti, queued); | | 972 | xennetback_tx_copy_process(ifp, xneti, queued); |
981 | queued = 0; | | 973 | queued = 0; |
982 | } | | 974 | } |
983 | } | | 975 | } |
| | | 976 | RING_FINAL_CHECK_FOR_REQUESTS(&xneti->xni_txring, receive_pending); |
| | | 977 | if (receive_pending) |
| | | 978 | goto again; |
984 | if (m0) { | | 979 | if (m0) { |
985 | /* Queue empty, and still unfinished multi-fragment request */ | | 980 | /* Queue empty, and still unfinished multi-fragment request */ |
986 | printf("%s: dropped unfinished multi-fragment\n", | | 981 | printf("%s: dropped unfinished multi-fragment\n", |
987 | ifp->if_xname); | | 982 | ifp->if_xname); |
988 | xennetback_tx_copy_abort(ifp, xneti, queued); | | 983 | xennetback_tx_copy_abort(ifp, xneti, queued); |
989 | queued = 0; | | 984 | queued = 0; |
990 | m0 = NULL; | | 985 | m0 = NULL; |
991 | } | | 986 | } |
992 | if (queued > 0) | | 987 | if (queued > 0) |
993 | xennetback_tx_copy_process(ifp, xneti, queued); | | 988 | xennetback_tx_copy_process(ifp, xneti, queued); |
994 | | | 989 | |
995 | /* check to see if we can transmit more packets */ | | 990 | /* check to see if we can transmit more packets */ |
996 | if_schedule_deferred_start(ifp); | | 991 | if_schedule_deferred_start(ifp); |