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 ***************************************************************************/
34 #include <machine/bus.h>
36 int cxgb_cache_init(void);
38 void cxgb_cache_flush(void);
40 caddr_t cxgb_cache_get(uma_zone_t zone);
42 void cxgb_cache_put(uma_zone_t zone, void *cl);
44 void cxgb_cache_refill(void);
46 extern int cxgb_cached_allocations;
47 extern int cxgb_cached;
48 extern int cxgb_ext_freed;
49 extern int cxgb_mbufs_outstanding;
50 extern int cxgb_pack_outstanding;
52 #define mtomv(m) ((struct mbuf_vec *)((m)->m_pktdat))
53 #define M_IOVEC 0x100000 /* mbuf immediate data area is used for cluster ptrs */
54 #define M_DDP 0x200000 /* direct data placement mbuf */
55 #define EXT_PHYS 10 /* physical/bus address */
58 * duplication from mbuf.h - can't use directly because
62 caddr_t ext_buf; /* start of buffer */
63 void (*ext_free) /* free routine if not the usual */
65 #if __FreeBSD_version >= 800016
66 void *ext_arg1; /* optional argument pointer */
67 void *ext_arg2; /* optional argument pointer */
69 void *ext_args; /* optional argument pointer */
71 u_int ext_size; /* size of buffer, for ext_free */
72 volatile u_int *ref_cnt; /* pointer to ref count info */
73 int ext_type; /* type of external storage */
81 #define EXT_JMPIOVEC 10
83 #define m_cur_offset m_ext.ext_size /* override to provide ddp offset */
84 #define m_seq m_pkthdr.csum_data /* stored sequence */
85 #define m_ddp_gl m_ext.ext_buf /* ddp list */
86 #define m_ddp_flags m_pkthdr.csum_flags /* ddp flags */
87 #define m_ulp_mode m_pkthdr.tso_segsz /* upper level protocol */
89 extern uma_zone_t zone_miovec;
96 uint16_t mi_tso_segsz;
97 uint16_t mi_ether_vtag;
98 uint16_t mi_rss_hash; /* this can be shrunk down if something comes
99 * along that needs 1 byte
102 struct mbuf *mi_mbuf; /* need to be able to handle the @#$@@#%$ing packet zone */
103 #define mi_size mi_ext.ext_size
104 #define mi_base mi_ext.ext_buf
105 #define mi_args mi_ext.ext_args
106 #define mi_size mi_ext.ext_size
107 #define mi_size mi_ext.ext_size
108 #define mi_refcnt mi_ext.ref_cnt
109 #define mi_ext_free mi_ext.ext_free
110 #define mi_ext_flags mi_ext.ext_flags
111 #define mi_type mi_ext.ext_type
114 #define MIOVBYTES 512
115 #define MAX_MBUF_IOV ((MHLEN-8)/sizeof(struct mbuf_iovec))
116 #define MAX_MIOVEC_IOV ((MIOVBYTES-sizeof(struct m_hdr)-sizeof(struct pkthdr)-8)/sizeof(struct mbuf_iovec))
117 #define MAX_CL_IOV ((MCLBYTES-sizeof(struct m_hdr)-sizeof(struct pkthdr)-8)/sizeof(struct mbuf_iovec))
118 #define MAX_PAGE_IOV ((MJUMPAGESIZE-sizeof(struct m_hdr)-sizeof(struct pkthdr)-8)/sizeof(struct mbuf_iovec))
121 uint16_t mv_first; /* first valid cluster */
122 uint16_t mv_count; /* # of clusters */
123 uint32_t mv_flags; /* flags for iovec */
124 struct mbuf_iovec mv_vec[0]; /* depends on whether or not this is in a cluster or an mbuf */
127 void mi_deinit(void);
129 int _m_explode(struct mbuf *);
130 void mb_free_vec(struct mbuf *m);
133 m_iovinit(struct mbuf *m)
135 struct mbuf_vec *mv = mtomv(m);
137 mv->mv_first = mv->mv_count = 0;
138 m->m_pkthdr.len = m->m_len = 0;
139 m->m_flags |= M_IOVEC;
143 m_iovappend(struct mbuf *m, uint8_t *cl, int size, int len, caddr_t data, volatile uint32_t *ref)
145 struct mbuf_vec *mv = mtomv(m);
146 struct mbuf_iovec *iov;
147 int idx = mv->mv_first + mv->mv_count;
149 KASSERT(idx <= MAX_MBUF_IOV, ("tried to append too many clusters to mbuf iovec"));
150 if ((m->m_flags & M_EXT) != 0)
151 panic("invalid flags in %s", __func__);
153 if (mv->mv_count == 0)
156 iov = &mv->mv_vec[idx];
157 iov->mi_type = m_gettype(size);
161 iov->mi_refcnt = ref;
162 m->m_pkthdr.len += len;
168 m_explode(struct mbuf *m)
170 if ((m->m_flags & M_IOVEC) == 0)
173 return _m_explode(m);
177 busdma_map_mbuf_fast(struct mbuf *m, bus_dma_segment_t *seg)
179 seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
180 seg->ds_len = m->m_len;
183 int busdma_map_sg_collapse(struct mbuf **m, bus_dma_segment_t *segs, int *nsegs);
184 int busdma_map_sg_vec(struct mbuf **m, struct mbuf **mp, bus_dma_segment_t *segs, int count);
185 static __inline int busdma_map_sgl(bus_dma_segment_t *vsegs, bus_dma_segment_t *segs, int count)
188 segs->ds_addr = pmap_kextract((vm_offset_t)vsegs->ds_addr);
189 segs->ds_len = vsegs->ds_len;
196 struct mbuf *mi_collapse_mbuf(struct mbuf_iovec *mi, struct mbuf *m);
197 void *mcl_alloc(int seg_count, int *type);
199 void mb_free_ext_fast(struct mbuf_iovec *mi, int type, int idx);
202 mi_collapse_sge(struct mbuf_iovec *mi, bus_dma_segment_t *seg)
205 mi->mi_base = (caddr_t)seg->ds_addr;
206 mi->mi_len = seg->ds_len;
208 mi->mi_type = EXT_PHYS;
209 mi->mi_refcnt = NULL;
213 m_free_iovec(struct mbuf *m, int type)
217 struct mbuf_iovec *mi;
221 for (i = 0; i < mv->mv_count; i++, mi++) {
222 DPRINTF("freeing buf=%d of %d\n", i, mv->mv_count);
223 mb_free_ext_fast(mi, mi->mi_type, i);
227 uma_zfree(zone_miovec, m);
230 cxgb_cache_put(zone_clust, m);
233 cxgb_cache_put(zone_jumbop, m);
236 panic("unexpected type %d\n", type);
241 m_freem_iovec(struct mbuf_iovec *mi)
243 struct mbuf *m = (struct mbuf *)mi->mi_base;
245 switch (mi->mi_type) {
248 KASSERT(m->m_pkthdr.len > PIO_LEN, ("freeing PIO buf"));
250 KASSERT((mi->mi_flags & M_NOFREE) == 0, ("no free set on mbuf"));
251 KASSERT(m->m_next == NULL, ("freeing chain"));
252 cxgb_mbufs_outstanding--;
256 cxgb_pack_outstanding--;
262 m = (struct mbuf *)mi->mi_base;
263 m_free_iovec(m, mi->mi_type);
274 mb_free_ext_fast(mi, mi->mi_type, -1);
277 panic("unknown miov type: %d\n", mi->mi_type);
282 static __inline uma_zone_t
283 m_getzonefromtype(int type)
294 #if MJUMPAGESIZE != MCLBYTES
311 panic("%s: invalid cluster type %d", __func__, type);
317 m_getsizefromtype(int type)
329 #if MJUMPAGESIZE != MCLBYTES
341 panic("%s: unrecognized cluster type %d", __func__, type);
346 void dump_mi(struct mbuf_iovec *mi);
348 #endif /* _MVEC_H_ */