summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Stormont <astormont@racktopsystems.com>2020-05-09 14:25:12 +0100
committerRobert Mustacchi <rm@fingolfin.org>2020-07-23 07:31:25 -0700
commit8fa80b6906806016ca3449e9e20ce5f6b49653dc (patch)
tree0d88942de953c8399db036008aad6ce3b6e8177c
parentaa2a44afcbfb9d08096ea5af01f0bb30d4b7f9a6 (diff)
downloadillumos-joyent-8fa80b6906806016ca3449e9e20ce5f6b49653dc.tar.gz
12712 xnf calls ddi_dma_nextcookie too many times and panics the system
Reviewed by: Paul Winder <pwinder@racktopsystems.com> Reviewed by: Garrett D'Amore <gdamore@racktopsystems.com> Reviewed by: Andy Fiddaman <andy@omniosce.org> Reviewed by: Patrick Mooney <pmooney@pfmooney.com> Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r--usr/src/uts/common/xen/io/xnf.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/usr/src/uts/common/xen/io/xnf.c b/usr/src/uts/common/xen/io/xnf.c
index ebed9c5f7e..2a53cc23e2 100644
--- a/usr/src/uts/common/xen/io/xnf.c
+++ b/usr/src/uts/common/xen/io/xnf.c
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2014, 2017 by Delphix. All rights reserved.
+ * Copyright 2020 RackTop Systems, Inc.
*/
/*
@@ -1779,8 +1780,7 @@ xnf_mblk_map(xnf_t *xnfp, mblk_t *mp, int *countp)
for (mblk_t *ml = mp; ml != NULL; ml = ml->b_cont) {
ddi_dma_handle_t dma_handle;
- ddi_dma_cookie_t dma_cookie;
- uint_t ncookies;
+ const ddi_dma_cookie_t *dma_cookie, *dma_cookie_prev;
xnf_txbuf_t *txp;
if (MBLKL(ml) == 0)
@@ -1804,8 +1804,7 @@ xnf_mblk_map(xnf_t *xnfp, mblk_t *mp, int *countp)
int ret = ddi_dma_addr_bind_handle(dma_handle,
NULL, (char *)ml->b_rptr, MBLKL(ml),
DDI_DMA_WRITE | DDI_DMA_STREAMING,
- DDI_DMA_DONTWAIT, 0, &dma_cookie,
- &ncookies);
+ DDI_DMA_DONTWAIT, 0, NULL, NULL);
if (ret != DDI_DMA_MAPPED) {
if (ret != DDI_DMA_NORESOURCES) {
dev_err(xnfp->xnf_devinfo, CE_WARN,
@@ -1816,15 +1815,16 @@ xnf_mblk_map(xnf_t *xnfp, mblk_t *mp, int *countp)
}
txp->tx_handle_bound = B_TRUE;
- ASSERT(ncookies > 0);
- for (int i = 0; i < ncookies; i++) {
+ dma_cookie_prev = NULL;
+ while ((dma_cookie = ddi_dma_cookie_iter(dma_handle,
+ dma_cookie_prev)) != NULL) {
if (nsegs == XEN_MAX_TX_DATA_PAGES) {
dev_err(xnfp->xnf_devinfo, CE_WARN,
"xnf_dmamap_alloc() failed: "
"too many segments");
goto error;
}
- if (i > 0) {
+ if (dma_cookie_prev != NULL) {
txp = xnf_data_txbuf_alloc(xnfp);
ASSERT(tail != NULL);
TXBUF_SETNEXT(tail, txp);
@@ -1832,7 +1832,7 @@ xnf_mblk_map(xnf_t *xnfp, mblk_t *mp, int *countp)
}
txp->tx_mfn =
- xnf_btop(pa_to_ma(dma_cookie.dmac_laddress));
+ xnf_btop(pa_to_ma(dma_cookie->dmac_laddress));
txp->tx_txreq.gref = xnf_gref_get(xnfp);
if (txp->tx_txreq.gref == INVALID_GRANT_REF) {
dev_err(xnfp->xnf_devinfo, CE_WARN,
@@ -1843,16 +1843,17 @@ xnf_mblk_map(xnf_t *xnfp, mblk_t *mp, int *countp)
gnttab_grant_foreign_access_ref(txp->tx_txreq.gref,
oeid, txp->tx_mfn, 1);
txp->tx_txreq.offset =
- dma_cookie.dmac_laddress & PAGEOFFSET;
- txp->tx_txreq.size = dma_cookie.dmac_size;
+ dma_cookie->dmac_laddress & PAGEOFFSET;
+ txp->tx_txreq.size = dma_cookie->dmac_size;
txp->tx_txreq.flags = 0;
- ddi_dma_nextcookie(dma_handle, &dma_cookie);
nsegs++;
if (tail != NULL)
tail->tx_txreq.flags = NETTXF_more_data;
tail = txp;
+
+ dma_cookie_prev = dma_cookie;
}
}