| @@ -1,41 +1,41 @@ | | | @@ -1,41 +1,41 @@ |
1 | /* $NetBSD: xennetback_xenbus.c,v 1.71 2018/10/26 05:33:21 cherry Exp $ */ | | 1 | /* $NetBSD: xennetback_xenbus.c,v 1.72 2018/12/23 12:09:45 bouyer 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.71 2018/10/26 05:33:21 cherry Exp $"); | | 28 | __KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.72 2018/12/23 12:09:45 bouyer Exp $"); |
29 | | | 29 | |
30 | #include "opt_xen.h" | | 30 | #include "opt_xen.h" |
31 | | | 31 | |
32 | #include <sys/types.h> | | 32 | #include <sys/types.h> |
33 | #include <sys/param.h> | | 33 | #include <sys/param.h> |
34 | #include <sys/systm.h> | | 34 | #include <sys/systm.h> |
35 | #include <sys/malloc.h> | | 35 | #include <sys/malloc.h> |
36 | #include <sys/kmem.h> | | 36 | #include <sys/kmem.h> |
37 | #include <sys/queue.h> | | 37 | #include <sys/queue.h> |
38 | #include <sys/kernel.h> | | 38 | #include <sys/kernel.h> |
39 | #include <sys/mbuf.h> | | 39 | #include <sys/mbuf.h> |
40 | #include <sys/protosw.h> | | 40 | #include <sys/protosw.h> |
41 | #include <sys/socket.h> | | 41 | #include <sys/socket.h> |
| @@ -1205,135 +1205,156 @@ xennetback_ifsoftstart_transfer(void *ar | | | @@ -1205,135 +1205,156 @@ xennetback_ifsoftstart_transfer(void *ar |
1205 | * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS() | | 1205 | * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS() |
1206 | * here, as the frontend doesn't notify when adding | | 1206 | * here, as the frontend doesn't notify when adding |
1207 | * requests anyway | | 1207 | * requests anyway |
1208 | */ | | 1208 | */ |
1209 | if (__predict_false( | | 1209 | if (__predict_false( |
1210 | !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) { | | 1210 | !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) { |
1211 | /* ring full */ | | 1211 | /* ring full */ |
1212 | break; | | 1212 | break; |
1213 | } | | 1213 | } |
1214 | } | | 1214 | } |
1215 | splx(s); | | 1215 | splx(s); |
1216 | } | | 1216 | } |
1217 | | | 1217 | |
| | | 1218 | /* |
| | | 1219 | * sighly different from m_dup(); for some reason m_dup() can return |
| | | 1220 | * a chain where the data area can cross a page boundary. |
| | | 1221 | * This doesn't happens with the function below. |
| | | 1222 | */ |
| | | 1223 | static struct mbuf * |
| | | 1224 | xennetback_copymbuf(struct mbuf *m) |
| | | 1225 | { |
| | | 1226 | struct mbuf *new_m; |
| | | 1227 | |
| | | 1228 | MGETHDR(new_m, M_DONTWAIT, MT_DATA); |
| | | 1229 | if (__predict_false(new_m == NULL)) { |
| | | 1230 | return NULL; |
| | | 1231 | } |
| | | 1232 | if (m->m_pkthdr.len > MHLEN) { |
| | | 1233 | MCLGET(new_m, M_DONTWAIT); |
| | | 1234 | if (__predict_false( |
| | | 1235 | (new_m->m_flags & M_EXT) == 0)) { |
| | | 1236 | m_freem(new_m); |
| | | 1237 | return NULL; |
| | | 1238 | } |
| | | 1239 | } |
| | | 1240 | m_copydata(m, 0, m->m_pkthdr.len, |
| | | 1241 | mtod(new_m, void *)); |
| | | 1242 | new_m->m_len = new_m->m_pkthdr.len = |
| | | 1243 | m->m_pkthdr.len; |
| | | 1244 | return new_m; |
| | | 1245 | } |
| | | 1246 | |
| | | 1247 | /* return physical page address and offset of data area of an mbuf */ |
| | | 1248 | static void |
| | | 1249 | xennetback_mbuf_addr(struct mbuf *m, paddr_t *xmit_pa, int *offset) |
| | | 1250 | { |
| | | 1251 | switch (m->m_flags & (M_EXT|M_EXT_CLUSTER)) { |
| | | 1252 | case M_EXT|M_EXT_CLUSTER: |
| | | 1253 | KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID); |
| | | 1254 | *xmit_pa = m->m_ext.ext_paddr; |
| | | 1255 | *offset = m->m_data - m->m_ext.ext_buf; |
| | | 1256 | break; |
| | | 1257 | case 0: |
| | | 1258 | KASSERT(m->m_paddr != M_PADDR_INVALID); |
| | | 1259 | *xmit_pa = m->m_paddr; |
| | | 1260 | *offset = M_BUFOFFSET(m) + |
| | | 1261 | (m->m_data - M_BUFADDR(m)); |
| | | 1262 | break; |
| | | 1263 | default: |
| | | 1264 | if (__predict_false( |
| | | 1265 | !pmap_extract(pmap_kernel(), |
| | | 1266 | (vaddr_t)m->m_data, xmit_pa))) { |
| | | 1267 | panic("xennet_start: no pa"); |
| | | 1268 | } |
| | | 1269 | *offset = 0; |
| | | 1270 | break; |
| | | 1271 | } |
| | | 1272 | *offset += (*xmit_pa & ~PG_FRAME); |
| | | 1273 | *xmit_pa = (*xmit_pa & PG_FRAME); |
| | | 1274 | } |
| | | 1275 | |
1218 | static void | | 1276 | static void |
1219 | xennetback_ifsoftstart_copy(void *arg) | | 1277 | xennetback_ifsoftstart_copy(void *arg) |
1220 | { | | 1278 | { |
1221 | struct xnetback_instance *xneti = arg; | | 1279 | struct xnetback_instance *xneti = arg; |
1222 | struct ifnet *ifp = &xneti->xni_if; | | 1280 | struct ifnet *ifp = &xneti->xni_if; |
1223 | struct mbuf *m, *new_m; | | 1281 | struct mbuf *m, *new_m; |
1224 | paddr_t xmit_pa; | | 1282 | paddr_t xmit_pa; |
1225 | paddr_t xmit_ma; | | 1283 | paddr_t xmit_ma; |
1226 | int i, j; | | 1284 | int i, j; |
1227 | netif_rx_response_t *rxresp; | | 1285 | netif_rx_response_t *rxresp; |
1228 | netif_rx_request_t rxreq; | | 1286 | netif_rx_request_t rxreq; |
1229 | RING_IDX req_prod, resp_prod; | | 1287 | RING_IDX req_prod, resp_prod; |
1230 | int do_event = 0; | | 1288 | int do_event = 0; |
1231 | gnttab_copy_t *gop; | | 1289 | gnttab_copy_t *gop; |
1232 | int id, offset; | | 1290 | int id, offset; |
| | | 1291 | bool abort; |
1233 | | | 1292 | |
1234 | XENPRINTF(("xennetback_ifsoftstart_copy ")); | | 1293 | XENPRINTF(("xennetback_ifsoftstart_copy ")); |
1235 | int s = splnet(); | | 1294 | int s = splnet(); |
1236 | if (__predict_false( | | 1295 | if (__predict_false( |
1237 | (ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) { | | 1296 | (ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) { |
1238 | splx(s); | | 1297 | splx(s); |
1239 | return; | | 1298 | return; |
1240 | } | | 1299 | } |
1241 | | | 1300 | |
1242 | while (!IFQ_IS_EMPTY(&ifp->if_snd)) { | | 1301 | while (!IFQ_IS_EMPTY(&ifp->if_snd)) { |
1243 | XENPRINTF(("pkt\n")); | | 1302 | XENPRINTF(("pkt\n")); |
1244 | req_prod = xneti->xni_rxring.sring->req_prod; | | 1303 | req_prod = xneti->xni_rxring.sring->req_prod; |
1245 | resp_prod = xneti->xni_rxring.rsp_prod_pvt; | | 1304 | resp_prod = xneti->xni_rxring.rsp_prod_pvt; |
1246 | xen_rmb(); | | 1305 | xen_rmb(); |
1247 | | | 1306 | |
1248 | gop = xstart_gop_copy; | | 1307 | gop = xstart_gop_copy; |
| | | 1308 | abort = false; |
1249 | for (i = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) { | | 1309 | for (i = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) { |
1250 | XENPRINTF(("have a packet\n")); | | 1310 | XENPRINTF(("have a packet\n")); |
1251 | IFQ_POLL(&ifp->if_snd, m); | | 1311 | IFQ_POLL(&ifp->if_snd, m); |
1252 | if (__predict_false(m == NULL)) | | 1312 | if (__predict_false(m == NULL)) |
1253 | panic("xennetback_ifstart: IFQ_POLL"); | | 1313 | panic("xennetback_ifstart: IFQ_POLL"); |
1254 | if (__predict_false( | | 1314 | if (__predict_false( |
1255 | req_prod == xneti->xni_rxring.req_cons || | | 1315 | req_prod == xneti->xni_rxring.req_cons || |
1256 | xneti->xni_rxring.req_cons - resp_prod == | | 1316 | xneti->xni_rxring.req_cons - resp_prod == |
1257 | NET_RX_RING_SIZE)) { | | 1317 | NET_RX_RING_SIZE)) { |
1258 | /* out of ring space */ | | 1318 | /* out of ring space */ |
1259 | XENPRINTF(("xennetback_ifstart: ring full " | | 1319 | XENPRINTF(("xennetback_ifstart: ring full " |
1260 | "req_prod 0x%x req_cons 0x%x resp_prod " | | 1320 | "req_prod 0x%x req_cons 0x%x resp_prod " |
1261 | "0x%x\n", | | 1321 | "0x%x\n", |
1262 | req_prod, xneti->xni_rxring.req_cons, | | 1322 | req_prod, xneti->xni_rxring.req_cons, |
1263 | resp_prod)); | | 1323 | resp_prod)); |
1264 | ifp->if_timer = 1; | | 1324 | abort = true; |
1265 | break; | | 1325 | break; |
1266 | } | | 1326 | } |
1267 | if (__predict_false(i == NB_XMIT_PAGES_BATCH)) | | 1327 | if (__predict_false(i == NB_XMIT_PAGES_BATCH)) |
1268 | break; /* we filled the array */ | | 1328 | break; /* we filled the array */ |
1269 | switch (m->m_flags & (M_EXT|M_EXT_CLUSTER)) { | | 1329 | |
1270 | case M_EXT|M_EXT_CLUSTER: | | 1330 | xennetback_mbuf_addr(m, &xmit_pa, &offset); |
1271 | KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID); | | | |
1272 | xmit_pa = m->m_ext.ext_paddr; | | | |
1273 | offset = m->m_data - m->m_ext.ext_buf; | | | |
1274 | break; | | | |
1275 | case 0: | | | |
1276 | KASSERT(m->m_paddr != M_PADDR_INVALID); | | | |
1277 | xmit_pa = m->m_paddr; | | | |
1278 | offset = M_BUFOFFSET(m) + | | | |
1279 | (m->m_data - M_BUFADDR(m)); | | | |
1280 | break; | | | |
1281 | default: | | | |
1282 | if (__predict_false( | | | |
1283 | !pmap_extract(pmap_kernel(), | | | |
1284 | (vaddr_t)m->m_data, &xmit_pa))) { | | | |
1285 | panic("xennet_start: no pa"); | | | |
1286 | } | | | |
1287 | offset = 0; | | | |
1288 | break; | | | |
1289 | } | | | |
1290 | offset += (xmit_pa & ~PG_FRAME); | | | |
1291 | xmit_pa = (xmit_pa & PG_FRAME); | | | |
1292 | if (m->m_pkthdr.len != m->m_len || | | 1331 | if (m->m_pkthdr.len != m->m_len || |
1293 | (offset + m->m_pkthdr.len) > PAGE_SIZE) { | | 1332 | (offset + m->m_pkthdr.len) > PAGE_SIZE) { |
1294 | MGETHDR(new_m, M_DONTWAIT, MT_DATA); | | 1333 | new_m = xennetback_copymbuf(m); |
1295 | if (__predict_false(new_m == NULL)) { | | 1334 | if (__predict_false(new_m == NULL)) { |
1296 | printf("%s: cannot allocate new mbuf\n", | | 1335 | static struct timeval lasttime; |
1297 | ifp->if_xname); | | 1336 | if (ratecheck(&lasttime, &xni_pool_errintvl)) |
| | | 1337 | printf("%s: cannot allocate new mbuf\n", |
| | | 1338 | ifp->if_xname); |
| | | 1339 | abort = 1; |
1298 | break; | | 1340 | break; |
1299 | } | | | |
1300 | if (m->m_pkthdr.len > MHLEN) { | | | |
1301 | MCLGET(new_m, M_DONTWAIT); | | | |
1302 | if (__predict_false( | | | |
1303 | (new_m->m_flags & M_EXT) == 0)) { | | | |
1304 | XENPRINTF(( | | | |
1305 | "%s: no mbuf cluster\n", | | | |
1306 | ifp->if_xname)); | | | |
1307 | m_freem(new_m); | | | |
1308 | break; | | | |
1309 | } | | | |
1310 | xmit_pa = new_m->m_ext.ext_paddr; | | | |
1311 | offset = new_m->m_data - | | | |
1312 | new_m->m_ext.ext_buf; | | | |
1313 | } else { | | 1341 | } else { |
1314 | xmit_pa = new_m->m_paddr; | | 1342 | IFQ_DEQUEUE(&ifp->if_snd, m); |
1315 | offset = M_BUFOFFSET(new_m) + | | 1343 | m_freem(m); |
1316 | (new_m->m_data - M_BUFADDR(new_m)); | | 1344 | m = new_m; |
| | | 1345 | xennetback_mbuf_addr(m, |
| | | 1346 | &xmit_pa, &offset); |
1317 | } | | 1347 | } |
1318 | offset += (xmit_pa & ~PG_FRAME); | | | |
1319 | xmit_pa = (xmit_pa & PG_FRAME); | | | |
1320 | m_copydata(m, 0, m->m_pkthdr.len, | | | |
1321 | mtod(new_m, void *)); | | | |
1322 | new_m->m_len = new_m->m_pkthdr.len = | | | |
1323 | m->m_pkthdr.len; | | | |
1324 | IFQ_DEQUEUE(&ifp->if_snd, m); | | | |
1325 | m_freem(m); | | | |
1326 | m = new_m; | | | |
1327 | } else { | | 1348 | } else { |
1328 | IFQ_DEQUEUE(&ifp->if_snd, m); | | 1349 | IFQ_DEQUEUE(&ifp->if_snd, m); |
1329 | } | | 1350 | } |
1330 | | | 1351 | |
1331 | KASSERT(xmit_pa != POOL_PADDR_INVALID); | | 1352 | KASSERT(xmit_pa != POOL_PADDR_INVALID); |
1332 | KASSERT((offset + m->m_pkthdr.len) <= PAGE_SIZE); | | 1353 | KASSERT((offset + m->m_pkthdr.len) <= PAGE_SIZE); |
1333 | xmit_ma = xpmap_ptom(xmit_pa); | | 1354 | xmit_ma = xpmap_ptom(xmit_pa); |
1334 | /* start filling ring */ | | 1355 | /* start filling ring */ |
1335 | gop->flags = GNTCOPY_dest_gref; | | 1356 | gop->flags = GNTCOPY_dest_gref; |
1336 | gop->source.offset = offset; | | 1357 | gop->source.offset = offset; |
1337 | gop->source.domid = DOMID_SELF; | | 1358 | gop->source.domid = DOMID_SELF; |
1338 | gop->source.u.gmfn = xmit_ma >> PAGE_SHIFT; | | 1359 | gop->source.u.gmfn = xmit_ma >> PAGE_SHIFT; |
1339 | | | 1360 | |
| @@ -1411,29 +1432,30 @@ xennetback_ifsoftstart_copy(void *arg) | | | @@ -1411,29 +1432,30 @@ xennetback_ifsoftstart_copy(void *arg) |
1411 | /* send event */ | | 1432 | /* send event */ |
1412 | if (do_event) { | | 1433 | if (do_event) { |
1413 | xen_rmb(); | | 1434 | xen_rmb(); |
1414 | XENPRINTF(("%s receive event\n", | | 1435 | XENPRINTF(("%s receive event\n", |
1415 | xneti->xni_if.if_xname)); | | 1436 | xneti->xni_if.if_xname)); |
1416 | hypervisor_notify_via_evtchn(xneti->xni_evtchn); | | 1437 | hypervisor_notify_via_evtchn(xneti->xni_evtchn); |
1417 | do_event = 0; | | 1438 | do_event = 0; |
1418 | } | | 1439 | } |
1419 | /* | | 1440 | /* |
1420 | * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS() | | 1441 | * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS() |
1421 | * here, as the frontend doesn't notify when adding | | 1442 | * here, as the frontend doesn't notify when adding |
1422 | * requests anyway | | 1443 | * requests anyway |
1423 | */ | | 1444 | */ |
1424 | if (__predict_false( | | 1445 | if (__predict_false(abort || |
1425 | !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) { | | 1446 | !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) { |
1426 | /* ring full */ | | 1447 | /* ring full */ |
| | | 1448 | ifp->if_timer = 1; |
1427 | break; | | 1449 | break; |
1428 | } | | 1450 | } |
1429 | } | | 1451 | } |
1430 | splx(s); | | 1452 | splx(s); |
1431 | } | | 1453 | } |
1432 | | | 1454 | |
1433 | static void | | 1455 | static void |
1434 | xennetback_ifwatchdog(struct ifnet * ifp) | | 1456 | xennetback_ifwatchdog(struct ifnet * ifp) |
1435 | { | | 1457 | { |
1436 | /* | | 1458 | /* |
1437 | * We can get to the following condition: transmit stalls because the | | 1459 | * We can get to the following condition: transmit stalls because the |
1438 | * ring is full when the ifq is full too. | | 1460 | * ring is full when the ifq is full too. |
1439 | * | | 1461 | * |