- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / sfc_netutil / accel_shared_fifo.h
1 /****************************************************************************
2  * Solarflare driver for Xen network acceleration
3  *
4  * Copyright 2006-2008: Solarflare Communications Inc,
5  *                      9501 Jeronimo Road, Suite 250,
6  *                      Irvine, CA 92618, USA
7  *
8  * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published
12  * by the Free Software Foundation, incorporated herein by reference.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  ****************************************************************************
23  */
24
25 #ifndef NET_ACCEL_SHARED_FIFO_H
26 #define NET_ACCEL_SHARED_FIFO_H
27
28 /*
29  * This is based on fifo.h, but handles sharing between address spaces
30  * that don't trust each other, by splitting out the read and write
31  * indices. This costs at least one pointer indirection more than the
32  * vanilla version per access.
33  */
34
35 typedef struct {
36         char*    fifo;
37         unsigned      fifo_mask;
38         unsigned      *fifo_rd_i;
39         unsigned      *fifo_wr_i;
40 } sh_byte_fifo2;
41
42 #define SH_FIFO2_M(f, x)     ((x) & ((f)->fifo_mask))
43
44 static inline unsigned log2_ge(unsigned long n, unsigned min_order) {
45         unsigned order = min_order;
46         while((1ul << order) < n) ++order;
47         return order;
48 }
49
50 static inline unsigned long pow2(unsigned order) {
51         return (1ul << order);
52 }
53
54 #define is_pow2(x)  (pow2(log2_ge((x), 0)) == (x))
55
56 #define sh_fifo2_valid(f)  ((f) && (f)->fifo && (f)->fifo_mask > 0 &&   \
57                             is_pow2((f)->fifo_mask+1u))
58
59 #define sh_fifo2_init(f, cap, _rptr, _wptr)             \
60         do {                                            \
61                 BUG_ON(!is_pow2((cap) + 1));            \
62                 (f)->fifo_rd_i = _rptr;                 \
63                 (f)->fifo_wr_i = _wptr;                 \
64                 *(f)->fifo_rd_i = *(f)->fifo_wr_i = 0u; \
65                 (f)->fifo_mask = (cap);                 \
66         } while(0)
67
68 #define sh_fifo2_num(f)      SH_FIFO2_M((f),*(f)->fifo_wr_i - *(f)->fifo_rd_i)
69 #define sh_fifo2_space(f)    SH_FIFO2_M((f),*(f)->fifo_rd_i - *(f)->fifo_wr_i-1u)
70 #define sh_fifo2_is_empty(f)  (sh_fifo2_num(f)==0)
71 #define sh_fifo2_not_empty(f) (sh_fifo2_num(f)!=0)
72 #define sh_fifo2_is_full(f)   (sh_fifo2_space(f)==0u)
73 #define sh_fifo2_not_full(f)  (sh_fifo2_space(f)!=0u)
74 #define sh_fifo2_buf_size(f) ((f)->fifo_mask + 1u)
75 #define sh_fifo2_capacity(f) ((f)->fifo_mask)
76 #define sh_fifo2_end(f)      ((f)->fifo + sh_fifo2_buf_size(f))
77 #define sh_fifo2_not_half_full(f) (sh_fifo2_space(f) > (sh_fifo2_capacity(f) >> 1))
78
79 #define sh_fifo2_peek(f)     ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_rd_i)])
80 #define sh_fifo2_peekp(f)    ((f)->fifo + SH_FIFO2_M((f), *(f)->fifo_rd_i))
81 #define sh_fifo2_poke(f)     ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_wr_i)])
82 #define sh_fifo2_pokep(f)    ((f)->fifo + SH_FIFO2_M((f), *(f)->fifo_wr_i))
83 #define sh_fifo2_peek_i(f,i) ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_rd_i+(i))])
84 #define sh_fifo2_poke_i(f,i) ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_wr_i+(i))])
85
86 #define sh_fifo2_rd_next(f)                                     \
87         do {*(f)->fifo_rd_i = *(f)->fifo_rd_i + 1u;} while(0)
88 #define sh_fifo2_wr_next(f)                                     \
89         do {*(f)->fifo_wr_i = *(f)->fifo_wr_i + 1u;} while(0)
90 #define sh_fifo2_rd_adv(f, n)                                   \
91         do {*(f)->fifo_rd_i = *(f)->fifo_rd_i + (n);} while(0)
92 #define sh_fifo2_wr_adv(f, n)                                   \
93         do {*(f)->fifo_wr_i = *(f)->fifo_wr_i + (n);} while(0)
94
95 #define sh_fifo2_put(f, v)                                              \
96         do {sh_fifo2_poke(f) = (v); wmb(); sh_fifo2_wr_next(f);} while(0)
97
98 #define sh_fifo2_get(f, pv)                                             \
99         do {*(pv) = sh_fifo2_peek(f); mb(); sh_fifo2_rd_next(f);} while(0)
100
101 static inline unsigned sh_fifo2_contig_num(sh_byte_fifo2 *f)
102 {
103         unsigned fifo_wr_i = SH_FIFO2_M(f, *f->fifo_wr_i);
104         unsigned fifo_rd_i = SH_FIFO2_M(f, *f->fifo_rd_i);
105
106         return (fifo_wr_i >= fifo_rd_i)
107                 ? fifo_wr_i - fifo_rd_i
108                 : f->fifo_mask + 1u - *(f)->fifo_rd_i;
109 }
110
111 static inline unsigned sh_fifo2_contig_space(sh_byte_fifo2 *f)
112 {
113         unsigned fifo_wr_i = SH_FIFO2_M(f, *f->fifo_wr_i);
114         unsigned fifo_rd_i = SH_FIFO2_M(f, *f->fifo_rd_i);
115
116         return (fifo_rd_i > fifo_wr_i)
117                 ? fifo_rd_i - fifo_wr_i - 1
118                 : (f->fifo_mask + 1u - fifo_wr_i
119                    /*
120                     * The last byte can't be used if the read pointer
121                     * is at zero.
122                     */
123                    - (fifo_rd_i==0));
124 }
125
126
127 #endif /* NET_ACCEL_SHARED_FIFO_H */