1 /************************************************************************** 2 * 3 * Copyright (c) 2007, Kip Macy kmacy@freebsd.org 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. The name of Kip Macy nor the names of other 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 ***************************************************************************/ 29 30 #ifndef _MVEC_H_ 31 #define _MVEC_H_ 32 33 #include <sys/mbuf.h> 34 35 #define mtomv(m) ((struct mbuf_vec *)((m)->m_pktdat)) 36 37 #define M_IOVEC 0x100000 /* mbuf immediate data area is used for cluster ptrs */ 38 #define MBUF_IOV_TYPE_MASK ((1<<3)-1) 39 #define mbuf_vec_set_type(mv, i, type) \ 40 (mv)->mv_vec[(i)].mi_flags = (((mv)->mv_vec[(i)].mi_flags \ 41 & ~MBUF_IOV_TYPE_MASK) | type) 42 43 #define mbuf_vec_get_type(mv, i) \ 44 ((mv)->mv_vec[(i)].mi_flags & MBUF_IOV_TYPE_MASK) 45 46 47 struct mbuf_iovec { 48 uint16_t mi_flags; /* per-cluster flags */ 49 uint16_t mi_len; /* length of cluster */ 50 uint32_t mi_offset; /* data offsets into cluster */ 51 uint8_t *mi_base; /* pointers to cluster */ 52 volatile uint32_t *mi_refcnt; /* refcnt for cluster*/ 53 #ifdef __i386__ 54 void *mi_args; /* for sf_buf */ 55 #endif 56 }; 57 58 #define MAX_MBUF_IOV ((MHLEN-8)/sizeof(struct mbuf_iovec)) 59 struct mbuf_vec { 60 uint16_t mv_first; /* first valid cluster */ 61 uint16_t mv_count; /* # of clusters */ 62 uint32_t mv_flags; /* flags for iovec */ 63 struct mbuf_iovec mv_vec[MAX_MBUF_IOV]; 64 }; 65 66 int _m_explode(struct mbuf *); 67 int _m_collapse(struct mbuf *, int maxbufs, struct mbuf **); 68 void mb_free_vec(struct mbuf *m); 69 70 static inline void 71 m_iovinit(struct mbuf *m) 72 { 73 struct mbuf_vec *mv = mtomv(m); 74 75 mv->mv_first = mv->mv_count = 0; 76 m->m_pkthdr.len = m->m_len = 0; 77 m->m_flags |= M_IOVEC; 78 } 79 80 static inline void 81 m_iovappend(struct mbuf *m, uint8_t *cl, int size, int len, int offset) 82 { 83 struct mbuf_vec *mv = mtomv(m); 84 struct mbuf_iovec *iov; 85 int idx = mv->mv_first + mv->mv_count; 86 87 if ((m->m_flags & M_EXT) != 0) 88 panic("invalid flags in %s", __func__); 89 90 if (mv->mv_count == 0) 91 m->m_data = cl + offset; 92 93 iov = &mv->mv_vec[idx]; 94 iov->mi_base = cl; 95 iov->mi_len = len; 96 iov->mi_offset = offset; 97 m->m_pkthdr.len += len; 98 m->m_len += len; 99 mv->mv_count++; 100 } 101 102 static inline int 103 m_explode(struct mbuf *m) 104 { 105 if ((m->m_flags & M_IOVEC) == 0) 106 return (0); 107 108 return _m_explode(m); 109 } 110 111 static inline int 112 m_collapse(struct mbuf *m, int maxbufs, struct mbuf **mnew) 113 { 114 #if (!defined(__sparc64__) && !defined(__sun4v__)) 115 if (m->m_next == NULL) 116 #endif 117 { 118 *mnew = m; 119 return (0); 120 } 121 return _m_collapse(m, maxbufs, mnew); 122 } 123 124 static inline struct mbuf * 125 m_free_vec(struct mbuf *m) 126 { 127 struct mbuf *n = NULL; 128 129 MFREE(m, n); 130 return (n); 131 } 132 133 static inline void 134 m_freem_vec(struct mbuf *m) 135 { 136 while (m != NULL) 137 m = m_free_vec(m); 138 } 139 140 #if (!defined(__sparc64__) && !defined(__sun4v__)) 141 int 142 bus_dmamap_load_mvec_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, 143 bus_dma_segment_t *segs, int *nsegs, int flags); 144 145 #else 146 #define bus_dmamap_load_mvec_sg bus_dmamap_load_mbuf_sg 147 #endif 148 149 #endif 150