]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/cxgb/sys/mvec.h
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / cxgb / sys / mvec.h
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  * $FreeBSD$
29  *
30  ***************************************************************************/
31
32 #ifndef _MVEC_H_
33 #define _MVEC_H_
34 #include <machine/bus.h>
35
36 int cxgb_cache_init(void);
37
38 void cxgb_cache_flush(void);
39
40 caddr_t cxgb_cache_get(uma_zone_t zone);
41
42 void cxgb_cache_put(uma_zone_t zone, void *cl);
43
44 void cxgb_cache_refill(void);
45
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;
51
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  */
56
57 /*
58  * duplication from mbuf.h - can't use directly because
59  * m_ext is a define
60  */
61 struct m_ext_ {
62         caddr_t          ext_buf;       /* start of buffer */
63         void            (*ext_free)     /* free routine if not the usual */
64                             (void *, void *);
65 #if __FreeBSD_version >= 800016
66         void            *ext_arg1;      /* optional argument pointer */
67         void            *ext_arg2;      /* optional argument pointer */
68 #else
69         void            *ext_args;      /* optional argument pointer */
70 #endif
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 */
74 };
75
76 #define MT_IOVEC        9
77 #define MT_CLIOVEC      10
78
79 #define EXT_IOVEC       8
80 #define EXT_CLIOVEC     9
81 #define EXT_JMPIOVEC    10
82
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 */
88
89 extern uma_zone_t zone_miovec;
90
91 struct mbuf_iovec {
92         struct m_ext_ mi_ext;
93         uint32_t      mi_flags;
94         uint32_t      mi_len;
95         caddr_t       mi_data;
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
100                                       */
101         uint16_t     mi_pad;
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
112 };
113
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))
119
120 struct mbuf_vec {
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 */
125 };
126 void mi_init(void);
127 void mi_deinit(void);
128
129 int _m_explode(struct mbuf *);
130 void mb_free_vec(struct mbuf *m);
131
132 static __inline void 
133 m_iovinit(struct mbuf *m) 
134
135         struct mbuf_vec *mv = mtomv(m); 
136
137         mv->mv_first = mv->mv_count = 0;
138         m->m_pkthdr.len = m->m_len = 0;
139         m->m_flags |= M_IOVEC; 
140
141  
142 static __inline void 
143 m_iovappend(struct mbuf *m, uint8_t *cl, int size, int len, caddr_t data, volatile uint32_t *ref)
144
145         struct mbuf_vec *mv = mtomv(m);
146         struct mbuf_iovec *iov;
147         int idx = mv->mv_first + mv->mv_count; 
148
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__); 
152
153         if (mv->mv_count == 0)
154                 m->m_data = data;
155
156         iov = &mv->mv_vec[idx];
157         iov->mi_type = m_gettype(size); 
158         iov->mi_base = cl; 
159         iov->mi_len = len; 
160         iov->mi_data = data;
161         iov->mi_refcnt = ref;
162         m->m_pkthdr.len += len;
163         m->m_len += len;
164         mv->mv_count++;
165
166
167 static __inline int
168 m_explode(struct mbuf *m)
169 {
170         if ((m->m_flags & M_IOVEC) == 0)
171                 return (0);
172
173         return _m_explode(m); 
174
175
176 static __inline void
177 busdma_map_mbuf_fast(struct mbuf *m, bus_dma_segment_t *seg)
178 {
179         seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
180         seg->ds_len = m->m_len;
181 }
182
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) 
186 {
187         while (count--) {
188                 segs->ds_addr = pmap_kextract((vm_offset_t)vsegs->ds_addr);
189                 segs->ds_len = vsegs->ds_len;
190                 segs++;
191                 vsegs++;
192         }
193         return (0);
194 }
195
196 struct mbuf *mi_collapse_mbuf(struct mbuf_iovec *mi, struct mbuf *m);
197 void *mcl_alloc(int seg_count, int *type);
198
199 void mb_free_ext_fast(struct mbuf_iovec *mi, int type, int idx);
200
201 static __inline void
202 mi_collapse_sge(struct mbuf_iovec *mi, bus_dma_segment_t *seg)
203 {
204         mi->mi_flags = 0;
205         mi->mi_base = (caddr_t)seg->ds_addr;
206         mi->mi_len = seg->ds_len;
207         mi->mi_size = 0;
208         mi->mi_type = EXT_PHYS;
209         mi->mi_refcnt = NULL;
210 }
211
212 static __inline void
213 m_free_iovec(struct mbuf *m, int type)
214 {
215         int i;
216         struct mbuf_vec *mv;
217         struct mbuf_iovec *mi;
218   
219         mv = mtomv(m);
220         mi = mv->mv_vec;
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);
224         }
225         switch (type) {
226         case EXT_IOVEC:
227                 uma_zfree(zone_miovec, m);
228                 break;
229         case EXT_CLIOVEC:
230                 cxgb_cache_put(zone_clust, m);
231                 break;
232         case EXT_JMPIOVEC:
233                 cxgb_cache_put(zone_jumbop, m);
234                 break;          
235         default:
236                 panic("unexpected type %d\n", type);
237         }
238 }
239
240 static __inline void
241 m_freem_iovec(struct mbuf_iovec *mi)
242 {
243         struct mbuf *m = (struct mbuf *)mi->mi_base;
244
245         switch (mi->mi_type) {
246         case EXT_MBUF:
247 #ifdef PIO_LEN          
248                 KASSERT(m->m_pkthdr.len > PIO_LEN, ("freeing PIO buf"));
249 #endif
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--;
253                 m_free_fast(m);
254                 break;
255         case EXT_PACKET:
256                 cxgb_pack_outstanding--;
257                 m_free(mi->mi_mbuf);
258                 break;
259         case EXT_IOVEC:
260         case EXT_CLIOVEC:
261         case EXT_JMPIOVEC:
262                 m = (struct mbuf *)mi->mi_base;
263                 m_free_iovec(m, mi->mi_type);
264                 break;
265         case EXT_CLUSTER:
266         case EXT_JUMBOP:
267         case EXT_JUMBO9:
268         case EXT_JUMBO16:
269         case EXT_SFBUF:
270         case EXT_NET_DRV:
271         case EXT_MOD_TYPE:
272         case EXT_DISPOSABLE:
273         case EXT_EXTREF:
274                 mb_free_ext_fast(mi, mi->mi_type, -1);
275                 break;
276         default:
277                 panic("unknown miov type: %d\n", mi->mi_type);
278                 break;
279         }
280 }
281
282 static __inline uma_zone_t
283 m_getzonefromtype(int type)
284 {
285         uma_zone_t zone;
286         
287         switch (type) {
288         case EXT_MBUF:
289                 zone = zone_mbuf;
290                 break;
291         case EXT_CLUSTER:
292                 zone = zone_clust;
293                 break;
294 #if MJUMPAGESIZE != MCLBYTES
295         case EXT_JUMBOP:
296                 zone = zone_jumbop;
297                 break;
298 #endif
299         case EXT_JUMBO9:
300                 zone = zone_jumbo9;
301                 break;
302         case EXT_JUMBO16:
303                 zone = zone_jumbo16;
304                 break;
305 #ifdef PACKET_ZONE              
306         case EXT_PACKET:
307                 zone = zone_pack;
308                 break;
309 #endif          
310         default:
311                 panic("%s: invalid cluster type %d", __func__, type);
312         }
313         return (zone);
314 }
315
316 static __inline int
317 m_getsizefromtype(int type)
318 {
319         int size;
320         
321         switch (type) {
322         case EXT_MBUF:
323                 size = MSIZE;
324                 break;
325         case EXT_CLUSTER:
326         case EXT_PACKET:                
327                 size = MCLBYTES;
328                 break;
329 #if MJUMPAGESIZE != MCLBYTES
330         case EXT_JUMBOP:
331                 size = MJUMPAGESIZE;
332                 break;
333 #endif
334         case EXT_JUMBO9:
335                 size = MJUM9BYTES;
336                 break;
337         case EXT_JUMBO16:
338                 size = MJUM16BYTES;
339                 break;
340         default:
341                 panic("%s: unrecognized cluster type %d", __func__, type);
342         }
343         return (size);
344 }
345
346 void dump_mi(struct mbuf_iovec *mi);
347
348 #endif /* _MVEC_H_ */