1 /*
2 * Copyright (C) 2015 Mellanox Technologies Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include "../include/mlx_port.h"
23 #include "../include/mlx_cmd.h"
24 #include "../../mlx_utils/include/public/mlx_memory.h"
25 #include "../../mlx_utils/include/public/mlx_pci.h"
26 #include "../../mlx_utils/include/public/mlx_bail.h"
27
28 #define PortDataEntry( _option, _offset, _align, _mask) { \
29 .option = _option, \
30 .offset = _offset, \
31 .align = _align, \
32 .mask = _mask, \
33 }
34
35 #define QpDataEntry( _type, _send_offset, _recv_offset) { \
36 .type = _type, \
37 .send_offset = _send_offset, \
38 .recv_offset = _recv_offset, \
39 }
40
41
42 struct nodnic_port_data_entry nodnic_port_data_table[] = {
43 PortDataEntry(nodnic_port_option_link_type, 0x0, 4, 0x1),
44 PortDataEntry(nodnic_port_option_mac_low, 0xc, 0, 0xFFFFFFFF),
45 PortDataEntry(nodnic_port_option_mac_high, 0x8, 0, 0xFFFF),
46 PortDataEntry(nodnic_port_option_log_cq_size, 0x6c, 0, 0x3F),
47 PortDataEntry(nodnic_port_option_reset_needed, 0x0, 31, 0x1),
48 PortDataEntry(nodnic_port_option_mac_filters_en, 0x4, 0, 0x1F),
49 PortDataEntry(nodnic_port_option_port_state, 0x0, 0, 0xF),
50 PortDataEntry(nodnic_port_option_network_en, 0x4, 31, 0x1),
51 PortDataEntry(nodnic_port_option_dma_en, 0x4, 30, 0x1),
52 PortDataEntry(nodnic_port_option_eq_addr_low, 0x74, 0, 0xFFFFFFFF),
53 PortDataEntry(nodnic_port_option_eq_addr_high, 0x70, 0, 0xFFFFFFFF),
54 PortDataEntry(nodnic_port_option_cq_addr_low, 0x6c, 12, 0xFFFFF),
55 PortDataEntry(nodnic_port_option_cq_addr_high, 0x68, 0, 0xFFFFFFFF),
56 PortDataEntry(nodnic_port_option_port_management_change_event, 0x0, 30, 0x1),
57 PortDataEntry(nodnic_port_option_port_promisc_en, 0x4, 29, 0x1),
58 #ifndef DEVICE_CX3
59 PortDataEntry(nodnic_port_option_arm_cq, 0x78, 8, 0xffffff),
60 #else
61 PortDataEntry(nodnic_port_option_arm_cq, 0x78, 8, 0xffff),
62 #endif
63 PortDataEntry(nodnic_port_option_port_promisc_multicast_en, 0x4, 28, 0x1),
64 #ifdef DEVICE_CX3
65 PortDataEntry(nodnic_port_option_crspace_en, 0x4, 27, 0x1),
66 #endif
67 PortDataEntry(nodnic_port_option_send_ring0_uar_index, 0x108, 0, 0xFFFFFFFF),
68 PortDataEntry(nodnic_port_option_send_ring1_uar_index, 0x10c, 0, 0xFFFFFFFF),
69 PortDataEntry(nodnic_port_option_cq_n_index, 0x118, 0, 0xFFFFFF),
70 };
71
72 #define MAX_QP_DATA_ENTRIES 5
73 struct nodnic_qp_data_entry nodnic_qp_data_teable[MAX_QP_DATA_ENTRIES] = {
74 QpDataEntry(NODNIC_QPT_SMI, 0, 0),
75 QpDataEntry(NODNIC_QPT_GSI, 0, 0),
76 QpDataEntry(NODNIC_QPT_UD, 0, 0),
77 QpDataEntry(NODNIC_QPT_RC, 0, 0),
78 QpDataEntry(NODNIC_QPT_ETH, 0x80, 0xC0),
79 };
80
81 #define MAX_NODNIC_PORTS 2
82 int nodnic_port_offset_table[MAX_NODNIC_PORTS] = {
83 0x100, //port 1 offset
84 0x280, //port 1 offset
85 };
86
87 mlx_status
nodnic_port_get_state(IN nodnic_port_priv * port_priv,OUT nodnic_port_state * state)88 nodnic_port_get_state(
89 IN nodnic_port_priv *port_priv,
90 OUT nodnic_port_state *state
91 )
92 {
93 mlx_status status = MLX_SUCCESS;
94 mlx_uint32 out = 0;
95
96 status = nodnic_port_query(port_priv,
97 nodnic_port_option_port_state, &out);
98 MLX_CHECK_STATUS(port_priv->device, status, query_err,
99 "nodnic_port_query failed");
100 *state = (nodnic_port_state)out;
101 query_err:
102 return status;
103 }
104 mlx_status
nodnic_port_get_type(IN nodnic_port_priv * port_priv,OUT nodnic_port_type * type)105 nodnic_port_get_type(
106 IN nodnic_port_priv *port_priv,
107 OUT nodnic_port_type *type
108 )
109 {
110 mlx_status status = MLX_SUCCESS;
111 mlx_uint32 out = 0;
112
113 if ( port_priv->port_type == NODNIC_PORT_TYPE_UNKNOWN){
114 status = nodnic_port_query(port_priv,
115 nodnic_port_option_link_type, &out);
116 MLX_FATAL_CHECK_STATUS(status, query_err,
117 "nodnic_port_query failed");
118 port_priv->port_type = (nodnic_port_type)out;
119 }
120 *type = port_priv->port_type;
121 query_err:
122 return status;
123 }
124
125 mlx_status
nodnic_port_query(IN nodnic_port_priv * port_priv,IN nodnic_port_option option,OUT mlx_uint32 * out)126 nodnic_port_query(
127 IN nodnic_port_priv *port_priv,
128 IN nodnic_port_option option,
129 OUT mlx_uint32 *out
130 )
131 {
132 mlx_status status = MLX_SUCCESS;
133 nodnic_device_priv *device_priv = NULL;
134 struct nodnic_port_data_entry *data_entry;
135 mlx_uint32 buffer = 0;
136 if( port_priv == NULL || out == NULL){
137 status = MLX_INVALID_PARAMETER;
138 goto invalid_parm;
139 }
140 device_priv = port_priv->device;
141
142 data_entry = &nodnic_port_data_table[option];
143
144 status = nodnic_cmd_read(device_priv,
145 port_priv->port_offset + data_entry->offset , &buffer);
146 MLX_CHECK_STATUS(device_priv, status, read_err,
147 "nodnic_cmd_read failed");
148 *out = (buffer >> data_entry->align) & data_entry->mask;
149 read_err:
150 invalid_parm:
151 return status;
152 }
153
154 mlx_status
nodnic_port_set(IN nodnic_port_priv * port_priv,IN nodnic_port_option option,IN mlx_uint32 in)155 nodnic_port_set(
156 IN nodnic_port_priv *port_priv,
157 IN nodnic_port_option option,
158 IN mlx_uint32 in
159 )
160 {
161 mlx_status status = MLX_SUCCESS;
162 nodnic_device_priv *device_priv = NULL;
163 struct nodnic_port_data_entry *data_entry;
164 mlx_uint32 buffer = 0;
165
166 if( port_priv == NULL ){
167 MLX_DEBUG_FATAL_ERROR("port_priv is NULL\n");
168 status = MLX_INVALID_PARAMETER;
169 goto invalid_parm;
170 }
171 device_priv = port_priv->device;
172 data_entry = &nodnic_port_data_table[option];
173
174 if( in > data_entry->mask ){
175 MLX_DEBUG_FATAL_ERROR("in > data_entry->mask (%d > %d)\n",
176 in, data_entry->mask);
177 status = MLX_INVALID_PARAMETER;
178 goto invalid_parm;
179 }
180 status = nodnic_cmd_read(device_priv,
181 port_priv->port_offset + data_entry->offset, &buffer);
182 MLX_FATAL_CHECK_STATUS(status, read_err,
183 "nodnic_cmd_read failed");
184 buffer = buffer & ~(data_entry->mask << data_entry->align);
185 buffer = buffer | (in << data_entry->align);
186 status = nodnic_cmd_write(device_priv,
187 port_priv->port_offset + data_entry->offset, buffer);
188 MLX_FATAL_CHECK_STATUS(status, write_err,
189 "nodnic_cmd_write failed");
190 write_err:
191 read_err:
192 invalid_parm:
193 return status;
194 }
195
196 mlx_status
nodnic_port_set_send_uar_offset(IN nodnic_port_priv * port_priv)197 nodnic_port_set_send_uar_offset(
198 IN nodnic_port_priv *port_priv
199 )
200 {
201 mlx_status status = MLX_SUCCESS;
202 mlx_uint32 out = 0;
203
204 if ( ! port_priv->device->device_cap.support_uar_tx_db ) {
205 MLX_DEBUG_INFO1 ( port_priv, "nodnic_port_set_send_uar_offset: tx db using uar is not supported \n");
206 status = MLX_UNSUPPORTED;
207 goto uar_not_supported;
208 }
209
210 status = nodnic_port_query(port_priv,
211 nodnic_port_option_send_ring0_uar_index, &out);
212 MLX_CHECK_STATUS(port_priv->device, status, query_err,
213 "nodnic_port_query failed");
214 port_priv->device->uar.offset = out << port_priv->device->device_cap.log_uar_page_size;
215 uar_not_supported:
216 query_err:
217 return status;
218 }
219
220 mlx_status
nodnic_port_read_reset_needed(IN nodnic_port_priv * port_priv,OUT mlx_boolean * reset_needed)221 nodnic_port_read_reset_needed(
222 IN nodnic_port_priv *port_priv,
223 OUT mlx_boolean *reset_needed
224 )
225 {
226 mlx_status status = MLX_SUCCESS;
227 mlx_uint32 out = 0;
228 status = nodnic_port_query(port_priv,
229 nodnic_port_option_reset_needed, &out);
230 MLX_CHECK_STATUS(port_priv->device, status, query_err,
231 "nodnic_port_query failed");
232 *reset_needed = (mlx_boolean)out;
233 query_err:
234 return status;
235 }
236
237 mlx_status
nodnic_port_read_port_management_change_event(IN nodnic_port_priv * port_priv,OUT mlx_boolean * change_event)238 nodnic_port_read_port_management_change_event(
239 IN nodnic_port_priv *port_priv,
240 OUT mlx_boolean *change_event
241 )
242 {
243 mlx_status status = MLX_SUCCESS;
244 mlx_uint32 out = 0;
245 status = nodnic_port_query(port_priv,
246 nodnic_port_option_port_management_change_event, &out);
247 MLX_CHECK_STATUS(port_priv->device, status, query_err,
248 "nodnic_port_query failed");
249 *change_event = (mlx_boolean)out;
250 query_err:
251 return status;
252 }
253
254 static
255 mlx_status
nodnic_port_allocate_dbr_dma(IN nodnic_port_priv * port_priv,IN struct nodnic_doorbell * nodnic_db,IN mlx_uint32 dbr_addr_low_ofst,IN mlx_uint32 dbr_addr_high_ofst,IN void ** dbr_addr,IN mlx_size size,IN void ** map)256 nodnic_port_allocate_dbr_dma (
257 IN nodnic_port_priv *port_priv,
258 IN struct nodnic_doorbell *nodnic_db,
259 IN mlx_uint32 dbr_addr_low_ofst,
260 IN mlx_uint32 dbr_addr_high_ofst,
261 IN void **dbr_addr,
262 IN mlx_size size,
263 IN void **map
264 )
265 {
266 mlx_status status = MLX_SUCCESS;
267 mlx_uint64 address = 0;
268 nodnic_device_priv *device_priv = NULL;
269
270 if( port_priv == NULL || nodnic_db == NULL ){
271 status = MLX_INVALID_PARAMETER;
272 goto invalid_parm;
273 }
274
275 device_priv = port_priv->device;
276 status = mlx_memory_alloc_dma(device_priv->utils,
277 size,
278 NODNIC_MEMORY_ALIGN,
279 (void **)dbr_addr
280 );
281 MLX_FATAL_CHECK_STATUS(status, alloc_db_record_err,
282 "doorbell record dma allocation error");
283
284 status = mlx_memory_map_dma(device_priv->utils,
285 (void *)(*dbr_addr),
286 size,
287 &nodnic_db->doorbell_physical,
288 map//nodnic_ring->map
289 );
290 MLX_FATAL_CHECK_STATUS(status, map_db_record_err,
291 "doorbell record map dma error");
292
293 address = (mlx_uint64)nodnic_db->doorbell_physical;
294 status = nodnic_cmd_write(device_priv,
295 dbr_addr_low_ofst,
296 (mlx_uint32)address);
297 MLX_FATAL_CHECK_STATUS(status, set_err,
298 "failed to set doorbell addr low");
299
300 address = address >> 32;
301 status = nodnic_cmd_write(device_priv,
302 dbr_addr_high_ofst,
303 (mlx_uint32)address);
304 MLX_FATAL_CHECK_STATUS(status, set_err,
305 "failed to set doorbell addr high");
306
307 return status;
308
309 set_err:
310 mlx_memory_ummap_dma(device_priv->utils, *map);
311 map_db_record_err:
312 mlx_memory_free_dma(device_priv->utils, size,
313 (void **)dbr_addr);
314 alloc_db_record_err:
315 invalid_parm:
316 return status;
317 }
318
319 static
320 mlx_status
nodnic_port_cq_dbr_dma_init(IN nodnic_port_priv * port_priv,OUT nodnic_cq ** cq)321 nodnic_port_cq_dbr_dma_init(
322 IN nodnic_port_priv *port_priv,
323 OUT nodnic_cq **cq
324 )
325 {
326 mlx_status status = MLX_SUCCESS;
327 nodnic_device_priv *device_priv = NULL;
328
329 if( port_priv == NULL ){
330 status = MLX_INVALID_PARAMETER;
331 goto invalid_parm;
332 }
333
334 device_priv = port_priv->device;
335 if ( ! device_priv->device_cap.support_bar_cq_ctrl ) {
336 status = MLX_UNSUPPORTED;
337 goto uar_arm_cq_db_unsupported;
338 }
339
340 #define NODNIC_PORT_ARM_CQ_DBR_ADDR_LOW_OFFSET 0x114
341 #define NODNIC_PORT_ARM_CQ_DBR_ADDR_HIGH_OFFSET 0x110
342
343 status = nodnic_port_allocate_dbr_dma ( port_priv,&(*cq)->arm_cq_doorbell,
344 port_priv->port_offset + NODNIC_PORT_ARM_CQ_DBR_ADDR_LOW_OFFSET,
345 port_priv->port_offset + NODNIC_PORT_ARM_CQ_DBR_ADDR_HIGH_OFFSET,
346 (void **)&port_priv->arm_cq_doorbell_record ,
347 sizeof(nodnic_arm_cq_db),
348 (void **)&((*cq)->arm_cq_doorbell.map));
349 MLX_FATAL_CHECK_STATUS(status, alloc_dbr_dma_err,
350 "failed to allocate doorbell record dma");
351 return status;
352
353 alloc_dbr_dma_err:
354 uar_arm_cq_db_unsupported:
355 invalid_parm:
356 return status;
357 }
358
359 mlx_status
nodnic_port_create_cq(IN nodnic_port_priv * port_priv,IN mlx_size cq_size,OUT nodnic_cq ** cq)360 nodnic_port_create_cq(
361 IN nodnic_port_priv *port_priv,
362 IN mlx_size cq_size,
363 OUT nodnic_cq **cq
364 )
365 {
366 mlx_status status = MLX_SUCCESS;
367 nodnic_device_priv *device_priv = NULL;
368 mlx_uint64 address = 0;
369 if( port_priv == NULL || cq == NULL){
370 status = MLX_INVALID_PARAMETER;
371 goto invalid_parm;
372 }
373
374 device_priv = port_priv->device;
375
376 status = mlx_memory_zalloc(device_priv->utils,
377 sizeof(nodnic_cq),(mlx_void **)cq);
378 MLX_FATAL_CHECK_STATUS(status, alloc_err,
379 "cq priv allocation error");
380
381 (*cq)->cq_size = cq_size;
382 status = mlx_memory_alloc_dma(device_priv->utils,
383 (*cq)->cq_size, NODNIC_MEMORY_ALIGN,
384 &(*cq)->cq_virt);
385 MLX_FATAL_CHECK_STATUS(status, dma_alloc_err,
386 "cq allocation error");
387
388 status = mlx_memory_map_dma(device_priv->utils,
389 (*cq)->cq_virt,
390 (*cq)->cq_size,
391 &(*cq)->cq_physical,
392 &(*cq)->map);
393 MLX_FATAL_CHECK_STATUS(status, cq_map_err,
394 "cq map error");
395
396 status = nodnic_port_cq_dbr_dma_init(port_priv,cq);
397
398 /* update cq address */
399 #define NODIC_CQ_ADDR_HIGH 0x68
400 #define NODIC_CQ_ADDR_LOW 0x6c
401 address = (mlx_uint64)(*cq)->cq_physical;
402 status = nodnic_port_set(port_priv, nodnic_port_option_cq_addr_low,
403 (mlx_uint32)(address) >> 12);
404 MLX_FATAL_CHECK_STATUS(status, dma_set_addr_low_err,
405 "cq set addr low error");
406 address = address >> 32;
407 status = nodnic_port_set(port_priv, nodnic_port_option_cq_addr_high,
408 (mlx_uint32)address);
409 MLX_FATAL_CHECK_STATUS(status, dma_set_addr_high_err,
410 "cq set addr high error");
411 return status;
412 dma_set_addr_high_err:
413 dma_set_addr_low_err:
414 mlx_memory_ummap_dma(device_priv->utils, (*cq)->map);
415 cq_map_err:
416 mlx_memory_free_dma(device_priv->utils, (*cq)->cq_size,
417 (void **)&((*cq)->cq_virt));
418 dma_alloc_err:
419 mlx_memory_free(device_priv->utils, (void **)cq);
420 alloc_err:
421 invalid_parm:
422 return status;
423 }
424
425 mlx_status
nodnic_port_destroy_cq(IN nodnic_port_priv * port_priv,IN nodnic_cq * cq)426 nodnic_port_destroy_cq(
427 IN nodnic_port_priv *port_priv,
428 IN nodnic_cq *cq
429 )
430 {
431 mlx_status status = MLX_SUCCESS;
432 nodnic_device_priv *device_priv = NULL;
433
434 if( port_priv == NULL || cq == NULL){
435 status = MLX_INVALID_PARAMETER;
436 goto invalid_parm;
437 }
438 device_priv = port_priv->device;
439
440 if ( device_priv->device_cap.support_bar_cq_ctrl ){
441 status = mlx_memory_ummap_dma(device_priv->utils,
442 cq->arm_cq_doorbell.map);
443 if( status != MLX_SUCCESS){
444 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
445 }
446
447 status = mlx_memory_free_dma(device_priv->utils,
448 sizeof(nodnic_arm_cq_db),
449 (void **)&(port_priv->arm_cq_doorbell_record));
450 if( status != MLX_SUCCESS){
451 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
452 }
453 }
454
455 mlx_memory_ummap_dma(device_priv->utils, cq->map);
456
457 mlx_memory_free_dma(device_priv->utils, cq->cq_size,
458 (void **)&(cq->cq_virt));
459
460 mlx_memory_free(device_priv->utils, (void **)&cq);
461 invalid_parm:
462 return status;
463 }
464
465 static
466 mlx_status
nodnic_port_allocate_ring_db_dma(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * nodnic_ring,IN struct nodnic_doorbell * nodnic_db)467 nodnic_port_allocate_ring_db_dma (
468 IN nodnic_port_priv *port_priv,
469 IN struct nodnic_ring *nodnic_ring,
470 IN struct nodnic_doorbell *nodnic_db
471 )
472 {
473 mlx_status status = MLX_SUCCESS;
474
475 if( port_priv == NULL || nodnic_ring == NULL || nodnic_db == NULL ){
476 status = MLX_INVALID_PARAMETER;
477 goto invalid_parm;
478 }
479 #define NODNIC_RING_DBR_ADDR_LOW_OFFSET 0x1C
480 #define NODNIC_RING_DBR_ADDR_HIGH_OFFSET 0x18
481 status = nodnic_port_allocate_dbr_dma ( port_priv,nodnic_db,
482 nodnic_ring->offset + NODNIC_RING_DBR_ADDR_LOW_OFFSET,
483 nodnic_ring->offset + NODNIC_RING_DBR_ADDR_HIGH_OFFSET,
484 (void **)&nodnic_db->qp_doorbell_record,
485 sizeof(nodnic_qp_db),
486 (void **)&nodnic_ring->map );
487 MLX_FATAL_CHECK_STATUS(status, alloc_dbr_dma_err,
488 "failed to allocate doorbell record dma");
489
490 return status;
491 alloc_dbr_dma_err:
492 invalid_parm:
493 return status;
494 }
495
496 static
497 mlx_status
nodnic_port_rx_pi_dma_alloc(IN nodnic_port_priv * port_priv,OUT nodnic_qp ** qp)498 nodnic_port_rx_pi_dma_alloc(
499 IN nodnic_port_priv *port_priv,
500 OUT nodnic_qp **qp
501 )
502 {
503 mlx_status status = MLX_SUCCESS;
504 nodnic_device_priv *device_priv = NULL;
505
506 if( port_priv == NULL || qp == NULL){
507 status = MLX_INVALID_PARAMETER;
508 goto invalid_parm;
509 }
510
511 device_priv = port_priv->device;
512
513 if ( ! device_priv->device_cap.support_rx_pi_dma ) {
514 goto rx_pi_dma_unsupported;
515 }
516
517 if ( device_priv->device_cap.support_rx_pi_dma ) {
518 status = nodnic_port_allocate_ring_db_dma(port_priv,
519 &(*qp)->receive.nodnic_ring,&(*qp)->receive.nodnic_ring.recv_doorbell);
520 MLX_FATAL_CHECK_STATUS(status, dma_alloc_err,
521 "rx doorbell dma allocation error");
522 }
523
524 return status;
525
526 dma_alloc_err:
527 rx_pi_dma_unsupported:
528 invalid_parm:
529 return status;
530 }
531
532 static
533 mlx_status
nodnic_port_send_db_dma(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * ring,IN mlx_uint16 index)534 nodnic_port_send_db_dma(
535 IN nodnic_port_priv *port_priv,
536 IN struct nodnic_ring *ring,
537 IN mlx_uint16 index
538 )
539 {
540 mlx_uint32 swapped = 0;
541 mlx_uint32 index32 = index;
542 mlx_memory_cpu_to_be32(port_priv->device->utils, index32, &swapped);
543 ring->send_doorbell.qp_doorbell_record->send_db = swapped;
544
545 return MLX_SUCCESS;
546 }
547
548 static
549 mlx_status
nodnic_port_tx_dbr_dma_init(IN nodnic_port_priv * port_priv,OUT nodnic_qp ** qp)550 nodnic_port_tx_dbr_dma_init(
551 IN nodnic_port_priv *port_priv,
552 OUT nodnic_qp **qp
553 )
554 {
555 mlx_status status = MLX_SUCCESS;
556 nodnic_device_priv *device_priv = NULL;
557
558 if( port_priv == NULL || qp == NULL){
559 status = MLX_INVALID_PARAMETER;
560 goto invalid_parm;
561 }
562
563 device_priv = port_priv->device;
564
565 if ( ! device_priv->device_cap.support_uar_tx_db || ! device_priv->uar.offset ) {
566 status = MLX_UNSUPPORTED;
567 goto uar_tx_db_unsupported;
568 }
569 status = nodnic_port_allocate_ring_db_dma(port_priv,
570 &(*qp)->send.nodnic_ring,&(*qp)->send.nodnic_ring.send_doorbell);
571 MLX_FATAL_CHECK_STATUS(status, dma_alloc_err,
572 "tx doorbell dma allocation error");
573 port_priv->send_doorbell = nodnic_port_send_db_dma;
574
575 return status;
576
577 dma_alloc_err:
578 uar_tx_db_unsupported:
579 invalid_parm:
580
581 return status;
582 }
583
584 mlx_status
nodnic_port_create_qp(IN nodnic_port_priv * port_priv,IN nodnic_queue_pair_type type,IN mlx_size send_wq_size,IN mlx_uint32 send_wqe_num,IN mlx_size receive_wq_size,IN mlx_uint32 recv_wqe_num,OUT nodnic_qp ** qp)585 nodnic_port_create_qp(
586 IN nodnic_port_priv *port_priv,
587 IN nodnic_queue_pair_type type,
588 IN mlx_size send_wq_size,
589 IN mlx_uint32 send_wqe_num,
590 IN mlx_size receive_wq_size,
591 IN mlx_uint32 recv_wqe_num,
592 OUT nodnic_qp **qp
593 )
594 {
595 mlx_status status = MLX_SUCCESS;
596 nodnic_device_priv *device_priv = NULL;
597 mlx_uint32 max_ring_size = 0;
598 mlx_uint64 address = 0;
599 mlx_uint32 log_size = 0;
600 if( port_priv == NULL || qp == NULL){
601 status = MLX_INVALID_PARAMETER;
602 goto invalid_parm;
603 }
604
605 device_priv = port_priv->device;
606 max_ring_size = (1 << device_priv->device_cap.log_max_ring_size);
607 if( send_wq_size > max_ring_size ||
608 receive_wq_size > max_ring_size ){
609 status = MLX_INVALID_PARAMETER;
610 goto invalid_parm;
611 }
612
613 status = mlx_memory_zalloc(device_priv->utils,
614 sizeof(nodnic_qp),(mlx_void **)qp);
615 MLX_FATAL_CHECK_STATUS(status, alloc_err,
616 "qp allocation error");
617
618 if( nodnic_qp_data_teable[type].send_offset == 0 ||
619 nodnic_qp_data_teable[type].recv_offset == 0){
620 status = MLX_INVALID_PARAMETER;
621 goto invalid_type;
622 }
623
624 (*qp)->send.nodnic_ring.offset = port_priv->port_offset +
625 nodnic_qp_data_teable[type].send_offset;
626 (*qp)->receive.nodnic_ring.offset = port_priv->port_offset +
627 nodnic_qp_data_teable[type].recv_offset;
628
629 status = mlx_memory_alloc_dma(device_priv->utils,
630 send_wq_size, NODNIC_MEMORY_ALIGN,
631 (void*)&(*qp)->send.wqe_virt);
632 MLX_FATAL_CHECK_STATUS(status, send_alloc_err,
633 "send wq allocation error");
634
635 status = mlx_memory_alloc_dma(device_priv->utils,
636 receive_wq_size, NODNIC_MEMORY_ALIGN,
637 &(*qp)->receive.wqe_virt);
638 MLX_FATAL_CHECK_STATUS(status, receive_alloc_err,
639 "receive wq allocation error");
640
641 status = mlx_memory_map_dma(device_priv->utils,
642 (*qp)->send.wqe_virt,
643 send_wq_size,
644 &(*qp)->send.nodnic_ring.wqe_physical,
645 &(*qp)->send.nodnic_ring.map);
646 MLX_FATAL_CHECK_STATUS(status, send_map_err,
647 "send wq map error");
648
649 status = mlx_memory_map_dma(device_priv->utils,
650 (*qp)->receive.wqe_virt,
651 receive_wq_size,
652 &(*qp)->receive.nodnic_ring.wqe_physical,
653 &(*qp)->receive.nodnic_ring.map);
654 MLX_FATAL_CHECK_STATUS(status, receive_map_err,
655 "receive wq map error");
656
657 status = nodnic_port_rx_pi_dma_alloc(port_priv,qp);
658 MLX_FATAL_CHECK_STATUS(status, rx_pi_dma_alloc_err,
659 "receive db dma error");
660
661 status = nodnic_port_tx_dbr_dma_init(port_priv,qp);
662
663
664 (*qp)->send.nodnic_ring.wq_size = send_wq_size;
665 (*qp)->send.nodnic_ring.num_wqes = send_wqe_num;
666 (*qp)->receive.nodnic_ring.wq_size = receive_wq_size;
667 (*qp)->receive.nodnic_ring.num_wqes = recv_wqe_num;
668
669 /* Set Ownership bit in Send/receive queue (0 - recv ; 1 - send) */
670 mlx_memory_set(device_priv->utils, (*qp)->send.wqe_virt, 0xff, send_wq_size );
671 mlx_memory_set(device_priv->utils, (*qp)->receive.wqe_virt, 0, recv_wqe_num );
672
673 /* update send ring */
674 #define NODIC_RING_QP_ADDR_HIGH 0x0
675 #define NODIC_RING_QP_ADDR_LOW 0x4
676 address = (mlx_uint64)(*qp)->send.nodnic_ring.wqe_physical;
677 status = nodnic_cmd_write(device_priv, (*qp)->send.nodnic_ring.offset +
678 NODIC_RING_QP_ADDR_HIGH,
679 (mlx_uint32)(address >> 32));
680 MLX_FATAL_CHECK_STATUS(status, write_send_addr_err,
681 "send address write error 1");
682 mlx_utils_ilog2((*qp)->send.nodnic_ring.wq_size, &log_size);
683 address = address | log_size;
684 status = nodnic_cmd_write(device_priv, (*qp)->send.nodnic_ring.offset +
685 NODIC_RING_QP_ADDR_LOW,
686 (mlx_uint32)address);
687 MLX_FATAL_CHECK_STATUS(status, write_send_addr_err,
688 "send address write error 2");
689 /* update receive ring */
690 address = (mlx_uint64)(*qp)->receive.nodnic_ring.wqe_physical;
691 status = nodnic_cmd_write(device_priv, (*qp)->receive.nodnic_ring.offset +
692 NODIC_RING_QP_ADDR_HIGH,
693 (mlx_uint32)(address >> 32));
694 MLX_FATAL_CHECK_STATUS(status, write_recv_addr_err,
695 "receive address write error 1");
696 mlx_utils_ilog2((*qp)->receive.nodnic_ring.wq_size, &log_size);
697 address = address | log_size;
698 status = nodnic_cmd_write(device_priv, (*qp)->receive.nodnic_ring.offset +
699 NODIC_RING_QP_ADDR_LOW,
700 (mlx_uint32)address);
701 MLX_FATAL_CHECK_STATUS(status, write_recv_addr_err,
702 "receive address write error 2");
703
704 return status;
705 write_recv_addr_err:
706 write_send_addr_err:
707 mlx_memory_ummap_dma(device_priv->utils, (*qp)->receive.nodnic_ring.map);
708 rx_pi_dma_alloc_err:
709 receive_map_err:
710 mlx_memory_ummap_dma(device_priv->utils, (*qp)->send.nodnic_ring.map);
711 send_map_err:
712 mlx_memory_free_dma(device_priv->utils, receive_wq_size,
713 &((*qp)->receive.wqe_virt));
714 receive_alloc_err:
715 mlx_memory_free_dma(device_priv->utils, send_wq_size,
716 (void **)&((*qp)->send.wqe_virt));
717 send_alloc_err:
718 invalid_type:
719 mlx_memory_free(device_priv->utils, (void **)qp);
720 alloc_err:
721 invalid_parm:
722 return status;
723 }
724
725 mlx_status
nodnic_port_destroy_qp(IN nodnic_port_priv * port_priv,IN nodnic_queue_pair_type type,IN nodnic_qp * qp)726 nodnic_port_destroy_qp(
727 IN nodnic_port_priv *port_priv,
728 IN nodnic_queue_pair_type type __attribute__((unused)),
729 IN nodnic_qp *qp
730 )
731 {
732 mlx_status status = MLX_SUCCESS;
733 nodnic_device_priv *device_priv = port_priv->device;
734
735 status = mlx_memory_ummap_dma(device_priv->utils,
736 qp->receive.nodnic_ring.map);
737 if( status != MLX_SUCCESS){
738 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
739 }
740
741 status = mlx_memory_ummap_dma(device_priv->utils, qp->send.nodnic_ring.map);
742 if( status != MLX_SUCCESS){
743 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
744 }
745
746 if ( device_priv->device_cap.support_rx_pi_dma ){
747 status = mlx_memory_ummap_dma(device_priv->utils,
748 qp->receive.nodnic_ring.recv_doorbell.map);
749 if( status != MLX_SUCCESS){
750 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
751 }
752
753 status = mlx_memory_free_dma(device_priv->utils,
754 sizeof(nodnic_qp_db),
755 (void **)&(qp->receive.nodnic_ring.recv_doorbell.qp_doorbell_record));
756 if( status != MLX_SUCCESS){
757 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
758 }
759 }
760
761 if ( device_priv->device_cap.support_uar_tx_db || ! device_priv->uar.offset){
762 status = mlx_memory_ummap_dma(device_priv->utils,
763 qp->send.nodnic_ring.send_doorbell.map);
764 if( status != MLX_SUCCESS){
765 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
766 }
767
768 status = mlx_memory_free_dma(device_priv->utils,
769 sizeof(nodnic_qp_db),
770 (void **)&(qp->send.nodnic_ring.send_doorbell.qp_doorbell_record));
771 if( status != MLX_SUCCESS){
772 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
773 }
774 }
775
776 status = mlx_memory_free_dma(device_priv->utils,
777 qp->receive.nodnic_ring.wq_size,
778 (void **)&(qp->receive.wqe_virt));
779 if( status != MLX_SUCCESS){
780 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
781 }
782 status = mlx_memory_free_dma(device_priv->utils,
783 qp->send.nodnic_ring.wq_size,
784 (void **)&(qp->send.wqe_virt));
785 if( status != MLX_SUCCESS){
786 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
787 }
788 status = mlx_memory_free(device_priv->utils, (void **)&qp);
789 if( status != MLX_SUCCESS){
790 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free failed (Status = %d)\n", status);
791 }
792 return status;
793 }
794
795 mlx_status
nodnic_port_get_qpn(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * ring,OUT mlx_uint32 * qpn)796 nodnic_port_get_qpn(
797 IN nodnic_port_priv *port_priv,
798 IN struct nodnic_ring *ring,
799 OUT mlx_uint32 *qpn
800 )
801 {
802 mlx_status status = MLX_SUCCESS;
803 mlx_uint32 buffer = 0;
804 if( ring == NULL || qpn == NULL){
805 status = MLX_INVALID_PARAMETER;
806 goto bad_param;
807 }
808 if( ring->qpn != 0 ){
809 *qpn = ring->qpn;
810 goto success;
811 }
812 #define NODNIC_RING_QPN_OFFSET 0xc
813 #define NODNIC_RING_QPN_MASK 0xFFFFFF
814 status = nodnic_cmd_read(port_priv->device,
815 ring->offset + NODNIC_RING_QPN_OFFSET,
816 &buffer);
817 MLX_FATAL_CHECK_STATUS(status, read_err,
818 "nodnic_cmd_read failed");
819 ring->qpn = buffer & NODNIC_RING_QPN_MASK;
820 *qpn = ring->qpn;
821 read_err:
822 success:
823 bad_param:
824 return status;
825 }
826
827 #ifdef DEVICE_CX3
828 static
829 mlx_status
nodnic_port_send_db_connectx3(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * ring,IN mlx_uint16 index)830 nodnic_port_send_db_connectx3(
831 IN nodnic_port_priv *port_priv,
832 IN struct nodnic_ring *ring __attribute__((unused)),
833 IN mlx_uint16 index
834 )
835 {
836 nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw;
837 mlx_uint32 index32 = index;
838 mlx_pci_mem_write(port_priv->device->utils, MlxPciWidthUint32, 0,
839 (mlx_uintn)&(ptr->send_doorbell), 1, &index32);
840 return MLX_SUCCESS;
841 }
842
843 static
844 mlx_status
nodnic_port_recv_db_connectx3(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * ring,IN mlx_uint16 index)845 nodnic_port_recv_db_connectx3(
846 IN nodnic_port_priv *port_priv,
847 IN struct nodnic_ring *ring __attribute__((unused)),
848 IN mlx_uint16 index
849 )
850 {
851 nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw;
852 mlx_uint32 index32 = index;
853 mlx_pci_mem_write(port_priv->device->utils, MlxPciWidthUint32, 0,
854 (mlx_uintn)&(ptr->recv_doorbell), 1, &index32);
855 return MLX_SUCCESS;
856 }
857 #endif
858 static
859 mlx_status
nodnic_port_recv_db_dma(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * ring,IN mlx_uint16 index)860 nodnic_port_recv_db_dma(
861 IN nodnic_port_priv *port_priv __attribute__((unused)),
862 IN struct nodnic_ring *ring,
863 IN mlx_uint16 index
864 )
865 {
866 mlx_uint32 swapped = 0;
867 mlx_uint32 index32 = index;
868 mlx_memory_cpu_to_be32(port_priv->device->utils, index32, &swapped);
869 ring->recv_doorbell.qp_doorbell_record->recv_db = swapped;
870 return MLX_SUCCESS;
871 }
872
873 mlx_status
nodnic_port_update_ring_doorbell(IN nodnic_port_priv * port_priv,IN struct nodnic_ring * ring,IN mlx_uint16 index)874 nodnic_port_update_ring_doorbell(
875 IN nodnic_port_priv *port_priv,
876 IN struct nodnic_ring *ring,
877 IN mlx_uint16 index
878 )
879 {
880 mlx_status status = MLX_SUCCESS;
881 mlx_uint32 buffer = 0;
882 if( ring == NULL ){
883 status = MLX_INVALID_PARAMETER;
884 goto bad_param;
885 }
886 #define NODNIC_RING_RING_OFFSET 0x8
887 buffer = (mlx_uint32)((index & 0xFFFF)<< 8);
888 status = nodnic_cmd_write(port_priv->device,
889 ring->offset + NODNIC_RING_RING_OFFSET,
890 buffer);
891 MLX_CHECK_STATUS(port_priv->device, status, write_err,
892 "nodnic_cmd_write failed");
893 write_err:
894 bad_param:
895 return status;
896 }
897
898 mlx_status
nodnic_port_get_cq_size(IN nodnic_port_priv * port_priv,OUT mlx_uint64 * cq_size)899 nodnic_port_get_cq_size(
900 IN nodnic_port_priv *port_priv,
901 OUT mlx_uint64 *cq_size
902 )
903 {
904 mlx_status status = MLX_SUCCESS;
905 mlx_uint32 out = 0;
906 status = nodnic_port_query(port_priv, nodnic_port_option_log_cq_size, &out);
907 MLX_FATAL_CHECK_STATUS(status, query_err,
908 "nodnic_port_query failed");
909 *cq_size = 1 << out;
910 query_err:
911 return status;
912 }
913
914 mlx_status
nodnic_port_allocate_eq(IN nodnic_port_priv * port_priv,IN mlx_uint8 log_eq_size)915 nodnic_port_allocate_eq(
916 IN nodnic_port_priv *port_priv,
917 IN mlx_uint8 log_eq_size
918 )
919 {
920 mlx_status status = MLX_SUCCESS;
921 nodnic_device_priv *device_priv = NULL;
922 mlx_uint64 address = 0;
923
924 if( port_priv == NULL ){
925 status = MLX_INVALID_PARAMETER;
926 goto bad_param;
927 }
928
929 device_priv = port_priv->device;
930 port_priv->eq.eq_size = ( ( 1 << log_eq_size ) * 1024 ); /* Size is in KB */
931 status = mlx_memory_alloc_dma(device_priv->utils,
932 port_priv->eq.eq_size,
933 NODNIC_MEMORY_ALIGN,
934 &port_priv->eq.eq_virt);
935 MLX_FATAL_CHECK_STATUS(status, alloc_err,
936 "eq allocation error");
937
938 status = mlx_memory_map_dma(device_priv->utils,
939 port_priv->eq.eq_virt,
940 port_priv->eq.eq_size,
941 &port_priv->eq.eq_physical,
942 &port_priv->eq.map);
943 MLX_FATAL_CHECK_STATUS(status, map_err,
944 "eq map error");
945
946 address = port_priv->eq.eq_physical;
947 status = nodnic_port_set(port_priv, nodnic_port_option_eq_addr_low,
948 (mlx_uint32)address);
949 MLX_FATAL_CHECK_STATUS(status, set_err,
950 "failed to set eq addr low");
951 address = (address >> 32);
952 status = nodnic_port_set(port_priv, nodnic_port_option_eq_addr_high,
953 (mlx_uint32)address);
954 MLX_FATAL_CHECK_STATUS(status, set_err,
955 "failed to set eq addr high");
956 return status;
957 set_err:
958 mlx_memory_ummap_dma(device_priv->utils, port_priv->eq.map);
959 map_err:
960 mlx_memory_free_dma(device_priv->utils,
961 port_priv->eq.eq_size,
962 (void **)&(port_priv->eq.eq_virt));
963 alloc_err:
964 bad_param:
965 return status;
966 }
967 mlx_status
nodnic_port_free_eq(IN nodnic_port_priv * port_priv)968 nodnic_port_free_eq(
969 IN nodnic_port_priv *port_priv
970 )
971 {
972 mlx_status status = MLX_SUCCESS;
973 nodnic_device_priv *device_priv = NULL;
974
975 if( port_priv == NULL ){
976 status = MLX_INVALID_PARAMETER;
977 goto bad_param;
978 }
979
980 device_priv = port_priv->device;
981 mlx_memory_ummap_dma(device_priv->utils, port_priv->eq.map);
982
983 mlx_memory_free_dma(device_priv->utils,
984 port_priv->eq.eq_size,
985 (void **)&(port_priv->eq.eq_virt));
986
987 bad_param:
988 return status;
989 }
990
991 mlx_status
nodnic_port_add_mac_filter(IN nodnic_port_priv * port_priv,IN mlx_mac_address mac)992 nodnic_port_add_mac_filter(
993 IN nodnic_port_priv *port_priv,
994 IN mlx_mac_address mac
995 )
996 {
997 mlx_status status = MLX_SUCCESS;
998 nodnic_device_priv *device= NULL;;
999 mlx_uint8 index = 0;
1000 mlx_uint32 out = 0;
1001 mlx_uint32 mac_filters_en = 0;
1002 mlx_uint32 address = 0;
1003 mlx_mac_address zero_mac;
1004 mlx_utils *utils = NULL;
1005
1006 if( port_priv == NULL){
1007 status = MLX_INVALID_PARAMETER;
1008 goto bad_param;
1009 }
1010
1011 device = port_priv->device;
1012 utils = device->utils;
1013
1014 mlx_memory_set(utils, &zero_mac, 0, sizeof(zero_mac));
1015 /* check if mac already exists */
1016 for( ; index < NODNIC_MAX_MAC_FILTERS ; index ++) {
1017 mlx_memory_cmp(utils, &port_priv->mac_filters[index], &mac,
1018 sizeof(mac), &out);
1019 if ( out == 0 ){
1020 status = MLX_FAILED;
1021 goto already_exists;
1022 }
1023 }
1024
1025 /* serch for available mac filter slot */
1026 for (index = 0 ; index < NODNIC_MAX_MAC_FILTERS ; index ++) {
1027 mlx_memory_cmp(utils, &port_priv->mac_filters[index], &zero_mac,
1028 sizeof(zero_mac), &out);
1029 if ( out == 0 ){
1030 break;
1031 }
1032 }
1033 if ( index >= NODNIC_MAX_MAC_FILTERS ){
1034 status = MLX_FAILED;
1035 goto mac_list_full;
1036 }
1037
1038 status = nodnic_port_query(port_priv, nodnic_port_option_mac_filters_en,
1039 &mac_filters_en);
1040 MLX_CHECK_STATUS(device, status , query_err,
1041 "nodnic_port_query failed");
1042 if(mac_filters_en & (1 << index)){
1043 status = MLX_FAILED;
1044 goto mac_list_full;
1045 }
1046 port_priv->mac_filters[index] = mac;
1047
1048 // set mac filter
1049 address = port_priv->port_offset + NODNIC_PORT_MAC_FILTERS_OFFSET +
1050 (0x8 * index);
1051
1052 status = nodnic_cmd_write(device, address, mac.high );
1053 MLX_CHECK_STATUS(device, status, write_err, "set mac high failed");
1054 status = nodnic_cmd_write(device, address + 0x4, mac.low );
1055 MLX_CHECK_STATUS(device, status, write_err, "set mac low failed");
1056
1057 // enable mac filter
1058 mac_filters_en = mac_filters_en | (1 << index);
1059 status = nodnic_port_set(port_priv, nodnic_port_option_mac_filters_en,
1060 mac_filters_en);
1061 MLX_CHECK_STATUS(device, status , set_err,
1062 "nodnic_port_set failed");
1063 set_err:
1064 write_err:
1065 query_err:
1066 mac_list_full:
1067 already_exists:
1068 bad_param:
1069 return status;
1070 }
1071
1072 mlx_status
nodnic_port_remove_mac_filter(IN nodnic_port_priv * port_priv,IN mlx_mac_address mac)1073 nodnic_port_remove_mac_filter(
1074 IN nodnic_port_priv *port_priv,
1075 IN mlx_mac_address mac
1076 )
1077 {
1078 mlx_status status = MLX_SUCCESS;
1079 nodnic_device_priv *device= NULL;;
1080 mlx_uint8 index = 0;
1081 mlx_uint32 out = 0;
1082 mlx_uint32 mac_filters_en = 0;
1083 mlx_mac_address zero_mac;
1084 mlx_utils *utils = NULL;
1085
1086 if( port_priv == NULL){
1087 status = MLX_INVALID_PARAMETER;
1088 goto bad_param;
1089 }
1090
1091 device = port_priv->device;
1092 utils = device->utils;
1093
1094 mlx_memory_set(utils, &zero_mac, 0, sizeof(zero_mac));
1095 /* serch for mac filter */
1096 for( ; index < NODNIC_MAX_MAC_FILTERS ; index ++) {
1097 mlx_memory_cmp(utils, &port_priv->mac_filters[index], &mac,
1098 sizeof(mac), &out);
1099 if ( out == 0 ){
1100 break;
1101 }
1102 }
1103 if ( index == NODNIC_MAX_MAC_FILTERS ){
1104 status = MLX_FAILED;
1105 goto mac_not_found;
1106 }
1107
1108 status = nodnic_port_query(port_priv, nodnic_port_option_mac_filters_en,
1109 &mac_filters_en);
1110 MLX_CHECK_STATUS(device, status , query_err,
1111 "nodnic_port_query failed");
1112 if((mac_filters_en & (1 << index)) == 0){
1113 status = MLX_FAILED;
1114 goto mac_not_en;
1115 }
1116 port_priv->mac_filters[index] = zero_mac;
1117
1118 // disable mac filter
1119 mac_filters_en = mac_filters_en & ~(1 << index);
1120 status = nodnic_port_set(port_priv, nodnic_port_option_mac_filters_en,
1121 mac_filters_en);
1122 MLX_CHECK_STATUS(device, status , set_err,
1123 "nodnic_port_set failed");
1124 set_err:
1125 query_err:
1126 mac_not_en:
1127 mac_not_found:
1128 bad_param:
1129 return status;
1130 }
1131
1132 static
1133 mlx_status
nodnic_port_set_network(IN nodnic_port_priv * port_priv,IN mlx_boolean value)1134 nodnic_port_set_network(
1135 IN nodnic_port_priv *port_priv,
1136 IN mlx_boolean value
1137 )
1138 {
1139 mlx_status status = MLX_SUCCESS;
1140 /*mlx_uint32 network_valid = 0;
1141 mlx_uint8 try = 0;*/
1142
1143 status = nodnic_port_set(port_priv, nodnic_port_option_network_en, value);
1144 MLX_CHECK_STATUS(port_priv->device, status, set_err,
1145 "nodnic_port_set failed");
1146 port_priv->network_state = value;
1147 set_err:
1148 return status;
1149 }
1150
1151 #ifdef DEVICE_CX3
1152 static
1153 mlx_status
nodnic_port_set_dma_connectx3(IN nodnic_port_priv * port_priv,IN mlx_boolean value)1154 nodnic_port_set_dma_connectx3(
1155 IN nodnic_port_priv *port_priv,
1156 IN mlx_boolean value
1157 )
1158 {
1159 mlx_utils *utils = port_priv->device->utils;
1160 nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw;
1161 mlx_uint32 data = (value ? 0xffffffff : 0x0);
1162 mlx_pci_mem_write(utils, MlxPciWidthUint32, 0,
1163 (mlx_uintn)&(ptr->dma_en), 1, &data);
1164 return MLX_SUCCESS;
1165 }
1166 #endif
1167
1168 static
1169 mlx_status
nodnic_port_set_dma(IN nodnic_port_priv * port_priv,IN mlx_boolean value)1170 nodnic_port_set_dma(
1171 IN nodnic_port_priv *port_priv,
1172 IN mlx_boolean value
1173 )
1174 {
1175 return nodnic_port_set(port_priv, nodnic_port_option_dma_en, value);
1176 }
1177
1178 static
1179 mlx_status
nodnic_port_check_and_set_dma(IN nodnic_port_priv * port_priv,IN mlx_boolean value)1180 nodnic_port_check_and_set_dma(
1181 IN nodnic_port_priv *port_priv,
1182 IN mlx_boolean value
1183 )
1184 {
1185 mlx_status status = MLX_SUCCESS;
1186 if ( port_priv->dma_state == value ) {
1187 MLX_DEBUG_WARN(port_priv->device,
1188 "nodnic_port_check_and_set_dma: already %s\n",
1189 (value ? "enabled" : "disabled"));
1190 status = MLX_SUCCESS;
1191 goto set_out;
1192 }
1193
1194 status = port_priv->set_dma(port_priv, value);
1195 MLX_CHECK_STATUS(port_priv->device, status, set_err,
1196 "nodnic_port_set failed");
1197 port_priv->dma_state = value;
1198 set_err:
1199 set_out:
1200 return status;
1201 }
1202
1203
1204 mlx_status
nodnic_port_set_promisc(IN nodnic_port_priv * port_priv,IN mlx_boolean value)1205 nodnic_port_set_promisc(
1206 IN nodnic_port_priv *port_priv,
1207 IN mlx_boolean value
1208 ){
1209 mlx_status status = MLX_SUCCESS;
1210 mlx_uint32 buffer = value;
1211
1212 status = nodnic_port_set(port_priv, nodnic_port_option_port_promisc_en, buffer);
1213 MLX_CHECK_STATUS(port_priv->device, status, set_err,
1214 "nodnic_port_set failed");
1215 set_err:
1216 return status;
1217 }
1218
1219 mlx_status
nodnic_port_set_promisc_multicast(IN nodnic_port_priv * port_priv,IN mlx_boolean value)1220 nodnic_port_set_promisc_multicast(
1221 IN nodnic_port_priv *port_priv,
1222 IN mlx_boolean value
1223 ){
1224 mlx_status status = MLX_SUCCESS;
1225 mlx_uint32 buffer = value;
1226
1227 status = nodnic_port_set(port_priv, nodnic_port_option_port_promisc_multicast_en, buffer);
1228 MLX_CHECK_STATUS(port_priv->device, status, set_err,
1229 "nodnic_port_set failed");
1230 set_err:
1231 return status;
1232 }
1233
1234 mlx_status
nodnic_port_init(IN nodnic_port_priv * port_priv)1235 nodnic_port_init(
1236 IN nodnic_port_priv *port_priv
1237 )
1238 {
1239 mlx_status status = MLX_SUCCESS;
1240
1241 if( port_priv == NULL ){
1242 status = MLX_INVALID_PARAMETER;
1243 goto bad_param;
1244 }
1245
1246 status = nodnic_port_set_network(port_priv, TRUE);
1247 MLX_FATAL_CHECK_STATUS(status, set_err,
1248 "nodnic_port_set_network failed");
1249 set_err:
1250 bad_param:
1251 return status;
1252 }
1253
1254 mlx_status
nodnic_port_close(IN nodnic_port_priv * port_priv)1255 nodnic_port_close(
1256 IN nodnic_port_priv *port_priv
1257 )
1258 {
1259 mlx_status status = MLX_SUCCESS;
1260
1261 if( port_priv == NULL ){
1262 status = MLX_INVALID_PARAMETER;
1263 goto bad_param;
1264 }
1265
1266 status = nodnic_port_set_network(port_priv, FALSE);
1267 MLX_FATAL_CHECK_STATUS(status, set_err,
1268 "nodnic_port_set_network failed");
1269 set_err:
1270 bad_param:
1271 return status;
1272 }
1273
1274 mlx_status
nodnic_port_enable_dma(IN nodnic_port_priv * port_priv)1275 nodnic_port_enable_dma(
1276 IN nodnic_port_priv *port_priv
1277 )
1278 {
1279 mlx_status status = MLX_SUCCESS;
1280
1281 if( port_priv == NULL ){
1282 status = MLX_INVALID_PARAMETER;
1283 goto bad_param;
1284 }
1285
1286 status = nodnic_port_check_and_set_dma(port_priv, TRUE);
1287 MLX_CHECK_STATUS(port_priv->device, status, set_err,
1288 "nodnic_port_check_and_set_dma failed");
1289 set_err:
1290 bad_param:
1291 return status;
1292 }
1293
1294 mlx_status
nodnic_port_disable_dma(IN nodnic_port_priv * port_priv)1295 nodnic_port_disable_dma(
1296 IN nodnic_port_priv *port_priv
1297 )
1298 {
1299 mlx_status status = MLX_SUCCESS;
1300
1301 if( port_priv == NULL ){
1302 status = MLX_INVALID_PARAMETER;
1303 goto bad_param;
1304 }
1305
1306 status = nodnic_port_check_and_set_dma(port_priv, FALSE);
1307 MLX_CHECK_STATUS(port_priv->device, status, set_err,
1308 "nodnic_port_check_and_set_dma failed");
1309 set_err:
1310 bad_param:
1311 return status;
1312 }
1313
1314 mlx_status
nodnic_port_thin_init(IN nodnic_device_priv * device_priv,IN nodnic_port_priv * port_priv,IN mlx_uint8 port_index)1315 nodnic_port_thin_init(
1316 IN nodnic_device_priv *device_priv,
1317 IN nodnic_port_priv *port_priv,
1318 IN mlx_uint8 port_index
1319 )
1320 {
1321 mlx_status status = MLX_SUCCESS;
1322 mlx_boolean reset_needed = 0;
1323 #ifdef DEVICE_CX3
1324 mlx_uint32 offset;
1325 #endif
1326
1327 if( device_priv == NULL || port_priv == NULL || port_index > 1){
1328 status = MLX_INVALID_PARAMETER;
1329 goto invalid_parm;
1330 }
1331
1332 port_priv->device = device_priv;
1333
1334 port_priv->port_offset = device_priv->device_offset +
1335 nodnic_port_offset_table[port_index];
1336
1337 port_priv->port_num = port_index + 1;
1338
1339 port_priv->send_doorbell = nodnic_port_update_ring_doorbell;
1340 port_priv->recv_doorbell = nodnic_port_update_ring_doorbell;
1341 port_priv->set_dma = nodnic_port_set_dma;
1342 #ifdef DEVICE_CX3
1343 if (device_priv->device_cap.crspace_doorbells) {
1344 status = nodnic_cmd_read(device_priv, (port_priv->port_offset + 0x100),
1345 &offset);
1346 if (status != MLX_SUCCESS) {
1347 return status;
1348 } else {
1349 port_priv->data_flow_gw = (nodnic_port_data_flow_gw *)
1350 (device_priv->utils->config + offset);
1351 }
1352 if ( nodnic_port_set ( port_priv, nodnic_port_option_crspace_en, 1 ) ) {
1353 return MLX_FAILED;
1354 }
1355 port_priv->send_doorbell = nodnic_port_send_db_connectx3;
1356 port_priv->recv_doorbell = nodnic_port_recv_db_connectx3;
1357 port_priv->set_dma = nodnic_port_set_dma_connectx3;
1358 }
1359 #endif
1360 if ( device_priv->device_cap.support_rx_pi_dma ) {
1361 port_priv->recv_doorbell = nodnic_port_recv_db_dma;
1362 }
1363
1364 /* clear reset_needed */
1365 nodnic_port_read_reset_needed(port_priv, &reset_needed);
1366
1367 port_priv->port_type = NODNIC_PORT_TYPE_UNKNOWN;
1368 invalid_parm:
1369 return status;
1370 }
1371