1 /*
2  * Copyright (c) 2014, Cisco Systems, Inc. All rights reserved.
3  *
4  * LICENSE_BEGIN
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * LICENSE_END
39  *
40  *
41  */
42 
43 #ifndef _USD_POST_H_
44 #define _USD_POST_H_
45 
46 #include <sys/uio.h>
47 
48 #include "usd.h"
49 #include "usd_util.h"
50 
51 static inline uint32_t
_usd_post_send_one(struct usd_wq * wq,const void * packet,size_t length,u_int8_t cq_entry)52 _usd_post_send_one(
53     struct usd_wq *wq,
54     const void *packet,
55     size_t length,
56     u_int8_t cq_entry)
57 {
58     struct vnic_wq *vwq;
59     uint32_t index;
60     struct wq_enet_desc *desc;
61     uint64_t wr;
62     u_int8_t offload_mode = 0, eop = 1;
63     u_int16_t mss = 7, header_length = 0, vlan_tag = 0;
64     u_int8_t vlan_tag_insert = 0, loopback = 0, fcoe_encap = 0;
65 
66     vwq = &wq->uwq_vnic_wq;
67     desc = wq->uwq_next_desc;
68     index = wq->uwq_post_index;
69 
70     wq_enet_desc_enc(desc, (uintptr_t)packet, length,
71         mss, header_length, offload_mode,
72         eop, cq_entry, fcoe_encap,
73         vlan_tag_insert, vlan_tag, loopback);
74     wmb();
75 
76     wr = vnic_cached_posted_index((dma_addr_t)packet, length, index);
77     iowrite64(wr, &vwq->ctrl->posted_index);
78 
79     wq->uwq_next_desc = (struct wq_enet_desc *)
80         ((uintptr_t)wq->uwq_desc_ring + (index<<4));
81     wq->uwq_post_index = (index+1) & wq->uwq_post_index_mask;
82     wq->uwq_send_credits--;
83 
84     return index;
85 }
86 
87 static inline uint32_t
_usd_post_send_two(struct usd_wq * wq,const void * hdr,size_t hdrlen,const void * pkt,size_t pktlen,u_int8_t cq_entry)88 _usd_post_send_two(
89     struct usd_wq *wq,
90     const void *hdr,
91     size_t hdrlen,
92     const void *pkt,
93     size_t pktlen,
94     u_int8_t cq_entry)
95 {
96     struct vnic_wq *vwq;
97     uint32_t index;
98     struct wq_enet_desc *desc;
99     u_int8_t offload_mode = 0, eop;
100     u_int16_t mss = 7, header_length = 0, vlan_tag = 0;
101     u_int8_t vlan_tag_insert = 0, loopback = 0, fcoe_encap = 0;
102 
103     vwq = &wq->uwq_vnic_wq;
104     desc = wq->uwq_next_desc;
105     index = wq->uwq_post_index;
106 
107     eop = 0;
108     wq_enet_desc_enc(desc, (uintptr_t)hdr, hdrlen,
109         mss, header_length, offload_mode,
110         eop, 0, fcoe_encap,
111         vlan_tag_insert, vlan_tag, loopback);
112 
113     desc = (struct wq_enet_desc *) ((uintptr_t)wq->uwq_desc_ring + (index<<4));
114     index = (index+1) & wq->uwq_post_index_mask;
115 
116     eop = 1;
117     wq_enet_desc_enc(desc, (uintptr_t)pkt, pktlen,
118         mss, header_length, offload_mode,
119         eop, cq_entry, fcoe_encap,
120         vlan_tag_insert, vlan_tag, loopback);
121     wmb();
122 
123     iowrite32(index, &vwq->ctrl->posted_index);
124 
125     wq->uwq_next_desc = (struct wq_enet_desc *)
126         ((uintptr_t)wq->uwq_desc_ring + (index<<4));
127     wq->uwq_post_index = (index+1) & wq->uwq_post_index_mask;
128     wq->uwq_send_credits -= 2;
129 
130     return index;
131 }
132 
133 static inline uint32_t
_usd_post_send_two_vlan(struct usd_wq * wq,const void * hdr,size_t hdrlen,const void * pkt,size_t pktlen,u_int8_t cq_entry,u_int16_t vlan_tag)134 _usd_post_send_two_vlan(
135     struct usd_wq *wq,
136     const void *hdr,
137     size_t hdrlen,
138     const void *pkt,
139     size_t pktlen,
140     u_int8_t cq_entry,
141     u_int16_t vlan_tag)
142 {
143     struct vnic_wq *vwq;
144     uint32_t index;
145     struct wq_enet_desc *desc;
146     u_int8_t offload_mode = 0, eop;
147     u_int16_t mss = 7, header_length = 0;
148     u_int8_t vlan_tag_insert = 1, loopback = 0, fcoe_encap = 0;
149 
150     vwq = &wq->uwq_vnic_wq;
151     desc = wq->uwq_next_desc;
152     index = wq->uwq_post_index;
153 
154     eop = 0;
155     wq_enet_desc_enc(desc, (uintptr_t)hdr, hdrlen,
156         mss, header_length, offload_mode,
157         eop, 0, fcoe_encap,
158         vlan_tag_insert, vlan_tag, loopback);
159 
160     desc = (struct wq_enet_desc *) ((uintptr_t)wq->uwq_desc_ring + (index<<4));
161     index = (index+1) & wq->uwq_post_index_mask;
162 
163     eop = 1;
164     wq_enet_desc_enc(desc, (uintptr_t)pkt, pktlen,
165         mss, header_length, offload_mode,
166         eop, cq_entry, fcoe_encap,
167         vlan_tag_insert, vlan_tag, loopback);
168     wmb();
169 
170     iowrite32(index, &vwq->ctrl->posted_index);
171 
172     wq->uwq_next_desc = (struct wq_enet_desc *)
173         ((uintptr_t)wq->uwq_desc_ring + (index<<4));
174     wq->uwq_post_index = (index+1) & wq->uwq_post_index_mask;
175     wq->uwq_send_credits -= 2;
176 
177     return index;
178 }
179 
180 /*
181  * Consume iov count credits, assumes that iov[0] includes usnic header
182  */
183 static inline uint32_t
_usd_post_send_iov(struct usd_wq * wq,const struct iovec * iov,size_t count,u_int8_t cq_entry)184 _usd_post_send_iov(
185     struct usd_wq *wq,
186     const struct iovec *iov,
187     size_t count,
188     u_int8_t cq_entry)
189 {
190     struct vnic_wq *vwq;
191     uint32_t index;
192     struct wq_enet_desc *desc;
193     u_int8_t offload_mode = 0;
194     u_int16_t mss = 7, header_length = 0, vlan_tag = 0;
195     u_int8_t vlan_tag_insert = 0, loopback = 0, fcoe_encap = 0;
196     unsigned i;
197 
198     vwq = &wq->uwq_vnic_wq;
199     desc = wq->uwq_next_desc;
200     index = wq->uwq_post_index;
201 
202     for (i = 0; i < count - 1; i++) {
203         wq_enet_desc_enc(desc, (uintptr_t)(iov[i].iov_base),
204             iov[i].iov_len, mss, header_length, offload_mode,
205             0, 0, fcoe_encap, vlan_tag_insert, vlan_tag, loopback);
206         desc = (struct wq_enet_desc *) ((uintptr_t)wq->uwq_desc_ring
207                                             + (index<<4));
208         index = (index+1) & wq->uwq_post_index_mask;
209     }
210 
211     wq_enet_desc_enc(desc, (uintptr_t)(iov[i].iov_base),
212             iov[i].iov_len, mss, header_length, offload_mode,
213 	        1, cq_entry, fcoe_encap, vlan_tag_insert, vlan_tag, loopback);
214 
215     wmb();
216 
217     iowrite32(index, &vwq->ctrl->posted_index);
218 
219     wq->uwq_next_desc = (struct wq_enet_desc *)
220         ((uintptr_t)wq->uwq_desc_ring + (index<<4));
221     wq->uwq_post_index = (index+1) & wq->uwq_post_index_mask;
222     wq->uwq_send_credits -= count;
223 
224     return index;
225 }
226 
227 #endif /* _USD_POST_H_ */
228