2
* Copyright (C) 2015 Mellanox Technologies Ltd.
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.
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.
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
20
FILE_LICENCE ( GPL2_OR_LATER );
27
#include <ipxe/malloc.h>
28
#include <ipxe/umalloc.h>
29
#include <ipxe/if_ether.h>
30
#include <ipxe/ethernet.h>
31
#include <ipxe/vlan.h>
33
#include "flexboot_nodnic.h"
34
#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h"
35
#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h"
36
#include "mlx_utils/include/public/mlx_pci_gw.h"
37
#include "mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.h"
38
#include "mlx_utils/include/public/mlx_types.h"
39
#include "mlx_utils/include/public/mlx_utils.h"
40
#include "mlx_utils/include/public/mlx_bail.h"
41
#include "mlx_nodnic/include/mlx_cmd.h"
42
#include "mlx_utils/include/public/mlx_memory.h"
43
#include "mlx_utils/include/public/mlx_pci.h"
44
#include "mlx_nodnic/include/mlx_device.h"
45
#include "mlx_nodnic/include/mlx_port.h"
47
/***************************************************************************
49
* Completion queue operations
51
***************************************************************************
53
static int flexboot_nodnic_arm_cq ( struct flexboot_nodnic_port *port ) {
55
mlx_uint32 val = ( port->eth_cq->next_idx & 0xffff );
56
if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val ) ) {
57
MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" );
61
mlx_utils *utils = port->port_priv.device->utils;
62
nodnic_port_data_flow_gw *ptr = port->port_priv.data_flow_gw;
66
if ( port->port_priv.device->device_cap.crspace_doorbells == 0 ) {
67
val = ( port->eth_cq->next_idx & 0xffff );
68
if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val ) ) {
69
MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" );
73
/* Arming the CQ with CQ CI should be with this format -
74
* 16 bit - CQ CI - same endianness as the FW (don't swap bytes)
76
* 1 bit - arm CQ - must correct the endianness with the reserved above */
77
data = ( ( ( port->eth_cq->next_idx & 0xffff ) << 16 ) | 0x0080 );
78
/* Write the new index and update FW that new data was submitted */
79
mlx_pci_mem_write ( utils, MlxPciWidthUint32, 0,
80
( mlx_uint64 ) & ( ptr->armcq_cq_ci_dword ), 1, &data );
87
* Create completion queue
89
* @v ibdev Infiniband device
90
* @v cq Completion queue
91
* @ret rc Return status code
93
static int flexboot_nodnic_create_cq ( struct ib_device *ibdev ,
94
struct ib_completion_queue *cq ) {
95
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
96
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
97
struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq;
98
mlx_status status = MLX_SUCCESS;
100
flexboot_nodnic_cq = (struct flexboot_nodnic_completion_queue *)
101
zalloc(sizeof(*flexboot_nodnic_cq));
102
if ( flexboot_nodnic_cq == NULL ) {
103
status = MLX_OUT_OF_RESOURCES;
107
status = nodnic_port_create_cq(&port->port_priv,
109
flexboot_nodnic->callbacks->get_cqe_size(),
110
&flexboot_nodnic_cq->nodnic_completion_queue
112
MLX_FATAL_CHECK_STATUS(status, create_err,
113
"nodnic_port_create_cq failed");
114
flexboot_nodnic->callbacks->cqe_set_owner(
115
flexboot_nodnic_cq->nodnic_completion_queue->cq_virt,
119
ib_cq_set_drvdata ( cq, flexboot_nodnic_cq );
122
free(flexboot_nodnic_cq);
128
* Destroy completion queue
130
* @v ibdev Infiniband device
131
* @v cq Completion queue
133
static void flexboot_nodnic_destroy_cq ( struct ib_device *ibdev ,
134
struct ib_completion_queue *cq ) {
135
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
136
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
137
struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq );
139
nodnic_port_destroy_cq(&port->port_priv,
140
flexboot_nodnic_cq->nodnic_completion_queue);
142
free(flexboot_nodnic_cq);
146
struct ib_work_queue * flexboot_nodnic_find_wq ( struct ib_device *ibdev ,
147
struct ib_completion_queue *cq,
148
unsigned long qpn, int is_send ) {
149
struct ib_work_queue *wq;
150
struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp;
151
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
152
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
153
struct nodnic_ring *ring;
155
list_for_each_entry ( wq, &cq->work_queues, list ) {
156
flexboot_nodnic_qp = ib_qp_get_drvdata ( wq->qp );
157
if( wq->is_send == is_send && wq->is_send == TRUE ) {
158
ring = &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring;
159
} else if( wq->is_send == is_send && wq->is_send == FALSE ) {
160
ring = &flexboot_nodnic_qp->nodnic_queue_pair->receive.nodnic_ring;
164
nodnic_port_get_qpn(&port->port_priv, ring, &out_qpn);
165
if ( out_qpn == qpn )
174
* @v ibdev Infiniband device
175
* @v cq Completion queue
176
* @v cqe Hardware completion queue entry
177
* @ret rc Return status code
179
static int flexboot_nodnic_complete ( struct ib_device *ibdev,
180
struct ib_completion_queue *cq,
181
struct cqe_data *cqe_data ) {
182
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
183
struct ib_work_queue *wq;
184
struct ib_queue_pair *qp;
185
struct io_buffer *iobuf;
186
struct ib_address_vector recv_dest;
187
struct ib_address_vector recv_source;
189
unsigned long wqe_idx;
190
unsigned long wqe_idx_mask;
194
/* Parse completion */
197
if ( cqe_data->is_error == TRUE ) {
198
DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx syndrome %x vendor %x\n",
199
flexboot_nodnic, cq->cqn, cqe_data->syndrome,
200
cqe_data->vendor_err_syndrome );
202
/* Don't return immediately; propagate error to completer */
205
/* Identify work queue */
206
wq = flexboot_nodnic_find_wq( ibdev, cq, qpn, cqe_data->is_send );
208
DBGC ( flexboot_nodnic,
209
"flexboot_nodnic %p CQN %#lx unknown %s QPN %#lx\n",
210
flexboot_nodnic, cq->cqn,
211
( cqe_data->is_send ? "send" : "recv" ), qpn );
216
/* Identify work queue entry */
217
wqe_idx = cqe_data->wqe_counter;
218
wqe_idx_mask = ( wq->num_wqes - 1 );
219
DBGCP ( flexboot_nodnic,
220
"NODNIC %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n",
221
flexboot_nodnic, cq->cqn, qp->qpn,
222
( cqe_data->is_send ? "send" : "recv" ),
225
/* Identify I/O buffer */
226
iobuf = wq->iobufs[wqe_idx & wqe_idx_mask];
227
if ( iobuf == NULL ) {
228
DBGC ( flexboot_nodnic,
229
"NODNIC %p CQN %#lx QPN %#lx empty %s WQE %#lx\n",
230
flexboot_nodnic, cq->cqn, qp->qpn,
231
( cqe_data->is_send ? "send" : "recv" ), wqe_idx );
234
wq->iobufs[wqe_idx & wqe_idx_mask] = NULL;
236
if ( cqe_data->is_send == TRUE ) {
237
/* Hand off to completion handler */
238
ib_complete_send ( ibdev, qp, iobuf, rc );
239
} else if ( rc != 0 ) {
240
/* Propagate error to receive completion handler */
241
ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf, rc );
243
/* Set received length */
244
len = cqe_data->byte_cnt;
245
assert ( len <= iob_tailroom ( iobuf ) );
246
iob_put ( iobuf, len );
247
memset ( &recv_dest, 0, sizeof ( recv_dest ) );
249
memset ( &recv_source, 0, sizeof ( recv_source ) );
250
switch ( qp->type ) {
262
/* Hand off to completion handler */
263
ib_complete_recv ( ibdev, qp, &recv_dest,
264
&recv_source, iobuf, rc );
270
* Poll completion queue
272
* @v ibdev Infiniband device
273
* @v cq Completion queues
275
static void flexboot_nodnic_poll_cq ( struct ib_device *ibdev,
276
struct ib_completion_queue *cq) {
277
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
278
struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq );
281
struct cqe_data cqe_data;
282
unsigned int cqe_idx_mask;
285
cqe_size = flexboot_nodnic->callbacks->get_cqe_size();
287
/* Look for completion entry */
288
cqe_idx_mask = ( cq->num_cqes - 1 );
289
cqe = ((uint8_t *)flexboot_nodnic_cq->nodnic_completion_queue->cq_virt) +
290
cqe_size * (cq->next_idx & cqe_idx_mask);
292
/* TODO: check fill_completion */
293
flexboot_nodnic->callbacks->fill_completion(cqe, &cqe_data);
294
if ( cqe_data.owner ^
295
( ( cq->next_idx & cq->num_cqes ) ? 1 : 0 ) ) {
296
/* Entry still owned by hardware; end of poll */
299
/* Handle completion */
300
rc = flexboot_nodnic_complete ( ibdev, cq, &cqe_data );
302
DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx failed to complete: %s\n",
303
flexboot_nodnic, cq->cqn, strerror ( rc ) );
304
DBGC_HDA ( flexboot_nodnic, virt_to_phys ( cqe ),
305
cqe, sizeof ( *cqe ) );
308
/* Update completion queue's index */
312
/***************************************************************************
314
* Queue pair operations
316
***************************************************************************
323
* @v ibdev Infiniband device
325
* @ret rc Return status code
327
static int flexboot_nodnic_create_qp ( struct ib_device *ibdev,
328
struct ib_queue_pair *qp ) {
329
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
330
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
331
struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp;
332
mlx_status status = MLX_SUCCESS;
334
flexboot_nodnic_qp = (struct flexboot_nodnic_queue_pair *)zalloc(sizeof(*flexboot_nodnic_qp));
335
if ( flexboot_nodnic_qp == NULL ) {
336
status = MLX_OUT_OF_RESOURCES;
340
status = nodnic_port_create_qp(&port->port_priv, qp->type,
341
qp->send.num_wqes * sizeof(struct nodnic_send_wqbb),
343
qp->recv.num_wqes * sizeof(struct nodnic_recv_wqe),
345
&flexboot_nodnic_qp->nodnic_queue_pair);
346
MLX_FATAL_CHECK_STATUS(status, create_err,
347
"nodnic_port_create_qp failed");
348
ib_qp_set_drvdata ( qp, flexboot_nodnic_qp );
351
free(flexboot_nodnic_qp);
359
* @v ibdev Infiniband device
361
* @ret rc Return status code
363
static int flexboot_nodnic_modify_qp ( struct ib_device *ibdev __unused,
364
struct ib_queue_pair *qp __unused) {
372
* @v ibdev Infiniband device
375
static void flexboot_nodnic_destroy_qp ( struct ib_device *ibdev,
376
struct ib_queue_pair *qp ) {
377
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
378
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
379
struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
381
nodnic_port_destroy_qp(&port->port_priv, qp->type,
382
flexboot_nodnic_qp->nodnic_queue_pair);
384
free(flexboot_nodnic_qp);
387
/***************************************************************************
389
* Work request operations
391
***************************************************************************
395
* Post send work queue entry
397
* @v ibdev Infiniband device
399
* @v av Address vector
400
* @v iobuf I/O buffer
401
* @ret rc Return status code
403
static int flexboot_nodnic_post_send ( struct ib_device *ibdev,
404
struct ib_queue_pair *qp,
405
struct ib_address_vector *av,
406
struct io_buffer *iobuf) {
408
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
409
struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
410
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
411
struct ib_work_queue *wq = &qp->send;
412
struct nodnic_send_wqbb *wqbb;
413
nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair;
414
struct nodnic_send_ring *send_ring = &nodnic_qp->send;
415
mlx_status status = MLX_SUCCESS;
416
unsigned int wqe_idx_mask;
417
unsigned long wqe_idx;
419
if ( ( port->port_priv.dma_state == FALSE ) ||
420
( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) {
421
DBGC ( flexboot_nodnic, "flexboot_nodnic DMA disabled\n");
426
/* Allocate work queue entry */
427
wqe_idx = wq->next_idx;
428
wqe_idx_mask = ( wq->num_wqes - 1 );
429
if ( wq->iobufs[wqe_idx & wqe_idx_mask] ) {
430
DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx send queue full\n",
431
flexboot_nodnic, qp->qpn );
435
wqbb = &send_ring->wqe_virt[wqe_idx & wqe_idx_mask];
436
wq->iobufs[wqe_idx & wqe_idx_mask] = iobuf;
438
assert ( flexboot_nodnic->callbacks->
439
fill_send_wqe[qp->type] != NULL );
440
status = flexboot_nodnic->callbacks->
441
fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf,
444
DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx fill send wqe failed\n",
445
flexboot_nodnic, qp->qpn );
451
status = port->port_priv.send_doorbell ( &port->port_priv,
452
&send_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx );
454
DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring send doorbell failed\n", flexboot_nodnic );
462
* Post receive work queue entry
464
* @v ibdev Infiniband device
466
* @v iobuf I/O buffer
467
* @ret rc Return status code
469
static int flexboot_nodnic_post_recv ( struct ib_device *ibdev,
470
struct ib_queue_pair *qp,
471
struct io_buffer *iobuf ) {
472
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
473
struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
474
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
475
struct ib_work_queue *wq = &qp->recv;
476
nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair;
477
struct nodnic_recv_ring *recv_ring = &nodnic_qp->receive;
478
struct nodnic_recv_wqe *wqe;
479
unsigned int wqe_idx_mask;
480
mlx_status status = MLX_SUCCESS;
482
/* Allocate work queue entry */
483
wqe_idx_mask = ( wq->num_wqes - 1 );
484
if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
485
DBGC ( flexboot_nodnic,
486
"flexboot_nodnic %p QPN %#lx receive queue full\n",
487
flexboot_nodnic, qp->qpn );
491
wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
492
wqe = &((struct nodnic_recv_wqe*)recv_ring->wqe_virt)[wq->next_idx & wqe_idx_mask];
494
MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
495
MLX_FILL_1 ( &wqe->data[0], 1, l_key, flexboot_nodnic->device_priv.lkey );
496
MLX_FILL_H ( &wqe->data[0], 2,
497
local_address_h, virt_to_bus ( iobuf->data ) );
498
MLX_FILL_1 ( &wqe->data[0], 3,
499
local_address_l, virt_to_bus ( iobuf->data ) );
503
status = port->port_priv.recv_doorbell ( &port->port_priv,
504
&recv_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx );
506
DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring receive doorbell failed\n", flexboot_nodnic );
512
/***************************************************************************
516
***************************************************************************
519
static void flexboot_nodnic_poll_eq ( struct ib_device *ibdev ) {
520
struct flexboot_nodnic *flexboot_nodnic;
521
struct flexboot_nodnic_port *port;
522
struct net_device *netdev;
523
nodnic_port_state state = 0;
527
DBG ( "%s: ibdev = NULL!!!\n", __FUNCTION__ );
531
flexboot_nodnic = ib_get_drvdata ( ibdev );
532
port = &flexboot_nodnic->port[ibdev->port - 1];
533
netdev = port->netdev;
535
if ( ! netdev_is_open ( netdev ) ) {
536
DBG2( "%s: port %d is closed\n", __FUNCTION__, port->ibdev->port );
540
/* we don't poll EQ. Just poll link status if it's not active */
541
if ( ! netdev_link_ok ( netdev ) ) {
542
status = nodnic_port_get_state ( &port->port_priv, &state );
543
MLX_FATAL_CHECK_STATUS(status, state_err, "nodnic_port_get_state failed");
545
if ( state == nodnic_port_state_active ) {
546
DBG( "%s: port %d physical link is up\n", __FUNCTION__,
548
port->type->state_change ( flexboot_nodnic, port, 1 );
555
/***************************************************************************
557
* Multicast group operations
559
***************************************************************************
561
static int flexboot_nodnic_mcast_attach ( struct ib_device *ibdev,
562
struct ib_queue_pair *qp,
564
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
565
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
567
mlx_status status = MLX_SUCCESS;
571
memcpy(&mac, &gid, sizeof(mac));
572
status = nodnic_port_add_mac_filter(&port->port_priv, mac);
573
MLX_CHECK_STATUS(flexboot_nodnic->device_priv, status, mac_err,
574
"nodnic_port_add_mac_filter failed");
582
static void flexboot_nodnic_mcast_detach ( struct ib_device *ibdev,
583
struct ib_queue_pair *qp,
584
union ib_gid *gid ) {
585
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
586
struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
588
mlx_status status = MLX_SUCCESS;
592
memcpy(&mac, &gid, sizeof(mac));
593
status = nodnic_port_remove_mac_filter(&port->port_priv, mac);
594
MLX_CHECK_STATUS(flexboot_nodnic->device_priv, status, mac_err,
595
"nodnic_port_remove_mac_filter failed");
603
/***************************************************************************
605
* Infiniband link-layer operations
607
***************************************************************************
611
* Initialise Infiniband link
613
* @v ibdev Infiniband device
614
* @ret rc Return status code
616
static int flexboot_nodnic_ib_open ( struct ib_device *ibdev __unused) {
619
/*TODO: add implementation*/
624
* Close Infiniband link
626
* @v ibdev Infiniband device
628
static void flexboot_nodnic_ib_close ( struct ib_device *ibdev __unused) {
629
/*TODO: add implementation*/
633
* Inform embedded subnet management agent of a received MAD
635
* @v ibdev Infiniband device
637
* @ret rc Return status code
639
static int flexboot_nodnic_inform_sma ( struct ib_device *ibdev __unused,
640
union ib_mad *mad __unused) {
641
/*TODO: add implementation*/
645
/** flexboot_nodnic Infiniband operations */
646
static struct ib_device_operations flexboot_nodnic_ib_operations = {
647
.create_cq = flexboot_nodnic_create_cq,
648
.destroy_cq = flexboot_nodnic_destroy_cq,
649
.create_qp = flexboot_nodnic_create_qp,
650
.modify_qp = flexboot_nodnic_modify_qp,
651
.destroy_qp = flexboot_nodnic_destroy_qp,
652
.post_send = flexboot_nodnic_post_send,
653
.post_recv = flexboot_nodnic_post_recv,
654
.poll_cq = flexboot_nodnic_poll_cq,
655
.poll_eq = flexboot_nodnic_poll_eq,
656
.open = flexboot_nodnic_ib_open,
657
.close = flexboot_nodnic_ib_close,
658
.mcast_attach = flexboot_nodnic_mcast_attach,
659
.mcast_detach = flexboot_nodnic_mcast_detach,
660
.set_port_info = flexboot_nodnic_inform_sma,
661
.set_pkey_table = flexboot_nodnic_inform_sma,
663
/***************************************************************************
667
***************************************************************************
670
#define FLEX_NODNIC_TX_POLL_TOUT 500000
671
#define FLEX_NODNIC_TX_POLL_USLEEP 10
673
static void flexboot_nodnic_complete_all_tx ( struct flexboot_nodnic_port *port ) {
674
struct ib_device *ibdev = port->ibdev;
675
struct ib_completion_queue *cq;
676
struct ib_work_queue *wq;
677
int keep_polling = 0;
678
int timeout = FLEX_NODNIC_TX_POLL_TOUT;
680
list_for_each_entry ( cq, &ibdev->cqs, list ) {
682
ib_poll_cq ( ibdev, cq );
684
list_for_each_entry ( wq, &cq->work_queues, list ) {
686
keep_polling += ( wq->fill > 0 );
688
udelay ( FLEX_NODNIC_TX_POLL_USLEEP );
689
} while ( keep_polling && ( timeout-- > 0 ) );
693
static void flexboot_nodnic_port_disable_dma ( struct flexboot_nodnic_port *port ) {
694
nodnic_port_priv *port_priv = & ( port->port_priv );
697
if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) )
700
port_priv->port_state |= NODNIC_PORT_DISABLING_DMA;
701
flexboot_nodnic_complete_all_tx ( port );
702
if ( ( status = nodnic_port_disable_dma ( port_priv ) ) ) {
703
MLX_DEBUG_WARN ( port, "Failed to disable DMA %d\n", status );
706
port_priv->port_state &= ~NODNIC_PORT_DISABLING_DMA;
709
/***************************************************************************
713
***************************************************************************
716
/** Number of flexboot_nodnic Ethernet send work queue entries */
717
#define FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES 64
719
/** Number of flexboot_nodnic Ethernet receive work queue entries */
720
#define FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES 64
721
/** flexboot nodnic Ethernet queue pair operations */
722
static struct ib_queue_pair_operations flexboot_nodnic_eth_qp_op = {
723
.alloc_iob = alloc_iob,
727
* Transmit packet via flexboot_nodnic Ethernet device
729
* @v netdev Network device
730
* @v iobuf I/O buffer
731
* @ret rc Return status code
733
static int flexboot_nodnic_eth_transmit ( struct net_device *netdev,
734
struct io_buffer *iobuf) {
735
struct flexboot_nodnic_port *port = netdev->priv;
736
struct ib_device *ibdev = port->ibdev;
737
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
740
rc = ib_post_send ( ibdev, port->eth_qp, NULL, iobuf);
741
/* Transmit packet */
743
DBGC ( flexboot_nodnic, "NODNIC %p port %d could not transmit: %s\n",
744
flexboot_nodnic, ibdev->port, strerror ( rc ) );
752
* Handle flexboot_nodnic Ethernet device send completion
754
* @v ibdev Infiniband device
756
* @v iobuf I/O buffer
757
* @v rc Completion status code
759
static void flexboot_nodnic_eth_complete_send ( struct ib_device *ibdev __unused,
760
struct ib_queue_pair *qp,
761
struct io_buffer *iobuf,
763
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
765
netdev_tx_complete_err ( netdev, iobuf, rc );
769
* Handle flexboot_nodnic Ethernet device receive completion
771
* @v ibdev Infiniband device
773
* @v av Address vector, or NULL
774
* @v iobuf I/O buffer
775
* @v rc Completion status code
777
static void flexboot_nodnic_eth_complete_recv ( struct ib_device *ibdev __unused,
778
struct ib_queue_pair *qp,
779
struct ib_address_vector *dest __unused,
780
struct ib_address_vector *source,
781
struct io_buffer *iobuf,
783
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
786
DBG ( "Received packet with error\n" );
787
netdev_rx_err ( netdev, iobuf, rc );
791
if ( source == NULL ) {
792
DBG ( "Received packet without address vector\n" );
793
netdev_rx_err ( netdev, iobuf, -ENOTTY );
796
netdev_rx ( netdev, iobuf );
799
/** flexboot_nodnic Ethernet device completion operations */
800
static struct ib_completion_queue_operations flexboot_nodnic_eth_cq_op = {
801
.complete_send = flexboot_nodnic_eth_complete_send,
802
.complete_recv = flexboot_nodnic_eth_complete_recv,
806
* Poll flexboot_nodnic Ethernet device
808
* @v netdev Network device
810
static void flexboot_nodnic_eth_poll ( struct net_device *netdev) {
811
struct flexboot_nodnic_port *port = netdev->priv;
812
struct ib_device *ibdev = port->ibdev;
814
ib_poll_eq ( ibdev );
818
* Open flexboot_nodnic Ethernet device
820
* @v netdev Network device
821
* @ret rc Return status code
823
static int flexboot_nodnic_eth_open ( struct net_device *netdev ) {
824
struct flexboot_nodnic_port *port = netdev->priv;
825
struct ib_device *ibdev = port->ibdev;
826
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
827
mlx_status status = MLX_SUCCESS;
828
struct ib_completion_queue *dummy_cq = NULL;
829
struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = NULL;
830
mlx_uint64 cq_size = 0;
832
nodnic_port_state state = nodnic_port_state_down;
834
if ( port->port_priv.port_state & NODNIC_PORT_OPENED ) {
835
DBGC ( flexboot_nodnic, "%s: port %d is already opened\n",
836
__FUNCTION__, port->ibdev->port );
840
port->port_priv.port_state |= NODNIC_PORT_OPENED;
842
dummy_cq = zalloc ( sizeof ( struct ib_completion_queue ) );
843
if ( dummy_cq == NULL ) {
844
DBGC ( flexboot_nodnic, "%s: Failed to allocate dummy CQ\n", __FUNCTION__ );
845
status = MLX_OUT_OF_RESOURCES;
846
goto err_create_dummy_cq;
848
INIT_LIST_HEAD ( &dummy_cq->work_queues );
850
port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH,
851
FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES, dummy_cq,
852
FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES, dummy_cq,
853
&flexboot_nodnic_eth_qp_op, netdev->name );
854
if ( !port->eth_qp ) {
855
DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not create queue pair\n",
856
flexboot_nodnic, ibdev->port );
857
status = MLX_OUT_OF_RESOURCES;
861
ib_qp_set_ownerdata ( port->eth_qp, netdev );
863
status = nodnic_port_get_cq_size(&port->port_priv, &cq_size);
864
MLX_FATAL_CHECK_STATUS(status, get_cq_size_err,
865
"nodnic_port_get_cq_size failed");
867
port->eth_cq = ib_create_cq ( ibdev, cq_size,
868
&flexboot_nodnic_eth_cq_op );
869
if ( !port->eth_cq ) {
870
DBGC ( flexboot_nodnic,
871
"flexboot_nodnic %p port %d could not create completion queue\n",
872
flexboot_nodnic, ibdev->port );
873
status = MLX_OUT_OF_RESOURCES;
876
port->eth_qp->send.cq = port->eth_cq;
877
list_del(&port->eth_qp->send.list);
878
list_add ( &port->eth_qp->send.list, &port->eth_cq->work_queues );
879
port->eth_qp->recv.cq = port->eth_cq;
880
list_del(&port->eth_qp->recv.list);
881
list_add ( &port->eth_qp->recv.list, &port->eth_cq->work_queues );
883
status = nodnic_port_allocate_eq(&port->port_priv,
884
flexboot_nodnic->device_priv.device_cap.log_working_buffer_size);
885
MLX_FATAL_CHECK_STATUS(status, eq_alloc_err,
886
"nodnic_port_allocate_eq failed");
888
status = nodnic_port_init(&port->port_priv);
889
MLX_FATAL_CHECK_STATUS(status, init_err,
890
"nodnic_port_init failed");
892
/* update qp - qpn */
893
flexboot_nodnic_qp = ib_qp_get_drvdata ( port->eth_qp );
894
status = nodnic_port_get_qpn(&port->port_priv,
895
&flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring,
897
MLX_FATAL_CHECK_STATUS(status, qpn_err,
898
"nodnic_port_get_qpn failed");
899
port->eth_qp->qpn = qpn;
901
/* Fill receive rings */
902
ib_refill_recv ( ibdev, port->eth_qp );
904
status = nodnic_port_enable_dma(&port->port_priv);
905
MLX_FATAL_CHECK_STATUS(status, dma_err,
906
"nodnic_port_enable_dma failed");
908
if (flexboot_nodnic->device_priv.device_cap.support_promisc_filter) {
909
status = nodnic_port_set_promisc(&port->port_priv, TRUE);
910
MLX_FATAL_CHECK_STATUS(status, promisc_err,
911
"nodnic_port_set_promisc failed");
914
status = nodnic_port_get_state(&port->port_priv, &state);
915
MLX_FATAL_CHECK_STATUS(status, state_err,
916
"nodnic_port_get_state failed");
918
port->type->state_change (
919
flexboot_nodnic, port, state == nodnic_port_state_active );
921
DBGC ( flexboot_nodnic, "%s: port %d opened (link is %s)\n",
922
__FUNCTION__, port->ibdev->port,
923
( ( state == nodnic_port_state_active ) ? "Up" : "Down" ) );
931
nodnic_port_close(&port->port_priv);
933
nodnic_port_free_eq(&port->port_priv);
937
ib_destroy_qp(ibdev, port->eth_qp );
941
port->port_priv.port_state &= ~NODNIC_PORT_OPENED;
946
* Close flexboot_nodnic Ethernet device
948
* @v netdev Network device
950
static void flexboot_nodnic_eth_close ( struct net_device *netdev) {
951
struct flexboot_nodnic_port *port = netdev->priv;
952
struct ib_device *ibdev = port->ibdev;
953
struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
954
mlx_status status = MLX_SUCCESS;
956
if ( ! ( port->port_priv.port_state & NODNIC_PORT_OPENED ) ) {
957
DBGC ( flexboot_nodnic, "%s: port %d is already closed\n",
958
__FUNCTION__, port->ibdev->port );
962
if (flexboot_nodnic->device_priv.device_cap.support_promisc_filter) {
963
if ( ( status = nodnic_port_set_promisc( &port->port_priv, FALSE ) ) ) {
964
DBGC ( flexboot_nodnic,
965
"nodnic_port_set_promisc failed (status = %d)\n", status );
969
flexboot_nodnic_port_disable_dma ( port );
971
port->port_priv.port_state &= ~NODNIC_PORT_OPENED;
973
port->type->state_change ( flexboot_nodnic, port, FALSE );
976
status = nodnic_port_close(&port->port_priv);
977
if ( status != MLX_SUCCESS ) {
978
DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not close port: %s\n",
979
flexboot_nodnic, ibdev->port, strerror ( status ) );
980
/* Nothing we can do about this */
983
ib_destroy_qp ( ibdev, port->eth_qp );
985
ib_destroy_cq ( ibdev, port->eth_cq );
988
nodnic_port_free_eq(&port->port_priv);
990
DBGC ( flexboot_nodnic, "%s: port %d closed\n", __FUNCTION__, port->ibdev->port );
993
void flexboot_nodnic_eth_irq ( struct net_device *netdev, int enable ) {
994
struct flexboot_nodnic_port *port = netdev->priv;
997
if ( ( port->port_priv.port_state & NODNIC_PORT_OPENED ) &&
998
! ( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) {
999
flexboot_nodnic_arm_cq ( port );
1004
nodnic_device_clear_int( port->port_priv.device );
1008
/** flexboot_nodnic Ethernet network device operations */
1009
static struct net_device_operations flexboot_nodnic_eth_operations = {
1010
.open = flexboot_nodnic_eth_open,
1011
.close = flexboot_nodnic_eth_close,
1012
.transmit = flexboot_nodnic_eth_transmit,
1013
.poll = flexboot_nodnic_eth_poll,
1017
* Register flexboot_nodnic Ethernet device
1019
static int flexboot_nodnic_register_netdev ( struct flexboot_nodnic *flexboot_nodnic,
1020
struct flexboot_nodnic_port *port) {
1021
mlx_status status = MLX_SUCCESS;
1022
struct net_device *netdev;
1023
struct ib_device *ibdev = port->ibdev;
1029
/* Allocate network devices */
1030
netdev = alloc_etherdev ( 0 );
1031
if ( netdev == NULL ) {
1032
DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not allocate net device\n",
1033
flexboot_nodnic, ibdev->port );
1034
status = MLX_OUT_OF_RESOURCES;
1037
port->netdev = netdev;
1038
netdev_init ( netdev, &flexboot_nodnic_eth_operations );
1039
netdev->dev = ibdev->dev;
1040
netdev->priv = port;
1042
status = nodnic_port_query(&port->port_priv,
1043
nodnic_port_option_mac_high,
1045
MLX_FATAL_CHECK_STATUS(status, mac_err,
1046
"failed to query mac high");
1047
status = nodnic_port_query(&port->port_priv,
1048
nodnic_port_option_mac_low,
1050
MLX_FATAL_CHECK_STATUS(status, mac_err,
1051
"failed to query mac low");
1052
mac.dwords[0] = htonl(mac.dwords[0]);
1053
mac.dwords[1] = htonl(mac.dwords[1]);
1054
memcpy ( netdev->hw_addr,
1055
&mac.bytes[2], ETH_ALEN);
1056
/* Register network device */
1057
status = register_netdev ( netdev );
1058
if ( status != MLX_SUCCESS ) {
1059
DBGC ( flexboot_nodnic,
1060
"flexboot_nodnic %p port %d could not register network device: %s\n",
1061
flexboot_nodnic, ibdev->port, strerror ( status ) );
1067
netdev_put ( netdev );
1073
* Handle flexboot_nodnic Ethernet device port state change
1075
static void flexboot_nodnic_state_change_netdev ( struct flexboot_nodnic *flexboot_nodnic __unused,
1076
struct flexboot_nodnic_port *port,
1078
struct net_device *netdev = port->netdev;
1081
netdev_link_up ( netdev );
1083
netdev_link_down ( netdev );
1088
* Unregister flexboot_nodnic Ethernet device
1090
static void flexboot_nodnic_unregister_netdev ( struct flexboot_nodnic *flexboot_nodnic __unused,
1091
struct flexboot_nodnic_port *port ) {
1092
struct net_device *netdev = port->netdev;
1093
unregister_netdev ( netdev );
1094
netdev_nullify ( netdev );
1095
netdev_put ( netdev );
1098
/** flexboot_nodnic Ethernet port type */
1099
static struct flexboot_nodnic_port_type flexboot_nodnic_port_type_eth = {
1100
.register_dev = flexboot_nodnic_register_netdev,
1101
.state_change = flexboot_nodnic_state_change_netdev,
1102
.unregister_dev = flexboot_nodnic_unregister_netdev,
1105
/***************************************************************************
1107
* PCI interface helper functions
1109
***************************************************************************
1113
flexboot_nodnic_allocate_infiniband_devices( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1114
mlx_status status = MLX_SUCCESS;
1115
nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1116
struct pci_device *pci = flexboot_nodnic_priv->pci;
1117
struct ib_device *ibdev = NULL;
1120
/* Allocate Infiniband devices */
1121
for (; i < device_priv->device_cap.num_ports; i++) {
1122
if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1124
ibdev = alloc_ibdev(0);
1125
if (ibdev == NULL) {
1126
status = MLX_OUT_OF_RESOURCES;
1127
goto err_alloc_ibdev;
1129
flexboot_nodnic_priv->port[i].ibdev = ibdev;
1130
ibdev->op = &flexboot_nodnic_ib_operations;
1131
ibdev->dev = &pci->dev;
1132
ibdev->port = ( FLEXBOOT_NODNIC_PORT_BASE + i);
1133
ib_set_drvdata(ibdev, flexboot_nodnic_priv);
1137
for ( i-- ; ( signed int ) i >= 0 ; i-- )
1138
ibdev_put ( flexboot_nodnic_priv->port[i].ibdev );
1144
flexboot_nodnic_thin_init_ports( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1145
mlx_status status = MLX_SUCCESS;
1146
nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1147
nodnic_port_priv *port_priv = NULL;
1150
for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
1151
if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1153
port_priv = &flexboot_nodnic_priv->port[i].port_priv;
1154
status = nodnic_port_thin_init( device_priv, port_priv, i );
1155
MLX_FATAL_CHECK_STATUS(status, thin_init_err,
1156
"flexboot_nodnic_thin_init_ports failed");
1165
flexboot_nodnic_set_ports_type ( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1166
mlx_status status = MLX_SUCCESS;
1167
nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1168
nodnic_port_priv *port_priv = NULL;
1169
nodnic_port_type type = NODNIC_PORT_TYPE_UNKNOWN;
1172
for ( i = 0 ; i < device_priv->device_cap.num_ports ; i++ ) {
1173
if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1175
port_priv = &flexboot_nodnic_priv->port[i].port_priv;
1176
status = nodnic_port_get_type(port_priv, &type);
1177
MLX_FATAL_CHECK_STATUS(status, type_err,
1178
"nodnic_port_get_type failed");
1180
case NODNIC_PORT_TYPE_ETH:
1181
DBGC ( flexboot_nodnic_priv, "Port %d type is Ethernet\n", i );
1182
flexboot_nodnic_priv->port[i].type = &flexboot_nodnic_port_type_eth;
1184
case NODNIC_PORT_TYPE_IB:
1185
DBGC ( flexboot_nodnic_priv, "Port %d type is Infiniband\n", i );
1186
status = MLX_UNSUPPORTED;
1189
DBGC ( flexboot_nodnic_priv, "Port %d type is unknown\n", i );
1190
status = MLX_UNSUPPORTED;
1200
flexboot_nodnic_ports_register_dev( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1201
mlx_status status = MLX_SUCCESS;
1202
nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1203
struct flexboot_nodnic_port *port = NULL;
1206
for (; i < device_priv->device_cap.num_ports; i++) {
1207
if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1209
port = &flexboot_nodnic_priv->port[i];
1210
status = port->type->register_dev ( flexboot_nodnic_priv, port );
1211
MLX_FATAL_CHECK_STATUS(status, reg_err,
1212
"port register_dev failed");
1220
flexboot_nodnic_ports_unregister_dev ( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1221
struct flexboot_nodnic_port *port;
1222
nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1223
int i = (device_priv->device_cap.num_ports - 1);
1225
for (; i >= 0; i--) {
1226
if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1228
port = &flexboot_nodnic_priv->port[i];
1229
port->type->unregister_dev(flexboot_nodnic_priv, port);
1230
ibdev_put(flexboot_nodnic_priv->port[i].ibdev);
1235
/***************************************************************************
1237
* flexboot nodnic interface
1239
***************************************************************************
1241
__unused static void flexboot_nodnic_enable_dma ( struct flexboot_nodnic *nodnic ) {
1242
nodnic_port_priv *port_priv;
1246
for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) {
1247
if ( ! ( nodnic->port_mask & ( i + 1 ) ) )
1249
port_priv = & ( nodnic->port[i].port_priv );
1250
if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) )
1253
if ( ( status = nodnic_port_enable_dma ( port_priv ) ) ) {
1254
MLX_DEBUG_WARN ( nodnic, "Failed to enable DMA %d\n", status );
1259
__unused static void flexboot_nodnic_disable_dma ( struct flexboot_nodnic *nodnic ) {
1262
for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) {
1263
if ( ! ( nodnic->port_mask & ( i + 1 ) ) )
1265
flexboot_nodnic_port_disable_dma ( & ( nodnic->port[i] ) );
1269
int flexboot_nodnic_is_supported ( struct pci_device *pci ) {
1271
mlx_pci_gw_buffer buffer;
1273
int is_supported = 0;
1275
DBG ( "%s: start\n", __FUNCTION__ );
1277
memset ( &utils, 0, sizeof ( utils ) );
1279
status = mlx_utils_init ( &utils, pci );
1280
MLX_CHECK_STATUS ( pci, status, utils_init_err, "mlx_utils_init failed" );
1282
status = mlx_pci_gw_init ( &utils );
1283
MLX_CHECK_STATUS ( pci, status, pci_gw_init_err, "mlx_pci_gw_init failed" );
1285
status = mlx_pci_gw_read ( &utils, PCI_GW_SPACE_NODNIC,
1286
NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET, &buffer );
1288
if ( status == MLX_SUCCESS ) {
1289
buffer >>= NODNIC_NIC_INTERFACE_SUPPORTED_BIT;
1290
is_supported = ( buffer & 0x1 );
1293
mlx_pci_gw_teardown( &utils );
1297
DBG ( "%s: NODNIC is %s supported (status = %d)\n",
1298
__FUNCTION__, ( is_supported ? "": "not" ), status );
1299
return is_supported;
1302
void flexboot_nodnic_copy_mac ( uint8_t mac_addr[], uint32_t low_byte,
1303
uint16_t high_byte ) {
1309
uint8_t mac_addr[ETH_ALEN];
1312
mac_addr_aux.high_byte = high_byte;
1313
mac_addr_aux.low_byte = low_byte;
1315
mac_addr[0] = mac_addr_aux.mac_addr[5];
1316
mac_addr[1] = mac_addr_aux.mac_addr[4];
1317
mac_addr[2] = mac_addr_aux.mac_addr[3];
1318
mac_addr[3] = mac_addr_aux.mac_addr[2];
1319
mac_addr[4] = mac_addr_aux.mac_addr[1];
1320
mac_addr[5] = mac_addr_aux.mac_addr[0];
1323
static mlx_status flexboot_nodnic_get_factory_mac (
1324
struct flexboot_nodnic *flexboot_nodnic_priv, uint8_t port __unused ) {
1325
struct mlx_vmac_query_virt_mac virt_mac;
1328
memset ( & virt_mac, 0, sizeof ( virt_mac ) );
1329
status = mlx_vmac_query_virt_mac ( flexboot_nodnic_priv->device_priv.utils,
1332
DBGC ( flexboot_nodnic_priv, "NODNIC %p Failed to set the virtual MAC\n",
1333
flexboot_nodnic_priv );
1342
* @v flexboot_nodnic nodnic device
1343
* @ret rc Return status code
1345
static int flexboot_nodnic_set_port_masking ( struct flexboot_nodnic *flexboot_nodnic ) {
1347
nodnic_device_priv *device_priv = &flexboot_nodnic->device_priv;
1349
flexboot_nodnic->port_mask = 0;
1350
for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
1351
flexboot_nodnic->port_mask |= (i + 1);
1354
if ( ! flexboot_nodnic->port_mask ) {
1355
/* No port was enabled */
1356
DBGC ( flexboot_nodnic, "NODNIC %p No port was enabled for "
1357
"booting\n", flexboot_nodnic );
1358
return -ENETUNREACH;
1364
int flexboot_nodnic_probe ( struct pci_device *pci,
1365
struct flexboot_nodnic_callbacks *callbacks,
1366
void *drv_priv __unused ) {
1367
mlx_status status = MLX_SUCCESS;
1368
struct flexboot_nodnic *flexboot_nodnic_priv = NULL;
1369
nodnic_device_priv *device_priv = NULL;
1372
if ( ( pci == NULL ) || ( callbacks == NULL ) ) {
1373
DBGC ( flexboot_nodnic_priv, "%s: Bad Parameter\n", __FUNCTION__ );
1377
flexboot_nodnic_priv = zalloc( sizeof ( *flexboot_nodnic_priv ) );
1378
if ( flexboot_nodnic_priv == NULL ) {
1379
DBGC ( flexboot_nodnic_priv, "%s: Failed to allocate priv data\n", __FUNCTION__ );
1380
status = MLX_OUT_OF_RESOURCES;
1381
goto device_err_alloc;
1384
/* Register settings
1385
* Note that pci->priv will be the device private data */
1386
flexboot_nodnic_priv->pci = pci;
1387
flexboot_nodnic_priv->callbacks = callbacks;
1388
pci_set_drvdata ( pci, flexboot_nodnic_priv );
1390
device_priv = &flexboot_nodnic_priv->device_priv;
1391
device_priv->utils = (mlx_utils *)zalloc( sizeof ( mlx_utils ) );
1392
if ( device_priv->utils == NULL ) {
1393
DBGC ( flexboot_nodnic_priv, "%s: Failed to allocate utils\n", __FUNCTION__ );
1394
status = MLX_OUT_OF_RESOURCES;
1395
goto utils_err_alloc;
1398
status = mlx_utils_init( device_priv->utils, pci );
1399
MLX_FATAL_CHECK_STATUS(status, utils_init_err,
1400
"mlx_utils_init failed");
1403
status = mlx_pci_gw_init( device_priv->utils );
1404
MLX_FATAL_CHECK_STATUS(status, cmd_init_err,
1405
"mlx_pci_gw_init failed");
1408
status = nodnic_device_init( device_priv );
1409
MLX_FATAL_CHECK_STATUS(status, device_init_err,
1410
"nodnic_device_init failed");
1412
status = nodnic_device_get_cap( device_priv );
1413
MLX_FATAL_CHECK_STATUS(status, get_cap_err,
1414
"nodnic_device_get_cap failed");
1416
status = flexboot_nodnic_set_port_masking ( flexboot_nodnic_priv );
1417
MLX_FATAL_CHECK_STATUS(status, err_set_masking,
1418
"flexboot_nodnic_set_port_masking failed");
1420
status = flexboot_nodnic_allocate_infiniband_devices( flexboot_nodnic_priv );
1421
MLX_FATAL_CHECK_STATUS(status, err_alloc_ibdev,
1422
"flexboot_nodnic_allocate_infiniband_devices failed");
1425
status = flexboot_nodnic_thin_init_ports( flexboot_nodnic_priv );
1426
MLX_FATAL_CHECK_STATUS(status, err_thin_init_ports,
1427
"flexboot_nodnic_thin_init_ports failed");
1430
status = flexboot_nodnic_set_ports_type( flexboot_nodnic_priv );
1431
MLX_CHECK_STATUS( flexboot_nodnic_priv, status, err_set_ports_types,
1432
"flexboot_nodnic_set_ports_type failed");
1434
status = flexboot_nodnic_ports_register_dev( flexboot_nodnic_priv );
1435
MLX_FATAL_CHECK_STATUS(status, reg_err,
1436
"flexboot_nodnic_ports_register_dev failed");
1438
for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
1439
if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1441
flexboot_nodnic_get_factory_mac ( flexboot_nodnic_priv, i );
1444
/* Update ETH operations with IRQ function if supported */
1445
DBGC ( flexboot_nodnic_priv, "%s: %s IRQ function\n",
1446
__FUNCTION__, ( callbacks->irq ? "Valid" : "No" ) );
1447
flexboot_nodnic_eth_operations.irq = callbacks->irq;
1450
flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv );
1452
err_set_ports_types:
1453
err_thin_init_ports:
1457
nodnic_device_teardown ( device_priv );
1459
mlx_pci_gw_teardown ( device_priv->utils );
1462
free ( device_priv->utils );
1464
free ( flexboot_nodnic_priv );
1469
void flexboot_nodnic_remove ( struct pci_device *pci )
1471
struct flexboot_nodnic *flexboot_nodnic_priv = pci_get_drvdata ( pci );
1472
nodnic_device_priv *device_priv = & ( flexboot_nodnic_priv->device_priv );
1474
flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv );
1475
nodnic_device_teardown( device_priv );
1476
mlx_pci_gw_teardown( device_priv->utils );
1477
free( device_priv->utils );
1478
free( flexboot_nodnic_priv );