1/*
2 *   BSD LICENSE
3 *
4 *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5 *   All rights reserved.
6 *
7 *   Redistribution and use in source and binary forms, with or without
8 *   modification, are permitted provided that the following conditions
9 *   are met:
10 *
11 *     * Redistributions of source code must retain the above copyright
12 *       notice, this list of conditions and the following disclaimer.
13 *     * Redistributions in binary form must reproduce the above copyright
14 *       notice, this list of conditions and the following disclaimer in
15 *       the documentation and/or other materials provided with the
16 *       distribution.
17 *     * Neither the name of Cavium, Inc. nor the names of its
18 *       contributors may be used to endorse or promote products derived
19 *       from this software without specific prior written permission.
20 *
21 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33/*$FreeBSD$*/
34
35/*   \file lio_ctrl.h
36 *   \brief Host NIC Driver: Routine to send network data &
37 *   control packet to Octeon.
38 */
39
40#ifndef __LIO_CTRL_H__
41#define __LIO_CTRL_H__
42
43/* Maximum number of 8-byte words can be sent in a NIC control message. */
44#define LIO_MAX_NCTRL_UDD	32
45
46typedef void	(*lio_ctrl_pkt_cb_fn_t)(void *);
47
48/*
49 * Structure of control information passed by the NIC module to the OSI
50 * layer when sending control commands to Octeon device software.
51 */
52struct lio_ctrl_pkt {
53	/* Command to be passed to the Octeon device software. */
54	union octeon_cmd	ncmd;
55
56	/* Send buffer  */
57	void			*data;
58	uint64_t		dmadata;
59
60	/* Response buffer */
61	void			*rdata;
62	uint64_t		dmardata;
63
64	/* Additional data that may be needed by some commands. */
65	uint64_t		udd[LIO_MAX_NCTRL_UDD];
66
67	/* Input queue to use to send this command. */
68	uint64_t		iq_no;
69
70	/*
71	 *  Time to wait for Octeon software to respond to this control command.
72	 *  If wait_time is 0, OSI assumes no response is expected.
73	 */
74	size_t			wait_time;
75
76	/* The network device that issued the control command. */
77	struct lio		*lio;
78
79	/* Callback function called when the command has been fetched */
80	lio_ctrl_pkt_cb_fn_t	cb_fn;
81};
82
83/*
84 * Structure of data information passed by the NIC module to the OSI
85 * layer when forwarding data to Octeon device software.
86 */
87struct lio_data_pkt {
88	/*
89	 *  Pointer to information maintained by NIC module for this packet. The
90	 *  OSI layer passes this as-is to the driver.
91	 */
92	void			*buf;
93
94	/* Type of buffer passed in "buf" above. */
95	uint32_t		reqtype;
96
97	/* Total data bytes to be transferred in this command. */
98	uint32_t		datasize;
99
100	/* Command to be passed to the Octeon device software. */
101	union lio_instr_64B	cmd;
102
103	/* Input queue to use to send this command. */
104	uint32_t		q_no;
105
106};
107
108/*
109 * Structure passed by NIC module to OSI layer to prepare a command to send
110 * network data to Octeon.
111 */
112union lio_cmd_setup {
113	struct {
114		uint32_t	iq_no:8;
115		uint32_t	gather:1;
116		uint32_t	timestamp:1;
117		uint32_t	ip_csum:1;
118		uint32_t	transport_csum:1;
119		uint32_t	tnl_csum:1;
120		uint32_t	rsvd:19;
121
122		union {
123			uint32_t	datasize;
124			uint32_t	gatherptrs;
125		}	u;
126	}	s;
127
128	uint64_t	cmd_setup64;
129
130};
131
132static inline int
133lio_iq_is_full(struct octeon_device *oct, uint32_t q_no)
134{
135
136	return (atomic_load_acq_int(&oct->instr_queue[q_no]->instr_pending) >=
137		(oct->instr_queue[q_no]->max_count - 2));
138}
139
140static inline void
141lio_prepare_pci_cmd_o3(struct octeon_device *oct, union lio_instr_64B *cmd,
142		       union lio_cmd_setup *setup, uint32_t tag)
143{
144	union octeon_packet_params	packet_params;
145	struct octeon_instr_irh		*irh;
146	struct octeon_instr_ih3		*ih3;
147	struct octeon_instr_pki_ih3	*pki_ih3;
148	int	port;
149
150	bzero(cmd, sizeof(union lio_instr_64B));
151
152	ih3 = (struct octeon_instr_ih3 *)&cmd->cmd3.ih3;
153	pki_ih3 = (struct octeon_instr_pki_ih3 *)&cmd->cmd3.pki_ih3;
154
155	/*
156	 * assume that rflag is cleared so therefore front data will only have
157	 * irh and ossp[1] and ossp[2] for a total of 24 bytes
158	 */
159	ih3->pkind = oct->instr_queue[setup->s.iq_no]->txpciq.s.pkind;
160	/* PKI IH */
161	ih3->fsz = LIO_PCICMD_O3;
162
163	if (!setup->s.gather) {
164		ih3->dlengsz = setup->s.u.datasize;
165	} else {
166		ih3->gather = 1;
167		ih3->dlengsz = setup->s.u.gatherptrs;
168	}
169
170	pki_ih3->w = 1;
171	pki_ih3->raw = 0;
172	pki_ih3->utag = 0;
173	pki_ih3->utt = 1;
174	pki_ih3->uqpg = oct->instr_queue[setup->s.iq_no]->txpciq.s.use_qpg;
175
176	port = (int)oct->instr_queue[setup->s.iq_no]->txpciq.s.port;
177
178	if (tag)
179		pki_ih3->tag = tag;
180	else
181		pki_ih3->tag = LIO_DATA(port);
182
183	pki_ih3->tagtype = LIO_ORDERED_TAG;
184	pki_ih3->qpg = oct->instr_queue[setup->s.iq_no]->txpciq.s.qpg;
185	pki_ih3->pm = 0x0;		/* parse from L2 */
186	/* sl will be sizeof(pki_ih3) + irh + ossp0 + ossp1 */
187	pki_ih3->sl = 32;
188
189	irh = (struct octeon_instr_irh *)&cmd->cmd3.irh;
190
191	irh->opcode = LIO_OPCODE_NIC;
192	irh->subcode = LIO_OPCODE_NIC_NW_DATA;
193
194	packet_params.pkt_params32 = 0;
195
196	packet_params.s.ip_csum = setup->s.ip_csum;
197	packet_params.s.transport_csum = setup->s.transport_csum;
198	packet_params.s.tnl_csum = setup->s.tnl_csum;
199	packet_params.s.tsflag = setup->s.timestamp;
200
201	irh->ossp = packet_params.pkt_params32;
202}
203
204/*
205 * Utility function to prepare a 64B NIC instruction based on a setup command
206 * @param oct - Pointer to current octeon device
207 * @param cmd - pointer to instruction to be filled in.
208 * @param setup - pointer to the setup structure
209 * @param q_no - which queue for back pressure
210 *
211 * Assumes the cmd instruction is pre-allocated, but no fields are filled in.
212 */
213static inline void
214lio_prepare_pci_cmd(struct octeon_device *oct, union lio_instr_64B *cmd,
215		    union lio_cmd_setup *setup, uint32_t tag)
216{
217
218	lio_prepare_pci_cmd_o3(oct, cmd, setup, tag);
219}
220
221/*
222 * Send a NIC data packet to the device
223 * @param oct - octeon device pointer
224 * @param ndata - control structure with queueing, and buffer information
225 *
226 * @returns LIO_IQ_FAILED if it failed to add to the input queue.
227 * LIO_IQ_STOP if it the queue should be stopped,
228 * and LIO_IQ_SEND_OK if it sent okay.
229 */
230int	lio_send_data_pkt(struct octeon_device *oct,
231			  struct lio_data_pkt *ndata);
232
233/*
234 * Send a NIC control packet to the device
235 * @param oct - octeon device pointer
236 * @param nctrl - control structure with command, timeout, and callback info
237 * @returns IQ_FAILED if it failed to add to the input queue. IQ_STOP if it the
238 * queue should be stopped, and LIO_IQ_SEND_OK if it sent okay.
239 */
240int	lio_send_ctrl_pkt(struct octeon_device *oct,
241			  struct lio_ctrl_pkt *nctrl);
242
243#endif	/* __LIO_CTRL_H__ */
244