/************************************************************************** * * Copyright (c) 2007, Kip Macy kmacy@freebsd.org * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. The name of Kip Macy nor the names of other * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/cxgb/sys/mvec.h,v 1.5 2007/05/25 16:42:25 kmacy Exp $ * ***************************************************************************/ #ifndef _MVEC_H_ #define _MVEC_H_ #include #define mtomv(m) ((struct mbuf_vec *)((m)->m_pktdat)) #define M_IOVEC 0x100000 /* mbuf immediate data area is used for cluster ptrs */ #define MBUF_IOV_TYPE_MASK ((1<<3)-1) #define mbuf_vec_set_type(mv, i, type) \ (mv)->mv_vec[(i)].mi_flags = (((mv)->mv_vec[(i)].mi_flags \ & ~MBUF_IOV_TYPE_MASK) | type) #define mbuf_vec_get_type(mv, i) \ ((mv)->mv_vec[(i)].mi_flags & MBUF_IOV_TYPE_MASK) struct mbuf_iovec { uint16_t mi_flags; /* per-cluster flags */ uint16_t mi_len; /* length of cluster */ uint32_t mi_offset; /* data offsets into cluster */ uint8_t *mi_base; /* pointers to cluster */ volatile uint32_t *mi_refcnt; /* refcnt for cluster*/ #ifdef __i386__ void *mi_args; /* for sf_buf */ #endif }; #define MAX_MBUF_IOV ((MHLEN-8)/sizeof(struct mbuf_iovec)) struct mbuf_vec { uint16_t mv_first; /* first valid cluster */ uint16_t mv_count; /* # of clusters */ uint32_t mv_flags; /* flags for iovec */ struct mbuf_iovec mv_vec[MAX_MBUF_IOV]; }; int _m_explode(struct mbuf *); int _m_collapse(struct mbuf *, int maxbufs, struct mbuf **); void mb_free_vec(struct mbuf *m); static inline void m_iovinit(struct mbuf *m) { struct mbuf_vec *mv = mtomv(m); mv->mv_first = mv->mv_count = 0; m->m_pkthdr.len = m->m_len = 0; m->m_flags |= M_IOVEC; } static inline void m_iovappend(struct mbuf *m, uint8_t *cl, int size, int len, int offset) { struct mbuf_vec *mv = mtomv(m); struct mbuf_iovec *iov; int idx = mv->mv_first + mv->mv_count; #ifdef __FreeBSD__ KASSERT(idx <= MAX_MBUF_IOV, ("tried to append too many clusters to mbuf iovec")); #endif if ((m->m_flags & M_EXT) != 0) panic("invalid flags in %s", __func__); if (mv->mv_count == 0) m->m_data = cl + offset; iov = &mv->mv_vec[idx]; #ifdef __FreeBSD__ iov->mi_flags = m_gettype(size); #endif iov->mi_base = cl; iov->mi_len = len; iov->mi_offset = offset; m->m_pkthdr.len += len; m->m_len += len; mv->mv_count++; } static inline int m_explode(struct mbuf *m) { if ((m->m_flags & M_IOVEC) == 0) return (0); return _m_explode(m); } static inline int m_collapse(struct mbuf *m, int maxbufs, struct mbuf **mnew) { #if (!defined(__sparc64__) && !defined(__sun4v__)) if (m->m_next == NULL) #endif { *mnew = m; return (0); } return _m_collapse(m, maxbufs, mnew); } static inline struct mbuf * m_free_vec(struct mbuf *m) { #ifdef __FreeBSD__ struct mbuf *n = m->m_next; if (m->m_flags & M_IOVEC) mb_free_vec(m); else if (m->m_flags & M_EXT) mb_free_ext(m); else uma_zfree(zone_mbuf, m); #endif #ifdef __NetBSD__ struct mbuf *n = NULL; MFREE(m, n); #endif return (n); } static inline void m_freem_vec(struct mbuf *m) { while (m != NULL) m = m_free_vec(m); } #ifdef __FreeBSD__ static inline uma_zone_t m_getzonefromtype(int type) { uma_zone_t zone; switch (type) { case EXT_MBUF: zone = zone_mbuf; break; case EXT_CLUSTER: zone = zone_clust; break; #if MJUMPAGESIZE != MCLBYTES case EXT_JUMBOP: zone = zone_jumbop; break; #endif case EXT_JUMBO9: zone = zone_jumbo9; break; case EXT_JUMBO16: zone = zone_jumbo16; break; #ifndef PACKET_ZONE_DISABLED case EXT_PACKET: zone = zone_pack; break; #endif default: panic("%s: invalid cluster type %d", __func__, type); } return (zone); } #endif #if (!defined(__sparc64__) && !defined(__sun4v__)) int bus_dmamap_load_mvec_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags); #else #define bus_dmamap_load_mvec_sg bus_dmamap_load_mbuf_sg #endif #endif