1 | /********************************************************************** |
2 | * Author: Cavium, Inc. |
3 | * |
4 | * Contact: support@cavium.com |
5 | * Please include "LiquidIO" in the subject. |
6 | * |
7 | * Copyright (c) 2003-2016 Cavium, Inc. |
8 | * |
9 | * This file is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License, Version 2, as |
11 | * published by the Free Software Foundation. |
12 | * |
13 | * This file is distributed in the hope that it will be useful, but |
14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty |
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or |
16 | * NONINFRINGEMENT. See the GNU General Public License for more |
17 | * details. |
18 | **********************************************************************/ |
19 | |
20 | /*! \file octeon_nic.h |
21 | * \brief Host NIC Driver: Routine to send network data & |
22 | * control packet to Octeon. |
23 | */ |
24 | |
25 | #ifndef __OCTEON_NIC_H__ |
26 | #define __OCTEON_NIC_H__ |
27 | |
28 | /* Maximum number of 8-byte words can be sent in a NIC control message. |
29 | */ |
30 | #define MAX_NCTRL_UDD 32 |
31 | |
32 | typedef void (*octnic_ctrl_pkt_cb_fn_t) (void *); |
33 | |
34 | /* Structure of control information passed by the NIC module to the OSI |
35 | * layer when sending control commands to Octeon device software. |
36 | */ |
37 | struct octnic_ctrl_pkt { |
38 | /** Command to be passed to the Octeon device software. */ |
39 | union octnet_cmd ncmd; |
40 | |
41 | /** Send buffer */ |
42 | void *data; |
43 | u64 dmadata; |
44 | |
45 | /** Response buffer */ |
46 | void *rdata; |
47 | u64 dmardata; |
48 | |
49 | /** Additional data that may be needed by some commands. */ |
50 | u64 udd[MAX_NCTRL_UDD]; |
51 | |
52 | /** Input queue to use to send this command. */ |
53 | u64 iq_no; |
54 | |
55 | /** The network device that issued the control command. */ |
56 | u64 netpndev; |
57 | |
58 | /** Callback function called when the command has been fetched */ |
59 | octnic_ctrl_pkt_cb_fn_t cb_fn; |
60 | |
61 | u32 sc_status; |
62 | }; |
63 | |
64 | #define MAX_UDD_SIZE(nctrl) (sizeof((nctrl)->udd)) |
65 | |
66 | /** Structure of data information passed by the NIC module to the OSI |
67 | * layer when forwarding data to Octeon device software. |
68 | */ |
69 | struct octnic_data_pkt { |
70 | /** Pointer to information maintained by NIC module for this packet. The |
71 | * OSI layer passes this as-is to the driver. |
72 | */ |
73 | void *buf; |
74 | |
75 | /** Type of buffer passed in "buf" above. */ |
76 | u32 reqtype; |
77 | |
78 | /** Total data bytes to be transferred in this command. */ |
79 | u32 datasize; |
80 | |
81 | /** Command to be passed to the Octeon device software. */ |
82 | union octeon_instr_64B cmd; |
83 | |
84 | /** Input queue to use to send this command. */ |
85 | u32 q_no; |
86 | |
87 | }; |
88 | |
89 | /** Structure passed by NIC module to OSI layer to prepare a command to send |
90 | * network data to Octeon. |
91 | */ |
92 | union octnic_cmd_setup { |
93 | struct { |
94 | u32 iq_no:8; |
95 | u32 gather:1; |
96 | u32 timestamp:1; |
97 | u32 ip_csum:1; |
98 | u32 transport_csum:1; |
99 | u32 tnl_csum:1; |
100 | u32 rsvd:19; |
101 | |
102 | union { |
103 | u32 datasize; |
104 | u32 gatherptrs; |
105 | } u; |
106 | } s; |
107 | |
108 | u64 u64; |
109 | |
110 | }; |
111 | |
112 | static inline int octnet_iq_is_full(struct octeon_device *oct, u32 q_no) |
113 | { |
114 | return ((u32)atomic_read(v: &oct->instr_queue[q_no]->instr_pending) |
115 | >= (oct->instr_queue[q_no]->max_count - 2)); |
116 | } |
117 | |
118 | static inline void |
119 | octnet_prepare_pci_cmd_o2(struct octeon_device *oct, |
120 | union octeon_instr_64B *cmd, |
121 | union octnic_cmd_setup *setup, u32 tag) |
122 | { |
123 | struct octeon_instr_ih2 *ih2; |
124 | struct octeon_instr_irh *irh; |
125 | union octnic_packet_params packet_params; |
126 | int port; |
127 | |
128 | memset(cmd, 0, sizeof(union octeon_instr_64B)); |
129 | |
130 | ih2 = (struct octeon_instr_ih2 *)&cmd->cmd2.ih2; |
131 | |
132 | /* assume that rflag is cleared so therefore front data will only have |
133 | * irh and ossp[0], ossp[1] for a total of 32 bytes |
134 | */ |
135 | ih2->fsz = LIO_PCICMD_O2; |
136 | |
137 | ih2->tagtype = ORDERED_TAG; |
138 | ih2->grp = DEFAULT_POW_GRP; |
139 | |
140 | port = (int)oct->instr_queue[setup->s.iq_no]->txpciq.s.port; |
141 | |
142 | if (tag) |
143 | ih2->tag = tag; |
144 | else |
145 | ih2->tag = LIO_DATA(port); |
146 | |
147 | ih2->raw = 1; |
148 | ih2->qos = (port & 3) + 4; /* map qos based on interface */ |
149 | |
150 | if (!setup->s.gather) { |
151 | ih2->dlengsz = setup->s.u.datasize; |
152 | } else { |
153 | ih2->gather = 1; |
154 | ih2->dlengsz = setup->s.u.gatherptrs; |
155 | } |
156 | |
157 | irh = (struct octeon_instr_irh *)&cmd->cmd2.irh; |
158 | |
159 | irh->opcode = OPCODE_NIC; |
160 | irh->subcode = OPCODE_NIC_NW_DATA; |
161 | |
162 | packet_params.u32 = 0; |
163 | |
164 | packet_params.s.ip_csum = setup->s.ip_csum; |
165 | packet_params.s.transport_csum = setup->s.transport_csum; |
166 | packet_params.s.tnl_csum = setup->s.tnl_csum; |
167 | packet_params.s.tsflag = setup->s.timestamp; |
168 | |
169 | irh->ossp = packet_params.u32; |
170 | } |
171 | |
172 | static inline void |
173 | octnet_prepare_pci_cmd_o3(struct octeon_device *oct, |
174 | union octeon_instr_64B *cmd, |
175 | union octnic_cmd_setup *setup, u32 tag) |
176 | { |
177 | struct octeon_instr_irh *irh; |
178 | struct octeon_instr_ih3 *ih3; |
179 | struct octeon_instr_pki_ih3 *pki_ih3; |
180 | union octnic_packet_params packet_params; |
181 | int port; |
182 | |
183 | memset(cmd, 0, sizeof(union octeon_instr_64B)); |
184 | |
185 | ih3 = (struct octeon_instr_ih3 *)&cmd->cmd3.ih3; |
186 | pki_ih3 = (struct octeon_instr_pki_ih3 *)&cmd->cmd3.pki_ih3; |
187 | |
188 | /* assume that rflag is cleared so therefore front data will only have |
189 | * irh and ossp[1] and ossp[2] for a total of 24 bytes |
190 | */ |
191 | ih3->pkind = oct->instr_queue[setup->s.iq_no]->txpciq.s.pkind; |
192 | /*PKI IH*/ |
193 | ih3->fsz = LIO_PCICMD_O3; |
194 | |
195 | if (!setup->s.gather) { |
196 | ih3->dlengsz = setup->s.u.datasize; |
197 | } else { |
198 | ih3->gather = 1; |
199 | ih3->dlengsz = setup->s.u.gatherptrs; |
200 | } |
201 | |
202 | pki_ih3->w = 1; |
203 | pki_ih3->raw = 1; |
204 | pki_ih3->utag = 1; |
205 | pki_ih3->utt = 1; |
206 | pki_ih3->uqpg = oct->instr_queue[setup->s.iq_no]->txpciq.s.use_qpg; |
207 | |
208 | port = (int)oct->instr_queue[setup->s.iq_no]->txpciq.s.port; |
209 | |
210 | if (tag) |
211 | pki_ih3->tag = tag; |
212 | else |
213 | pki_ih3->tag = LIO_DATA(port); |
214 | |
215 | pki_ih3->tagtype = ORDERED_TAG; |
216 | pki_ih3->qpg = oct->instr_queue[setup->s.iq_no]->txpciq.s.qpg; |
217 | pki_ih3->pm = 0x7; /*0x7 - meant for Parse nothing, uninterpreted*/ |
218 | pki_ih3->sl = 8; /* sl will be sizeof(pki_ih3)*/ |
219 | |
220 | irh = (struct octeon_instr_irh *)&cmd->cmd3.irh; |
221 | |
222 | irh->opcode = OPCODE_NIC; |
223 | irh->subcode = OPCODE_NIC_NW_DATA; |
224 | |
225 | packet_params.u32 = 0; |
226 | |
227 | packet_params.s.ip_csum = setup->s.ip_csum; |
228 | packet_params.s.transport_csum = setup->s.transport_csum; |
229 | packet_params.s.tnl_csum = setup->s.tnl_csum; |
230 | packet_params.s.tsflag = setup->s.timestamp; |
231 | |
232 | irh->ossp = packet_params.u32; |
233 | } |
234 | |
235 | /** Utility function to prepare a 64B NIC instruction based on a setup command |
236 | * @param cmd - pointer to instruction to be filled in. |
237 | * @param setup - pointer to the setup structure |
238 | * @param q_no - which queue for back pressure |
239 | * |
240 | * Assumes the cmd instruction is pre-allocated, but no fields are filled in. |
241 | */ |
242 | static inline void |
243 | octnet_prepare_pci_cmd(struct octeon_device *oct, union octeon_instr_64B *cmd, |
244 | union octnic_cmd_setup *setup, u32 tag) |
245 | { |
246 | if (OCTEON_CN6XXX(oct)) |
247 | octnet_prepare_pci_cmd_o2(oct, cmd, setup, tag); |
248 | else |
249 | octnet_prepare_pci_cmd_o3(oct, cmd, setup, tag); |
250 | } |
251 | |
252 | /** Allocate and a soft command with space for a response immediately following |
253 | * the commnad. |
254 | * @param oct - octeon device pointer |
255 | * @param cmd - pointer to the command structure, pre-filled for everything |
256 | * except the response. |
257 | * @param rdatasize - size in bytes of the response. |
258 | * |
259 | * @returns pointer to allocated buffer with command copied into it, and |
260 | * response space immediately following. |
261 | */ |
262 | void * |
263 | octeon_alloc_soft_command_resp(struct octeon_device *oct, |
264 | union octeon_instr_64B *cmd, |
265 | u32 rdatasize); |
266 | |
267 | /** Send a NIC data packet to the device |
268 | * @param oct - octeon device pointer |
269 | * @param ndata - control structure with queueing, and buffer information |
270 | * |
271 | * @returns IQ_FAILED if it failed to add to the input queue. IQ_STOP if it the |
272 | * queue should be stopped, and IQ_SEND_OK if it sent okay. |
273 | */ |
274 | int octnet_send_nic_data_pkt(struct octeon_device *oct, |
275 | struct octnic_data_pkt *ndata, |
276 | int xmit_more); |
277 | |
278 | /** Send a NIC control packet to the device |
279 | * @param oct - octeon device pointer |
280 | * @param nctrl - control structure with command, timout, and callback info |
281 | * @returns IQ_FAILED if it failed to add to the input queue. IQ_STOP if it the |
282 | * queue should be stopped, and IQ_SEND_OK if it sent okay. |
283 | */ |
284 | int |
285 | octnet_send_nic_ctrl_pkt(struct octeon_device *oct, |
286 | struct octnic_ctrl_pkt *nctrl); |
287 | |
288 | #endif |
289 | |