1 /**************************************************************************
3 * Copyright (c) 2007, Kip Macy kmacy@freebsd.org
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
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.
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.
30 ***************************************************************************/
35 #define mtomv(m) ((struct mbuf_vec *)((m)->m_pktdat))
37 #define M_IOVEC 0x100000 /* mbuf immediate data area is used for cluster ptrs */
39 #define MBUF_IOV_TYPE_MASK ((1<<3)-1)
40 #define mbuf_vec_set_type(mv, i, type) \
41 (mv)->mv_vec[(i)].mi_flags = (((mv)->mv_vec[(i)].mi_flags \
42 & ~MBUF_IOV_TYPE_MASK) | type)
44 #define mbuf_vec_get_type(mv, i) \
45 ((mv)->mv_vec[(i)].mi_flags & MBUF_IOV_TYPE_MASK)
49 uint16_t mi_flags; /* per-cluster flags */
50 uint16_t mi_len; /* length of cluster */
51 uint32_t mi_offset; /* data offsets into cluster */
52 caddr_t mi_base; /* pointers to cluster */
53 volatile uint32_t *mi_refcnt; /* refcnt for cluster*/
55 void *mi_args; /* for sf_buf */
59 #define MAX_MBUF_IOV ((MHLEN-8)/sizeof(struct mbuf_iovec))
61 uint16_t mv_first; /* first valid cluster */
62 uint16_t mv_count; /* # of clusters */
63 uint32_t mv_flags; /* flags for iovec */
64 struct mbuf_iovec mv_vec[MAX_MBUF_IOV];
79 #if MJUMPAGESIZE != MCLBYTES
91 panic("%s: m_getjcl: invalid cluster size", __func__);
98 m_cljset(struct mbuf *m, void *cl, int type)
108 #if MJUMPAGESIZE != MCLBYTES
123 panic("unknown cluster type");
127 m->m_data = m->m_ext.ext_buf = cl;
128 m->m_ext.ext_free = m->m_ext.ext_args = NULL;
129 m->m_ext.ext_size = size;
130 m->m_ext.ext_type = type;
131 m->m_ext.ref_cnt = uma_find_refcnt(zone, cl);
132 if (*m->m_ext.ref_cnt == 0)
133 *m->m_ext.ref_cnt = 1;
140 int _m_explode(struct mbuf *);
141 int _m_collapse(struct mbuf *, int maxbufs, struct mbuf **);
142 void mb_free_vec(struct mbuf *m);
145 m_iovinit(struct mbuf *m)
147 struct mbuf_vec *mv = mtomv(m);
149 mv->mv_first = mv->mv_count = 0;
150 m->m_pkthdr.len = m->m_len = 0;
151 m->m_flags |= M_IOVEC;
155 m_iovappend(struct mbuf *m, caddr_t cl, int size, int len, int offset)
157 struct mbuf_vec *mv = mtomv(m);
158 struct mbuf_iovec *iov;
159 int idx = mv->mv_first + mv->mv_count;
161 KASSERT(idx <= MAX_MBUF_IOV, ("tried to append too many clusters to mbuf iovec"));
162 if ((m->m_flags & M_EXT) != 0)
163 panic("invalid flags in %s", __func__);
165 if (mv->mv_count == 0)
166 m->m_data = (caddr_t)(cl + offset);
168 iov = &mv->mv_vec[idx];
169 iov->mi_flags = m_gettype(size);
172 iov->mi_offset = offset;
173 m->m_pkthdr.len += len;
179 m_explode(struct mbuf *m)
181 if ((m->m_flags & M_IOVEC) == 0)
184 return _m_explode(m);
188 m_collapse(struct mbuf *m, int maxbufs, struct mbuf **mnew)
190 #if (!defined(__sparc64__) && !defined(__sun4v__))
191 if (m->m_next == NULL)
197 return _m_collapse(m, maxbufs, mnew);
200 static __inline struct mbuf *
201 m_free_vec(struct mbuf *m)
203 struct mbuf *n = m->m_next;
205 if (m->m_flags & M_IOVEC)
207 else if (m->m_flags & M_EXT)
210 uma_zfree(zone_mbuf, m);
215 m_freem_vec(struct mbuf *m)
221 static __inline uma_zone_t
222 m_getzonefromtype(int type)
233 #if MJUMPAGESIZE != MCLBYTES
244 #ifndef PACKET_ZONE_DISABLED
250 panic("%s: invalid cluster type %d", __func__, type);
255 #if (!defined(__sparc64__) && !defined(__sun4v__))
257 bus_dmamap_load_mvec_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
258 bus_dma_segment_t *segs, int *nsegs, int flags);
261 #define bus_dmamap_load_mvec_sg bus_dmamap_load_mbuf_sg