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
m_iovinit(struct mbuf * m)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
m_iovappend(struct mbuf * m,uint8_t * cl,int size,int len,int offset)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
m_explode(struct mbuf * m)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
m_collapse(struct mbuf * m,int maxbufs,struct mbuf ** mnew)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 *
m_free_vec(struct mbuf * m)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
m_freem_vec(struct mbuf * m)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