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