Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2001-2023 Intel Corporation
3 : : */
4 : :
5 : : #include "idpf_type.h"
6 : : #include "idpf_prototype.h"
7 : : #include <virtchnl.h>
8 : :
9 : :
10 : : /**
11 : : * idpf_set_mac_type - Sets MAC type
12 : : * @hw: pointer to the HW structure
13 : : *
14 : : * This function sets the mac type of the adapter based on the
15 : : * vendor ID and device ID stored in the hw structure.
16 : : */
17 : 0 : int idpf_set_mac_type(struct idpf_hw *hw)
18 : : {
19 : : int status = 0;
20 : :
21 : 0 : DEBUGFUNC("Set MAC type\n");
22 : :
23 [ # # ]: 0 : if (hw->vendor_id == IDPF_INTEL_VENDOR_ID) {
24 [ # # # ]: 0 : switch (hw->device_id) {
25 : 0 : case IDPF_DEV_ID_PF:
26 : 0 : hw->mac.type = IDPF_MAC_PF;
27 : 0 : break;
28 : 0 : case IDPF_DEV_ID_VF:
29 : 0 : hw->mac.type = IDPF_MAC_VF;
30 : 0 : break;
31 : 0 : default:
32 : 0 : hw->mac.type = IDPF_MAC_GENERIC;
33 : 0 : break;
34 : : }
35 : : } else {
36 : : status = -ENODEV;
37 : : }
38 : :
39 : 0 : DEBUGOUT2("Setting MAC type found mac: %d, returns: %d\n",
40 : : hw->mac.type, status);
41 : 0 : return status;
42 : : }
43 : :
44 : : /**
45 : : * idpf_init_hw - main initialization routine
46 : : * @hw: pointer to the hardware structure
47 : : * @ctlq_size: struct to pass ctlq size data
48 : : */
49 : 0 : int idpf_init_hw(struct idpf_hw *hw, struct idpf_ctlq_size ctlq_size)
50 : : {
51 : : struct idpf_ctlq_create_info *q_info;
52 : : int status = 0;
53 : : struct idpf_ctlq_info *cq = NULL;
54 : :
55 : : /* Setup initial control queues */
56 : : q_info = (struct idpf_ctlq_create_info *)
57 : 0 : idpf_calloc(hw, 2, sizeof(struct idpf_ctlq_create_info));
58 [ # # ]: 0 : if (!q_info)
59 : : return -ENOMEM;
60 : :
61 : 0 : q_info[0].type = IDPF_CTLQ_TYPE_MAILBOX_TX;
62 : 0 : q_info[0].buf_size = ctlq_size.asq_buf_size;
63 : 0 : q_info[0].len = ctlq_size.asq_ring_size;
64 : 0 : q_info[0].id = -1; /* default queue */
65 : :
66 [ # # ]: 0 : if (hw->mac.type == IDPF_MAC_PF) {
67 : 0 : q_info[0].reg.head = PF_FW_ATQH;
68 : 0 : q_info[0].reg.tail = PF_FW_ATQT;
69 : 0 : q_info[0].reg.len = PF_FW_ATQLEN;
70 : 0 : q_info[0].reg.bah = PF_FW_ATQBAH;
71 : 0 : q_info[0].reg.bal = PF_FW_ATQBAL;
72 : 0 : q_info[0].reg.len_mask = PF_FW_ATQLEN_ATQLEN_M;
73 : 0 : q_info[0].reg.len_ena_mask = PF_FW_ATQLEN_ATQENABLE_M;
74 : 0 : q_info[0].reg.head_mask = PF_FW_ATQH_ATQH_M;
75 : : } else {
76 : 0 : q_info[0].reg.head = VF_ATQH;
77 : 0 : q_info[0].reg.tail = VF_ATQT;
78 : 0 : q_info[0].reg.len = VF_ATQLEN;
79 : 0 : q_info[0].reg.bah = VF_ATQBAH;
80 : 0 : q_info[0].reg.bal = VF_ATQBAL;
81 : 0 : q_info[0].reg.len_mask = VF_ATQLEN_ATQLEN_M;
82 : 0 : q_info[0].reg.len_ena_mask = VF_ATQLEN_ATQENABLE_M;
83 : 0 : q_info[0].reg.head_mask = VF_ATQH_ATQH_M;
84 : : }
85 : :
86 : 0 : q_info[1].type = IDPF_CTLQ_TYPE_MAILBOX_RX;
87 : 0 : q_info[1].buf_size = ctlq_size.arq_buf_size;
88 : 0 : q_info[1].len = ctlq_size.arq_ring_size;
89 : 0 : q_info[1].id = -1; /* default queue */
90 : :
91 [ # # ]: 0 : if (hw->mac.type == IDPF_MAC_PF) {
92 : 0 : q_info[1].reg.head = PF_FW_ARQH;
93 : 0 : q_info[1].reg.tail = PF_FW_ARQT;
94 : 0 : q_info[1].reg.len = PF_FW_ARQLEN;
95 : 0 : q_info[1].reg.bah = PF_FW_ARQBAH;
96 : 0 : q_info[1].reg.bal = PF_FW_ARQBAL;
97 : 0 : q_info[1].reg.len_mask = PF_FW_ARQLEN_ARQLEN_M;
98 : 0 : q_info[1].reg.len_ena_mask = PF_FW_ARQLEN_ARQENABLE_M;
99 : 0 : q_info[1].reg.head_mask = PF_FW_ARQH_ARQH_M;
100 : : } else {
101 : 0 : q_info[1].reg.head = VF_ARQH;
102 : 0 : q_info[1].reg.tail = VF_ARQT;
103 : 0 : q_info[1].reg.len = VF_ARQLEN;
104 : 0 : q_info[1].reg.bah = VF_ARQBAH;
105 : 0 : q_info[1].reg.bal = VF_ARQBAL;
106 : 0 : q_info[1].reg.len_mask = VF_ARQLEN_ARQLEN_M;
107 : 0 : q_info[1].reg.len_ena_mask = VF_ARQLEN_ARQENABLE_M;
108 : 0 : q_info[1].reg.head_mask = VF_ARQH_ARQH_M;
109 : : }
110 : :
111 : 0 : status = idpf_ctlq_init(hw, 2, q_info);
112 [ # # ]: 0 : if (status) {
113 : : /* TODO return error */
114 : 0 : idpf_free(hw, q_info);
115 : 0 : return status;
116 : : }
117 : :
118 [ # # ]: 0 : LIST_FOR_EACH_ENTRY(cq, &hw->cq_list_head, idpf_ctlq_info, cq_list) {
119 [ # # ]: 0 : if (cq->cq_type == IDPF_CTLQ_TYPE_MAILBOX_TX)
120 : 0 : hw->asq = cq;
121 [ # # ]: 0 : else if (cq->cq_type == IDPF_CTLQ_TYPE_MAILBOX_RX)
122 : 0 : hw->arq = cq;
123 : : }
124 : :
125 : : /* TODO hardcode a mac addr for now */
126 : 0 : hw->mac.addr[0] = 0x00;
127 : 0 : hw->mac.addr[1] = 0x00;
128 : 0 : hw->mac.addr[2] = 0x00;
129 : 0 : hw->mac.addr[3] = 0x00;
130 : 0 : hw->mac.addr[4] = 0x03;
131 : 0 : hw->mac.addr[5] = 0x14;
132 : :
133 : 0 : idpf_free(hw, q_info);
134 : :
135 : 0 : return 0;
136 : : }
137 : :
138 : : /**
139 : : * idpf_send_msg_to_cp
140 : : * @hw: pointer to the hardware structure
141 : : * @v_opcode: opcodes for VF-PF communication
142 : : * @v_retval: return error code
143 : : * @msg: pointer to the msg buffer
144 : : * @msglen: msg length
145 : : * @cmd_details: pointer to command details
146 : : *
147 : : * Send message to CP. By default, this message
148 : : * is sent asynchronously, i.e. idpf_asq_send_command() does not wait for
149 : : * completion before returning.
150 : : */
151 : 0 : int idpf_send_msg_to_cp(struct idpf_hw *hw, int v_opcode,
152 : : int v_retval, u8 *msg, u16 msglen)
153 : : {
154 : 0 : struct idpf_ctlq_msg ctlq_msg = { 0 };
155 : 0 : struct idpf_dma_mem dma_mem = { 0 };
156 : : int status;
157 : :
158 : 0 : ctlq_msg.opcode = idpf_mbq_opc_send_msg_to_pf;
159 : : ctlq_msg.func_id = 0;
160 : 0 : ctlq_msg.data_len = msglen;
161 : 0 : ctlq_msg.cookie.mbx.chnl_retval = v_retval;
162 : 0 : ctlq_msg.cookie.mbx.chnl_opcode = v_opcode;
163 : :
164 [ # # ]: 0 : if (msglen > 0) {
165 : 0 : dma_mem.va = (struct idpf_dma_mem *)
166 : 0 : idpf_alloc_dma_mem(hw, &dma_mem, msglen);
167 [ # # ]: 0 : if (!dma_mem.va)
168 : : return -ENOMEM;
169 : :
170 : : idpf_memcpy(dma_mem.va, msg, msglen, IDPF_NONDMA_TO_DMA);
171 : 0 : ctlq_msg.ctx.indirect.payload = &dma_mem;
172 : : }
173 : 0 : status = idpf_ctlq_send(hw, hw->asq, 1, &ctlq_msg);
174 : :
175 [ # # ]: 0 : if (dma_mem.va)
176 : : idpf_free_dma_mem(hw, &dma_mem);
177 : :
178 : : return status;
179 : : }
180 : :
181 : : /**
182 : : * idpf_asq_done - check if FW has processed the Admin Send Queue
183 : : * @hw: pointer to the hw struct
184 : : *
185 : : * Returns true if the firmware has processed all descriptors on the
186 : : * admin send queue. Returns false if there are still requests pending.
187 : : */
188 : 0 : bool idpf_asq_done(struct idpf_hw *hw)
189 : : {
190 : : /* AQ designers suggest use of head for better
191 : : * timing reliability than DD bit
192 : : */
193 : 0 : return rd32(hw, hw->asq->reg.head) == hw->asq->next_to_use;
194 : : }
195 : :
196 : : /**
197 : : * idpf_check_asq_alive
198 : : * @hw: pointer to the hw struct
199 : : *
200 : : * Returns true if Queue is enabled else false.
201 : : */
202 : 0 : bool idpf_check_asq_alive(struct idpf_hw *hw)
203 : : {
204 [ # # ]: 0 : if (hw->asq->reg.len)
205 : 0 : return !!(rd32(hw, hw->asq->reg.len) &
206 : : PF_FW_ATQLEN_ATQENABLE_M);
207 : :
208 : : return false;
209 : : }
210 : :
211 : : /**
212 : : * idpf_clean_arq_element
213 : : * @hw: pointer to the hw struct
214 : : * @e: event info from the receive descriptor, includes any buffers
215 : : * @pending: number of events that could be left to process
216 : : *
217 : : * This function cleans one Admin Receive Queue element and returns
218 : : * the contents through e. It can also return how many events are
219 : : * left to process through 'pending'
220 : : */
221 : 0 : int idpf_clean_arq_element(struct idpf_hw *hw,
222 : : struct idpf_arq_event_info *e, u16 *pending)
223 : : {
224 : 0 : struct idpf_dma_mem *dma_mem = NULL;
225 : 0 : struct idpf_ctlq_msg msg = { 0 };
226 : : int status;
227 : : u16 msg_data_len;
228 : :
229 : 0 : *pending = 1;
230 : :
231 : 0 : status = idpf_ctlq_recv(hw->arq, pending, &msg);
232 [ # # ]: 0 : if (status == -ENOMSG)
233 : 0 : goto exit;
234 : :
235 : : /* ctlq_msg does not align to ctlq_desc, so copy relevant data here */
236 : 0 : e->desc.opcode = msg.opcode;
237 : 0 : e->desc.cookie_high = msg.cookie.mbx.chnl_opcode;
238 : 0 : e->desc.cookie_low = msg.cookie.mbx.chnl_retval;
239 : 0 : e->desc.ret_val = msg.status;
240 : 0 : e->desc.datalen = msg.data_len;
241 [ # # ]: 0 : if (msg.data_len > 0) {
242 [ # # # # ]: 0 : if (!msg.ctx.indirect.payload || !msg.ctx.indirect.payload->va ||
243 [ # # ]: 0 : !e->msg_buf) {
244 : : return -EFAULT;
245 : : }
246 : 0 : e->buf_len = msg.data_len;
247 : : msg_data_len = msg.data_len;
248 [ # # ]: 0 : idpf_memcpy(e->msg_buf, msg.ctx.indirect.payload->va, msg_data_len,
249 : : IDPF_DMA_TO_NONDMA);
250 : 0 : dma_mem = msg.ctx.indirect.payload;
251 : : } else {
252 : 0 : *pending = 0;
253 : : }
254 : :
255 : 0 : status = idpf_ctlq_post_rx_buffs(hw, hw->arq, pending, &dma_mem);
256 : :
257 : : exit:
258 : : return status;
259 : : }
260 : :
261 : : /**
262 : : * idpf_deinit_hw - shutdown routine
263 : : * @hw: pointer to the hardware structure
264 : : */
265 : 0 : void idpf_deinit_hw(struct idpf_hw *hw)
266 : : {
267 : 0 : hw->asq = NULL;
268 : 0 : hw->arq = NULL;
269 : :
270 : 0 : idpf_ctlq_deinit(hw);
271 : 0 : }
272 : :
273 : : /**
274 : : * idpf_reset
275 : : * @hw: pointer to the hardware structure
276 : : *
277 : : * Send a RESET message to the CPF. Does not wait for response from CPF
278 : : * as none will be forthcoming. Immediately after calling this function,
279 : : * the control queue should be shut down and (optionally) reinitialized.
280 : : */
281 : 0 : int idpf_reset(struct idpf_hw *hw)
282 : : {
283 : 0 : return idpf_send_msg_to_cp(hw, VIRTCHNL_OP_RESET_VF,
284 : : 0, NULL, 0);
285 : : }
286 : :
287 : : /**
288 : : * idpf_get_set_rss_lut
289 : : * @hw: pointer to the hardware structure
290 : : * @vsi_id: vsi fw index
291 : : * @pf_lut: for PF table set true, for VSI table set false
292 : : * @lut: pointer to the lut buffer provided by the caller
293 : : * @lut_size: size of the lut buffer
294 : : * @set: set true to set the table, false to get the table
295 : : *
296 : : * Internal function to get or set RSS look up table
297 : : */
298 : : STATIC int idpf_get_set_rss_lut(struct idpf_hw *hw, u16 vsi_id,
299 : : bool pf_lut, u8 *lut, u16 lut_size,
300 : : bool set)
301 : : {
302 : : /* TODO fill out command */
303 : : return 0;
304 : : }
305 : :
306 : : /**
307 : : * idpf_get_rss_lut
308 : : * @hw: pointer to the hardware structure
309 : : * @vsi_id: vsi fw index
310 : : * @pf_lut: for PF table set true, for VSI table set false
311 : : * @lut: pointer to the lut buffer provided by the caller
312 : : * @lut_size: size of the lut buffer
313 : : *
314 : : * get the RSS lookup table, PF or VSI type
315 : : */
316 : 0 : int idpf_get_rss_lut(struct idpf_hw *hw, u16 vsi_id, bool pf_lut,
317 : : u8 *lut, u16 lut_size)
318 : : {
319 : 0 : return idpf_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size, false);
320 : : }
321 : :
322 : : /**
323 : : * idpf_set_rss_lut
324 : : * @hw: pointer to the hardware structure
325 : : * @vsi_id: vsi fw index
326 : : * @pf_lut: for PF table set true, for VSI table set false
327 : : * @lut: pointer to the lut buffer provided by the caller
328 : : * @lut_size: size of the lut buffer
329 : : *
330 : : * set the RSS lookup table, PF or VSI type
331 : : */
332 : 0 : int idpf_set_rss_lut(struct idpf_hw *hw, u16 vsi_id, bool pf_lut,
333 : : u8 *lut, u16 lut_size)
334 : : {
335 : 0 : return idpf_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size, true);
336 : : }
337 : :
338 : : /**
339 : : * idpf_get_set_rss_key
340 : : * @hw: pointer to the hw struct
341 : : * @vsi_id: vsi fw index
342 : : * @key: pointer to key info struct
343 : : * @set: set true to set the key, false to get the key
344 : : *
345 : : * get the RSS key per VSI
346 : : */
347 : : STATIC int idpf_get_set_rss_key(struct idpf_hw *hw, u16 vsi_id,
348 : : struct idpf_get_set_rss_key_data *key,
349 : : bool set)
350 : : {
351 : : /* TODO fill out command */
352 : : return 0;
353 : : }
354 : :
355 : : /**
356 : : * idpf_get_rss_key
357 : : * @hw: pointer to the hw struct
358 : : * @vsi_id: vsi fw index
359 : : * @key: pointer to key info struct
360 : : *
361 : : */
362 : 0 : int idpf_get_rss_key(struct idpf_hw *hw, u16 vsi_id,
363 : : struct idpf_get_set_rss_key_data *key)
364 : : {
365 : 0 : return idpf_get_set_rss_key(hw, vsi_id, key, false);
366 : : }
367 : :
368 : : /**
369 : : * idpf_set_rss_key
370 : : * @hw: pointer to the hw struct
371 : : * @vsi_id: vsi fw index
372 : : * @key: pointer to key info struct
373 : : *
374 : : * set the RSS key per VSI
375 : : */
376 : 0 : int idpf_set_rss_key(struct idpf_hw *hw, u16 vsi_id,
377 : : struct idpf_get_set_rss_key_data *key)
378 : : {
379 : 0 : return idpf_get_set_rss_key(hw, vsi_id, key, true);
380 : : }
381 : :
382 [ - + ]: 235 : RTE_LOG_REGISTER_DEFAULT(idpf_common_logger, NOTICE);
|