diff options
author | jhb <jhb@FreeBSD.org> | 2016-12-05 23:46:21 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2016-12-05 23:46:21 +0000 |
commit | 6bc9fd0c59bb8d19504cbebf4c81b789a40e80d2 (patch) | |
tree | a9b8bdc7f1e019ba2e6ce92b242b1fa498d9ecf9 | |
parent | 99bce69d5abc80aa1535b2714f5f2798435f0a60 (diff) | |
download | FreeBSD-src-6bc9fd0c59bb8d19504cbebf4c81b789a40e80d2.zip FreeBSD-src-6bc9fd0c59bb8d19504cbebf4c81b789a40e80d2.tar.gz |
MFC 307876:
cxgbe(4): Fix bug in the calculation of the number of physically
contiguous regions in an mbuf chain.
If the payload of an mbuf ends at a page boundary count_mbuf_nsegs would
incorrectly consider the next mbuf's payload physically contiguous based
solely on a KVA comparison.
-rw-r--r-- | sys/dev/cxgbe/t4_sge.c | 33 |
1 files changed, 8 insertions, 25 deletions
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index dd5eba1..29e15a0 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -2101,24 +2101,6 @@ m_advance(struct mbuf **pm, int *poffset, int len) return ((void *)p); } -static inline int -same_paddr(char *a, char *b) -{ - - if (a == b) - return (1); - else if (a != NULL && b != NULL) { - vm_offset_t x = (vm_offset_t)a; - vm_offset_t y = (vm_offset_t)b; - - if ((x & PAGE_MASK) == (y & PAGE_MASK) && - pmap_kextract(x) == pmap_kextract(y)) - return (1); - } - - return (0); -} - /* * Can deal with empty mbufs in the chain that have m_len = 0, but the chain * must have at least one mbuf that's not empty. @@ -2126,24 +2108,25 @@ same_paddr(char *a, char *b) static inline int count_mbuf_nsegs(struct mbuf *m) { - char *prev_end, *start; + vm_paddr_t lastb, next; + vm_offset_t va; int len, nsegs; MPASS(m != NULL); nsegs = 0; - prev_end = NULL; + lastb = 0; for (; m; m = m->m_next) { len = m->m_len; if (__predict_false(len == 0)) continue; - start = mtod(m, char *); - - nsegs += sglist_count(start, len); - if (same_paddr(prev_end, start)) + va = mtod(m, vm_offset_t); + next = pmap_kextract(va); + nsegs += sglist_count(m->m_data, len); + if (lastb + 1 == next) nsegs--; - prev_end = start + len; + lastb = pmap_kextract(va + len - 1); } MPASS(nsegs > 0); |