iPXE
flexboot_nodnic.c
Go to the documentation of this file.
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 <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <ipxe/pci.h>
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>
32 #include <ipxe/io.h>
33 #include "flexboot_nodnic.h"
42 #include <byteswap.h>
43 #include <usr/ifmgmt.h>
49 
50 /***************************************************************************
51  *
52  * Completion queue operations
53  *
54  ***************************************************************************
55  */
57 #ifndef DEVICE_CX3
58  mlx_uint32 val32 = 0;
59  union arm_cq_uar cq_uar;
60 
61 #define ARM_CQ_UAR_CQ_CI_MASK 0xffffff
62 #define ARM_CQ_UAR_CMDSN_MASK 3
63 #define ARM_CQ_UAR_CMDSN_OFFSET 28
64 #define ARM_CQ_UAR_CQ_CI_OFFSET 0x20
65  if ( port->port_priv.device->device_cap.support_bar_cq_ctrl ) {
66  cq_uar.dword[0] = cpu_to_be32((port->eth_cq->next_idx & ARM_CQ_UAR_CQ_CI_MASK) |
68  cq_uar.dword[1] = cpu_to_be32(port->eth_cq->cqn);
69  wmb();
70  writeq(cq_uar.qword, port->port_priv.device->uar.virt + ARM_CQ_UAR_CQ_CI_OFFSET);
71  port->port_priv.arm_cq_doorbell_record->dword[0] = cq_uar.dword[1];
72  port->port_priv.arm_cq_doorbell_record->dword[1] = cq_uar.dword[0];
73  } else {
74  val32 = ( port->eth_cq->next_idx & 0xffffff );
75  if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val32 ) ) {
76  MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" );
77  return MLX_FAILED;
78  }
79  }
80 #else
81  mlx_utils *utils = port->port_priv.device->utils;
82  nodnic_port_data_flow_gw *ptr = port->port_priv.data_flow_gw;
83  mlx_uint32 data = 0;
84  mlx_uint32 val = 0;
85 
86  if ( port->port_priv.device->device_cap.crspace_doorbells == 0 ) {
87  val = ( port->eth_cq->next_idx & 0xffff );
88  if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val ) ) {
89  MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" );
90  return MLX_FAILED;
91  }
92  } else {
93  /* Arming the CQ with CQ CI should be with this format -
94  * 16 bit - CQ CI - same endianness as the FW (don't swap bytes)
95  * 15 bit - reserved
96  * 1 bit - arm CQ - must correct the endianness with the reserved above */
97  data = ( ( ( port->eth_cq->next_idx & 0xffff ) << 16 ) | 0x0080 );
98  /* Write the new index and update FW that new data was submitted */
100  ( mlx_uintn ) & ( ptr->armcq_cq_ci_dword ), 1, &data );
101  }
102 #endif
103  return 0;
104 }
105 
106 /**
107  * Create completion queue
108  *
109  * @v ibdev Infiniband device
110  * @v cq Completion queue
111  * @ret rc Return status code
112  */
113 static int flexboot_nodnic_create_cq ( struct ib_device *ibdev ,
114  struct ib_completion_queue *cq ) {
115  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
117  struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq;
119  mlx_uint32 cqn;
120 
121  flexboot_nodnic_cq = (struct flexboot_nodnic_completion_queue *)
122  zalloc(sizeof(*flexboot_nodnic_cq));
123  if ( flexboot_nodnic_cq == NULL ) {
125  goto qp_alloc_err;
126  }
127 
128  status = nodnic_port_create_cq(&port->port_priv,
129  cq->num_cqes *
131  &flexboot_nodnic_cq->nodnic_completion_queue
132  );
133  MLX_FATAL_CHECK_STATUS(status, create_err,
134  "nodnic_port_create_cq failed");
136  flexboot_nodnic_cq->nodnic_completion_queue->cq_virt,
137  cq->num_cqes);
139  status = nodnic_port_query(&port->port_priv,
141  (mlx_uint32 *)&cqn );
142  MLX_FATAL_CHECK_STATUS(status, read_cqn_err,
143  "failed to query cqn");
144  cq->cqn = cqn;
145  }
146 
147  ib_cq_set_drvdata ( cq, flexboot_nodnic_cq );
148  return status;
149 read_cqn_err:
150 create_err:
151  free(flexboot_nodnic_cq);
152 qp_alloc_err:
153  return status;
154 }
155 
156 /**
157  * Destroy completion queue
158  *
159  * @v ibdev Infiniband device
160  * @v cq Completion queue
161  */
162 static void flexboot_nodnic_destroy_cq ( struct ib_device *ibdev ,
163  struct ib_completion_queue *cq ) {
164  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
166  struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq );
167 
168  nodnic_port_destroy_cq(&port->port_priv,
169  flexboot_nodnic_cq->nodnic_completion_queue);
170 
171  free(flexboot_nodnic_cq);
172 }
173 
174 static
176  struct ib_completion_queue *cq,
177  unsigned long qpn, int is_send ) {
178  struct ib_work_queue *wq;
179  struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp;
180  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
182  struct nodnic_ring *ring;
183  mlx_uint32 out_qpn;
184  list_for_each_entry ( wq, &cq->work_queues, list ) {
185  flexboot_nodnic_qp = ib_qp_get_drvdata ( wq->qp );
186  if( wq->is_send == is_send && wq->is_send == TRUE ) {
187  ring = &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring;
188  } else if( wq->is_send == is_send && wq->is_send == FALSE ) {
189  ring = &flexboot_nodnic_qp->nodnic_queue_pair->receive.nodnic_ring;
190  } else {
191  continue;
192  }
193  nodnic_port_get_qpn(&port->port_priv, ring, &out_qpn);
194  if ( out_qpn == qpn )
195  return wq;
196  }
197  return NULL;
198 }
199 
200 /**
201  * Handle completion
202  *
203  * @v ibdev Infiniband device
204  * @v cq Completion queue
205  * @v cqe Hardware completion queue entry
206  * @ret rc Return status code
207  */
208 static int flexboot_nodnic_complete ( struct ib_device *ibdev,
209  struct ib_completion_queue *cq,
210  struct cqe_data *cqe_data ) {
211  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
212  struct ib_work_queue *wq;
213  struct ib_queue_pair *qp;
214  struct io_buffer *iobuf;
215  struct ib_address_vector recv_dest;
216  struct ib_address_vector recv_source;
217  unsigned long qpn;
218  unsigned long wqe_idx;
219  unsigned long wqe_idx_mask;
220  size_t len;
221  int rc = 0;
222 
223  /* Parse completion */
224  qpn = cqe_data->qpn;
225 
226  if ( cqe_data->is_error == TRUE ) {
227  DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx syndrome %x vendor %x\n",
230  rc = -EIO;
231  /* Don't return immediately; propagate error to completer */
232  }
233 
234  /* Identify work queue */
235  wq = flexboot_nodnic_find_wq( ibdev, cq, qpn, cqe_data->is_send );
236  if ( wq == NULL ) {
238  "flexboot_nodnic %p CQN %#lx unknown %s QPN %#lx\n",
239  flexboot_nodnic, cq->cqn,
240  ( cqe_data->is_send ? "send" : "recv" ), qpn );
241  return -EIO;
242  }
243  qp = wq->qp;
244 
245  /* Identify work queue entry */
246  wqe_idx = cqe_data->wqe_counter;
247  wqe_idx_mask = ( wq->num_wqes - 1 );
249  "NODNIC %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n",
250  flexboot_nodnic, cq->cqn, qp->qpn,
251  ( cqe_data->is_send ? "send" : "recv" ),
252  wqe_idx );
253 
254  /* Identify I/O buffer */
255  iobuf = wq->iobufs[wqe_idx & wqe_idx_mask];
256  if ( iobuf == NULL ) {
258  "NODNIC %p CQN %#lx QPN %#lx empty %s WQE %#lx\n",
259  flexboot_nodnic, cq->cqn, qp->qpn,
260  ( cqe_data->is_send ? "send" : "recv" ), wqe_idx );
261  return -EIO;
262  }
263  wq->iobufs[wqe_idx & wqe_idx_mask] = NULL;
264 
265  if ( cqe_data->is_send == TRUE ) {
266  /* Hand off to completion handler */
267  ib_complete_send ( ibdev, qp, iobuf, rc );
268  } else if ( rc != 0 ) {
269  /* Propagate error to receive completion handler */
270  ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf, rc );
271  } else {
272  /* Set received length */
273  len = cqe_data->byte_cnt;
274  assert ( len <= iob_tailroom ( iobuf ) );
275  iob_put ( iobuf, len );
276  memset ( &recv_dest, 0, sizeof ( recv_dest ) );
277  recv_dest.qpn = qpn;
278  memset ( &recv_source, 0, sizeof ( recv_source ) );
279  switch ( qp->type ) {
280  case IB_QPT_SMI:
281  case IB_QPT_GSI:
282  case IB_QPT_UD:
283  case IB_QPT_RC:
284  break;
285  case IB_QPT_ETH:
286  break;
287  default:
288  assert ( 0 );
289  return -EINVAL;
290  }
291  /* Hand off to completion handler */
292  ib_complete_recv ( ibdev, qp, &recv_dest,
293  &recv_source, iobuf, rc );
294  }
295 
296  return rc;
297 }
298 /**
299  * Poll completion queue
300  *
301  * @v ibdev Infiniband device
302  * @v cq Completion queues
303  */
304 static void flexboot_nodnic_poll_cq ( struct ib_device *ibdev,
305  struct ib_completion_queue *cq) {
306  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
307  struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq );
308  void *cqe;
309  mlx_size cqe_size;
310  struct cqe_data cqe_data;
311  unsigned int cqe_idx_mask;
312  int rc;
313 
314  cqe_size = flexboot_nodnic->callbacks->get_cqe_size();
315  while ( TRUE ) {
316  /* Look for completion entry */
317  cqe_idx_mask = ( cq->num_cqes - 1 );
318  cqe = ((uint8_t *)flexboot_nodnic_cq->nodnic_completion_queue->cq_virt) +
319  cqe_size * (cq->next_idx & cqe_idx_mask);
320 
321  /* TODO: check fill_completion */
323  if ( cqe_data.owner ^
324  ( ( cq->next_idx & cq->num_cqes ) ? 1 : 0 ) ) {
325  /* Entry still owned by hardware; end of poll */
326  break;
327  }
328  /* Handle completion */
329  rc = flexboot_nodnic_complete ( ibdev, cq, &cqe_data );
330  if ( rc != 0 ) {
331  DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx failed to complete: %s\n",
332  flexboot_nodnic, cq->cqn, strerror ( rc ) );
333  DBGC_HDA ( flexboot_nodnic, virt_to_phys ( cqe ),
334  cqe, sizeof ( *cqe ) );
335  }
336 
337  /* Update completion queue's index */
338  cq->next_idx++;
339  }
340 }
341 /***************************************************************************
342  *
343  * Queue pair operations
344  *
345  ***************************************************************************
346  */
347 
348 
349 /**
350  * Create queue pair
351  *
352  * @v ibdev Infiniband device
353  * @v qp Queue pair
354  * @ret rc Return status code
355  */
356 static int flexboot_nodnic_create_qp ( struct ib_device *ibdev,
357  struct ib_queue_pair *qp ) {
358  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
360  struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp;
362 
363  flexboot_nodnic_qp = (struct flexboot_nodnic_queue_pair *)zalloc(sizeof(*flexboot_nodnic_qp));
364  if ( flexboot_nodnic_qp == NULL ) {
366  goto qp_alloc_err;
367  }
368 
369  status = nodnic_port_create_qp(&port->port_priv,
370  (nodnic_queue_pair_type) qp->type,
371  qp->send.num_wqes * sizeof(struct nodnic_send_wqbb),
372  qp->send.num_wqes,
373  qp->recv.num_wqes * sizeof(struct nodnic_recv_wqe),
374  qp->recv.num_wqes,
375  &flexboot_nodnic_qp->nodnic_queue_pair);
376  MLX_FATAL_CHECK_STATUS(status, create_err,
377  "nodnic_port_create_qp failed");
378  ib_qp_set_drvdata ( qp, flexboot_nodnic_qp );
379  return status;
380 create_err:
381  free(flexboot_nodnic_qp);
382 qp_alloc_err:
383  return status;
384 }
385 
386 /**
387  * Modify queue pair
388  *
389  * @v ibdev Infiniband device
390  * @v qp Queue pair
391  * @ret rc Return status code
392  */
393 static int flexboot_nodnic_modify_qp ( struct ib_device *ibdev __unused,
394  struct ib_queue_pair *qp __unused) {
395  /*not needed*/
396  return 0;
397 }
398 
399 /**
400  * Destroy queue pair
401  *
402  * @v ibdev Infiniband device
403  * @v qp Queue pair
404  */
405 static void flexboot_nodnic_destroy_qp ( struct ib_device *ibdev,
406  struct ib_queue_pair *qp ) {
407  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
409  struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
410 
411  nodnic_port_destroy_qp(&port->port_priv,
412  (nodnic_queue_pair_type) qp->type,
413  flexboot_nodnic_qp->nodnic_queue_pair);
414 
415  free(flexboot_nodnic_qp);
416 }
417 
418 /***************************************************************************
419  *
420  * Work request operations
421  *
422  ***************************************************************************
423  */
424 
425 /**
426  * Post send work queue entry
427  *
428  * @v ibdev Infiniband device
429  * @v qp Queue pair
430  * @v av Address vector
431  * @v iobuf I/O buffer
432  * @ret rc Return status code
433  */
434 static int flexboot_nodnic_post_send ( struct ib_device *ibdev,
435  struct ib_queue_pair *qp,
436  struct ib_address_vector *av,
437  struct io_buffer *iobuf) {
438 
439  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
440  struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
442  struct ib_work_queue *wq = &qp->send;
443  struct nodnic_send_wqbb *wqbb;
444  nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair;
445  struct nodnic_send_ring *send_ring = &nodnic_qp->send;
447  unsigned int wqe_idx_mask;
448  unsigned long wqe_idx;
449 
450  if ( ( port->port_priv.dma_state == FALSE ) ||
451  ( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) {
452  DBGC ( flexboot_nodnic, "flexboot_nodnic DMA disabled\n");
453  status = -ENETDOWN;
454  goto post_send_done;
455  }
456 
457  /* Allocate work queue entry */
458  wqe_idx = wq->next_idx;
459  wqe_idx_mask = ( wq->num_wqes - 1 );
460  if ( wq->iobufs[wqe_idx & wqe_idx_mask] ) {
461  DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx send queue full\n",
462  flexboot_nodnic, qp->qpn );
463  status = -ENOBUFS;
464  goto post_send_done;
465  }
466  wqbb = &send_ring->wqe_virt[wqe_idx & wqe_idx_mask];
467  wq->iobufs[wqe_idx & wqe_idx_mask] = iobuf;
468 
470  fill_send_wqe[qp->type] != NULL );
472  fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf,
473  wqbb, wqe_idx );
474  if ( status != 0 ) {
475  DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx fill send wqe failed\n",
476  flexboot_nodnic, qp->qpn );
477  goto post_send_done;
478  }
479 
480  wq->next_idx++;
481 
482  status = port->port_priv.send_doorbell ( &port->port_priv,
483  &send_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx );
486  }
487  if ( status != 0 ) {
488  DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring send doorbell failed\n", flexboot_nodnic );
489  }
490 
491 post_send_done:
492  return status;
493 }
494 
495 /**
496  * Post receive work queue entry
497  *
498  * @v ibdev Infiniband device
499  * @v qp Queue pair
500  * @v iobuf I/O buffer
501  * @ret rc Return status code
502  */
503 static int flexboot_nodnic_post_recv ( struct ib_device *ibdev,
504  struct ib_queue_pair *qp,
505  struct io_buffer *iobuf ) {
506  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
507  struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
509  struct ib_work_queue *wq = &qp->recv;
510  nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair;
511  struct nodnic_recv_ring *recv_ring = &nodnic_qp->receive;
512  struct nodnic_recv_wqe *wqe;
513  unsigned int wqe_idx_mask;
515 
516  /* Allocate work queue entry */
517  wqe_idx_mask = ( wq->num_wqes - 1 );
518  if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
520  "flexboot_nodnic %p QPN %#lx receive queue full\n",
521  flexboot_nodnic, qp->qpn );
522  status = -ENOBUFS;
523  goto post_recv_done;
524  }
525  wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
526  wqe = &((struct nodnic_recv_wqe*)recv_ring->wqe_virt)[wq->next_idx & wqe_idx_mask];
527 
528  MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
529  MLX_FILL_1 ( &wqe->data[0], 1, l_key, flexboot_nodnic->device_priv.lkey );
530  MLX_FILL_H ( &wqe->data[0], 2,
531  local_address_h, virt_to_bus ( iobuf->data ) );
532  MLX_FILL_1 ( &wqe->data[0], 3,
533  local_address_l, virt_to_bus ( iobuf->data ) );
534 
535  wq->next_idx++;
536 
537  status = port->port_priv.recv_doorbell ( &port->port_priv,
538  &recv_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx );
539  if ( status != 0 ) {
540  DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring receive doorbell failed\n", flexboot_nodnic );
541  }
542 post_recv_done:
543  return status;
544 }
545 
546 /***************************************************************************
547  *
548  * Event queues
549  *
550  ***************************************************************************
551  */
552 
553 static void flexboot_nodnic_poll_eq ( struct ib_device *ibdev ) {
555  struct flexboot_nodnic_port *port;
556  struct net_device *netdev;
559 
560  if ( ! ibdev ) {
561  DBG ( "%s: ibdev = NULL!!!\n", __FUNCTION__ );
562  return;
563  }
564 
565  flexboot_nodnic = ib_get_drvdata ( ibdev );
566  port = &flexboot_nodnic->port[ibdev->port - 1];
567  netdev = port->netdev;
568 
569  if ( ! netdev_is_open ( netdev ) ) {
570  DBG2( "%s: port %d is closed\n", __FUNCTION__, port->ibdev->port );
571  return;
572  }
573 
574  /* we don't poll EQ. Just poll link status if it's not active */
575  if ( ! netdev_link_ok ( netdev ) ) {
576  status = nodnic_port_get_state ( &port->port_priv, &state );
577  MLX_FATAL_CHECK_STATUS(status, state_err, "nodnic_port_get_state failed");
578 
579  if ( state == nodnic_port_state_active ) {
580  DBG( "%s: port %d physical link is up\n", __FUNCTION__,
581  port->ibdev->port );
582  port->type->state_change ( flexboot_nodnic, port, 1 );
583  }
584  }
585 state_err:
586  return;
587 }
588 
589 /***************************************************************************
590  *
591  * Multicast group operations
592  *
593  ***************************************************************************
594  */
595 static int flexboot_nodnic_mcast_attach ( struct ib_device *ibdev,
596  struct ib_queue_pair *qp,
597  union ib_gid *gid) {
598  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
602 
603  switch (qp->type) {
604  case IB_QPT_ETH:
605  memcpy(&mac, gid, sizeof(mac));
606  status = nodnic_port_add_mac_filter(&port->port_priv, mac);
608  "nodnic_port_add_mac_filter failed");
609  break;
610  default:
611  break;
612  }
613 mac_err:
614  return status;
615 }
617  struct ib_queue_pair *qp,
618  union ib_gid *gid ) {
619  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
623 
624  switch (qp->type) {
625  case IB_QPT_ETH:
626  memcpy(&mac, gid, sizeof(mac));
629  "nodnic_port_remove_mac_filter failed");
630  break;
631  default:
632  break;
633  }
634 mac_err:
635  return;
636 }
637 /***************************************************************************
638  *
639  * Infiniband link-layer operations
640  *
641  ***************************************************************************
642  */
643 
644 /**
645  * Initialise Infiniband link
646  *
647  * @v ibdev Infiniband device
648  * @ret rc Return status code
649  */
651  int rc = 0;
652 
653  /*TODO: add implementation*/
654  return rc;
655 }
656 
657 /**
658  * Close Infiniband link
659  *
660  * @v ibdev Infiniband device
661  */
663  /*TODO: add implementation*/
664 }
665 
666 /**
667  * Inform embedded subnet management agent of a received MAD
668  *
669  * @v ibdev Infiniband device
670  * @v mad MAD
671  * @ret rc Return status code
672  */
674  union ib_mad *mad __unused) {
675  /*TODO: add implementation*/
676  return 0;
677 }
678 
679 /** flexboot_nodnic Infiniband operations */
682  .destroy_cq = flexboot_nodnic_destroy_cq,
683  .create_qp = flexboot_nodnic_create_qp,
684  .modify_qp = flexboot_nodnic_modify_qp,
685  .destroy_qp = flexboot_nodnic_destroy_qp,
686  .post_send = flexboot_nodnic_post_send,
687  .post_recv = flexboot_nodnic_post_recv,
688  .poll_cq = flexboot_nodnic_poll_cq,
689  .poll_eq = flexboot_nodnic_poll_eq,
690  .open = flexboot_nodnic_ib_open,
691  .close = flexboot_nodnic_ib_close,
692  .mcast_attach = flexboot_nodnic_mcast_attach,
693  .mcast_detach = flexboot_nodnic_mcast_detach,
694  .set_port_info = flexboot_nodnic_inform_sma,
695  .set_pkey_table = flexboot_nodnic_inform_sma,
696 };
697 /***************************************************************************
698  *
699  *
700  *
701  ***************************************************************************
702  */
703 
704 #define FLEX_NODNIC_TX_POLL_TOUT 500000
705 #define FLEX_NODNIC_TX_POLL_USLEEP 10
706 
708  struct ib_device *ibdev = port->ibdev;
709  struct ib_completion_queue *cq;
710  struct ib_work_queue *wq;
711  int keep_polling = 0;
713 
714  list_for_each_entry ( cq, &ibdev->cqs, list ) {
715  do {
716  ib_poll_cq ( ibdev, cq );
717  keep_polling = 0;
719  if ( wq->is_send )
720  keep_polling += ( wq->fill > 0 );
721  }
723  } while ( keep_polling && ( timeout-- > 0 ) );
724  }
725 }
726 
728  nodnic_port_priv *port_priv = & ( port->port_priv );
730 
731  if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) )
732  return;
733 
736  if ( ( status = nodnic_port_disable_dma ( port_priv ) ) ) {
737  MLX_DEBUG_WARN ( port, "Failed to disable DMA %d\n", status );
738  }
739 
740  port_priv->port_state &= ~NODNIC_PORT_DISABLING_DMA;
741 }
742 
743 /***************************************************************************
744  *
745  * Ethernet operation
746  *
747  ***************************************************************************
748  */
749 
750 /** Number of flexboot_nodnic Ethernet send work queue entries */
751 #define FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES 64
752 
753 /** Number of flexboot_nodnic Ethernet receive work queue entries */
754 #define FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES 64
755 /** flexboot nodnic Ethernet queue pair operations */
757  .alloc_iob = alloc_iob,
758 };
759 
760 /**
761  * Transmit packet via flexboot_nodnic Ethernet device
762  *
763  * @v netdev Network device
764  * @v iobuf I/O buffer
765  * @ret rc Return status code
766  */
768  struct io_buffer *iobuf) {
770  struct ib_device *ibdev = port->ibdev;
771  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
772  int rc;
773 
774  rc = ib_post_send ( ibdev, port->eth_qp, NULL, iobuf);
775  /* Transmit packet */
776  if ( rc != 0) {
777  DBGC ( flexboot_nodnic, "NODNIC %p port %d could not transmit: %s\n",
778  flexboot_nodnic, ibdev->port, strerror ( rc ) );
779  return rc;
780  }
781 
782  return 0;
783 }
784 
785 /**
786  * Handle flexboot_nodnic Ethernet device send completion
787  *
788  * @v ibdev Infiniband device
789  * @v qp Queue pair
790  * @v iobuf I/O buffer
791  * @v rc Completion status code
792  */
794  struct ib_queue_pair *qp,
795  struct io_buffer *iobuf,
796  int rc) {
797  struct net_device *netdev = ib_qp_get_ownerdata ( qp );
798 
799  netdev_tx_complete_err ( netdev, iobuf, rc );
800 }
801 
802 /**
803  * Handle flexboot_nodnic Ethernet device receive completion
804  *
805  * @v ibdev Infiniband device
806  * @v qp Queue pair
807  * @v av Address vector, or NULL
808  * @v iobuf I/O buffer
809  * @v rc Completion status code
810  */
812  struct ib_queue_pair *qp,
814  struct ib_address_vector *source,
815  struct io_buffer *iobuf,
816  int rc) {
817  struct net_device *netdev = ib_qp_get_ownerdata ( qp );
818 
819  if ( rc != 0 ) {
820  DBG ( "Received packet with error\n" );
821  netdev_rx_err ( netdev, iobuf, rc );
822  return;
823  }
824 
825  if ( source == NULL ) {
826  DBG ( "Received packet without address vector\n" );
827  netdev_rx_err ( netdev, iobuf, -ENOTTY );
828  return;
829  }
830 
831  netdev_rx ( netdev, iobuf );
832 }
833 
834 /** flexboot_nodnic Ethernet device completion operations */
837  .complete_recv = flexboot_nodnic_eth_complete_recv,
838 };
839 
840 /**
841  * Poll flexboot_nodnic Ethernet device
842  *
843  * @v netdev Network device
844  */
847  struct ib_device *ibdev = port->ibdev;
848 
849  ib_poll_eq ( ibdev );
850 }
851 
852 /**
853  * Open flexboot_nodnic Ethernet device
854  *
855  * @v netdev Network device
856  * @ret rc Return status code
857  */
860  struct ib_device *ibdev = port->ibdev;
861  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
863  struct ib_completion_queue *dummy_cq = NULL;
864  struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = NULL;
865  mlx_uint64 cq_size = 0;
866  mlx_uint32 qpn = 0;
868  int rc;
869 
870  if ( port->port_priv.port_state & NODNIC_PORT_OPENED ) {
871  DBGC ( flexboot_nodnic, "%s: port %d is already opened\n",
872  __FUNCTION__, port->ibdev->port );
873  return 0;
874  }
875 
876  port->port_priv.port_state |= NODNIC_PORT_OPENED;
877 
878  dummy_cq = zalloc ( sizeof ( struct ib_completion_queue ) );
879  if ( dummy_cq == NULL ) {
880  DBGC ( flexboot_nodnic, "%s: Failed to allocate dummy CQ\n", __FUNCTION__ );
882  goto err_create_dummy_cq;
883  }
884  INIT_LIST_HEAD ( &dummy_cq->work_queues );
885 
886  if ( ( rc = ib_create_qp ( ibdev, IB_QPT_ETH,
890  &port->eth_qp ) ) != 0 ) {
891  DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not create queue pair\n",
892  flexboot_nodnic, ibdev->port );
894  goto err_create_qp;
895  }
896 
897  ib_qp_set_ownerdata ( port->eth_qp, netdev );
898 
899  status = nodnic_port_get_cq_size(&port->port_priv, &cq_size);
900  MLX_FATAL_CHECK_STATUS(status, get_cq_size_err,
901  "nodnic_port_get_cq_size failed");
902 
903  if ( ( rc = ib_create_cq ( ibdev, cq_size, &flexboot_nodnic_eth_cq_op,
904  &port->eth_cq ) ) != 0 ) {
906  "flexboot_nodnic %p port %d could not create completion queue\n",
907  flexboot_nodnic, ibdev->port );
909  goto err_create_cq;
910  }
911  port->eth_qp->send.cq = port->eth_cq;
912  list_del(&port->eth_qp->send.list);
913  list_add ( &port->eth_qp->send.list, &port->eth_cq->work_queues );
914  port->eth_qp->recv.cq = port->eth_cq;
915  port->cmdsn = 0;
916  list_del(&port->eth_qp->recv.list);
917  list_add ( &port->eth_qp->recv.list, &port->eth_cq->work_queues );
918 
919  status = nodnic_port_allocate_eq(&port->port_priv,
921  MLX_FATAL_CHECK_STATUS(status, eq_alloc_err,
922  "nodnic_port_allocate_eq failed");
923 
924  status = nodnic_port_init(&port->port_priv);
925  MLX_FATAL_CHECK_STATUS(status, init_err,
926  "nodnic_port_init failed");
927 
928  /* update qp - qpn */
929  flexboot_nodnic_qp = ib_qp_get_drvdata ( port->eth_qp );
930  status = nodnic_port_get_qpn(&port->port_priv,
931  &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring,
932  &qpn);
934  "nodnic_port_get_qpn failed");
935  port->eth_qp->qpn = qpn;
936 
937  /* Fill receive rings */
938  ib_refill_recv ( ibdev, port->eth_qp );
939 
940  status = nodnic_port_enable_dma(&port->port_priv);
942  "nodnic_port_enable_dma failed");
943 
945  status = nodnic_port_set_promisc(&port->port_priv, TRUE);
946  MLX_FATAL_CHECK_STATUS(status, promisc_err,
947  "nodnic_port_set_promisc failed");
948  }
949 
950  status = nodnic_port_get_state(&port->port_priv, &state);
951  MLX_FATAL_CHECK_STATUS(status, state_err,
952  "nodnic_port_get_state failed");
953 
954  port->type->state_change (
956 
957  DBGC ( flexboot_nodnic, "%s: port %d opened (link is %s)\n",
958  __FUNCTION__, port->ibdev->port,
959  ( ( state == nodnic_port_state_active ) ? "Up" : "Down" ) );
960 
961  free(dummy_cq);
962  return 0;
963 state_err:
964 promisc_err:
965 dma_err:
966 qpn_err:
967  nodnic_port_close(&port->port_priv);
968 init_err:
969  nodnic_port_free_eq(&port->port_priv);
970 eq_alloc_err:
971 err_create_cq:
972 get_cq_size_err:
973  ib_destroy_qp(ibdev, port->eth_qp );
974 err_create_qp:
975  free(dummy_cq);
976 err_create_dummy_cq:
977  port->port_priv.port_state &= ~NODNIC_PORT_OPENED;
978  return status;
979 }
980 
981 /**
982  * Close flexboot_nodnic Ethernet device
983  *
984  * @v netdev Network device
985  */
988  struct ib_device *ibdev = port->ibdev;
989  struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
991 
992  if ( ! ( port->port_priv.port_state & NODNIC_PORT_OPENED ) ) {
993  DBGC ( flexboot_nodnic, "%s: port %d is already closed\n",
994  __FUNCTION__, port->ibdev->port );
995  return;
996  }
997 
999  if ( ( status = nodnic_port_set_promisc( &port->port_priv, FALSE ) ) ) {
1001  "nodnic_port_set_promisc failed (status = %d)\n", status );
1002  }
1003  }
1004 
1006 
1007  port->port_priv.port_state &= ~NODNIC_PORT_OPENED;
1008 
1009  port->type->state_change ( flexboot_nodnic, port, FALSE );
1010 
1011  /* Close port */
1012  status = nodnic_port_close(&port->port_priv);
1013  if ( status != MLX_SUCCESS ) {
1014  DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not close port: %s\n",
1015  flexboot_nodnic, ibdev->port, strerror ( status ) );
1016  /* Nothing we can do about this */
1017  }
1018 
1019  ib_destroy_qp ( ibdev, port->eth_qp );
1020  port->eth_qp = NULL;
1021  ib_destroy_cq ( ibdev, port->eth_cq );
1022  port->eth_cq = NULL;
1023 
1024  nodnic_port_free_eq(&port->port_priv);
1025 
1026  DBGC ( flexboot_nodnic, "%s: port %d closed\n", __FUNCTION__, port->ibdev->port );
1027 }
1028 
1029 void flexboot_nodnic_eth_irq ( struct net_device *netdev, int enable ) {
1030  struct flexboot_nodnic_port *port = netdev->priv;
1031 
1032  if ( enable ) {
1033  if ( ( port->port_priv.port_state & NODNIC_PORT_OPENED ) &&
1034  ! ( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) {
1036  } else {
1037  /* do nothing */
1038  }
1039  } else {
1040  nodnic_device_clear_int( port->port_priv.device );
1041  }
1042 }
1043 
1044 /** flexboot_nodnic Ethernet network device operations */
1047  .close = flexboot_nodnic_eth_close,
1048  .transmit = flexboot_nodnic_eth_transmit,
1049  .poll = flexboot_nodnic_eth_poll,
1050 };
1051 
1052 /**
1053  * Register flexboot_nodnic Ethernet device
1054  */
1056  struct flexboot_nodnic_port *port) {
1058  struct net_device *netdev;
1059  struct ib_device *ibdev = port->ibdev;
1060  union {
1061  uint8_t bytes[8];
1062  uint32_t dwords[2];
1063  } mac;
1064 
1065  /* Allocate network devices */
1066  netdev = alloc_etherdev ( 0 );
1067  if ( netdev == NULL ) {
1068  DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not allocate net device\n",
1069  flexboot_nodnic, ibdev->port );
1071  goto alloc_err;
1072  }
1073  port->netdev = netdev;
1075  netdev->dev = ibdev->dev;
1076  netdev->priv = port;
1077 
1078  status = nodnic_port_query(&port->port_priv,
1080  &mac.dwords[0]);
1081  MLX_FATAL_CHECK_STATUS(status, mac_err,
1082  "failed to query mac high");
1083  status = nodnic_port_query(&port->port_priv,
1085  &mac.dwords[1]);
1086  MLX_FATAL_CHECK_STATUS(status, mac_err,
1087  "failed to query mac low");
1088  mac.dwords[0] = htonl(mac.dwords[0]);
1089  mac.dwords[1] = htonl(mac.dwords[1]);
1090  memcpy ( netdev->hw_addr,
1091  &mac.bytes[2], ETH_ALEN);
1092  /* Register network device */
1094  if ( status != MLX_SUCCESS ) {
1096  "flexboot_nodnic %p port %d could not register network device: %s\n",
1097  flexboot_nodnic, ibdev->port, strerror ( status ) );
1098  goto reg_err;
1099  }
1100  return status;
1101 reg_err:
1102 mac_err:
1103  netdev_put ( netdev );
1104 alloc_err:
1105  return status;
1106 }
1107 
1108 /**
1109  * Handle flexboot_nodnic Ethernet device port state change
1110  */
1112  struct flexboot_nodnic_port *port,
1113  int link_up ) {
1114  struct net_device *netdev = port->netdev;
1115 
1116  if ( link_up )
1117  netdev_link_up ( netdev );
1118  else
1120 
1121 }
1122 
1123 /**
1124  * Unregister flexboot_nodnic Ethernet device
1125  */
1127  struct flexboot_nodnic_port *port ) {
1128  struct net_device *netdev = port->netdev;
1130  netdev_nullify ( netdev );
1131  netdev_put ( netdev );
1132 }
1133 
1134 /** flexboot_nodnic Ethernet port type */
1137  .state_change = flexboot_nodnic_state_change_netdev,
1138  .unregister_dev = flexboot_nodnic_unregister_netdev,
1139 };
1140 
1141 /***************************************************************************
1142  *
1143  * PCI interface helper functions
1144  *
1145  ***************************************************************************
1146  */
1147 static
1148 mlx_status
1151  nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1152  struct pci_device *pci = flexboot_nodnic_priv->pci;
1153  struct ib_device *ibdev = NULL;
1154  unsigned int i = 0;
1155 
1156  /* Allocate Infiniband devices */
1157  for (; i < device_priv->device_cap.num_ports; i++) {
1158  if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1159  continue;
1160  ibdev = alloc_ibdev(0);
1161  if (ibdev == NULL) {
1163  goto err_alloc_ibdev;
1164  }
1165  flexboot_nodnic_priv->port[i].ibdev = ibdev;
1167  ibdev->dev = &pci->dev;
1168  ibdev->port = ( FLEXBOOT_NODNIC_PORT_BASE + i);
1169  ibdev->ports = device_priv->device_cap.num_ports;
1170  ib_set_drvdata(ibdev, flexboot_nodnic_priv);
1171  }
1172  return status;
1173 err_alloc_ibdev:
1174  for ( i-- ; ( signed int ) i >= 0 ; i-- )
1175  ibdev_put ( flexboot_nodnic_priv->port[i].ibdev );
1176  return status;
1177 }
1178 
1179 static
1180 mlx_status
1181 flexboot_nodnic_thin_init_ports( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1183  nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1184  nodnic_port_priv *port_priv = NULL;
1185  unsigned int i = 0;
1186 
1187  for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
1188  if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1189  continue;
1190  port_priv = &flexboot_nodnic_priv->port[i].port_priv;
1191  status = nodnic_port_thin_init( device_priv, port_priv, i );
1192  MLX_FATAL_CHECK_STATUS(status, thin_init_err,
1193  "flexboot_nodnic_thin_init_ports failed");
1194  }
1195 thin_init_err:
1196  return status;
1197 }
1198 
1199 
1200 static
1201 mlx_status
1202 flexboot_nodnic_set_ports_type ( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1204  nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1205  nodnic_port_priv *port_priv = NULL;
1207  unsigned int i = 0;
1208 
1209  for ( i = 0 ; i < device_priv->device_cap.num_ports ; i++ ) {
1210  if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1211  continue;
1212  port_priv = &flexboot_nodnic_priv->port[i].port_priv;
1213  status = nodnic_port_get_type(port_priv, &type);
1214  MLX_FATAL_CHECK_STATUS(status, type_err,
1215  "nodnic_port_get_type failed");
1216  switch ( type ) {
1217  case NODNIC_PORT_TYPE_ETH:
1218  DBGC ( flexboot_nodnic_priv, "Port %d type is Ethernet\n", i );
1219  flexboot_nodnic_priv->port[i].type = &flexboot_nodnic_port_type_eth;
1220  break;
1221  case NODNIC_PORT_TYPE_IB:
1222  DBGC ( flexboot_nodnic_priv, "Port %d type is Infiniband\n", i );
1224  goto type_err;
1225  default:
1226  DBGC ( flexboot_nodnic_priv, "Port %d type is unknown\n", i );
1228  goto type_err;
1229  }
1230  }
1231 type_err:
1232  return status;
1233 }
1234 
1235 static
1236 mlx_status
1237 flexboot_nodnic_ports_register_dev( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1239  nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1240  struct flexboot_nodnic_port *port = NULL;
1241  unsigned int i = 0;
1242 
1243  for (; i < device_priv->device_cap.num_ports; i++) {
1244  if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1245  continue;
1246  port = &flexboot_nodnic_priv->port[i];
1247  status = port->type->register_dev ( flexboot_nodnic_priv, port );
1248  MLX_FATAL_CHECK_STATUS(status, reg_err,
1249  "port register_dev failed");
1250  }
1251 reg_err:
1252  return status;
1253 }
1254 
1255 static
1256 mlx_status
1257 flexboot_nodnic_ports_unregister_dev ( struct flexboot_nodnic *flexboot_nodnic_priv ) {
1258  struct flexboot_nodnic_port *port;
1259  nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
1260  int i = (device_priv->device_cap.num_ports - 1);
1261 
1262  for (; i >= 0; i--) {
1263  if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1264  continue;
1265  port = &flexboot_nodnic_priv->port[i];
1266  port->type->unregister_dev(flexboot_nodnic_priv, port);
1267  ibdev_put(flexboot_nodnic_priv->port[i].ibdev);
1268  }
1269  return MLX_SUCCESS;
1270 }
1271 
1272 /***************************************************************************
1273  *
1274  * flexboot nodnic interface
1275  *
1276  ***************************************************************************
1277  */
1278 __unused static void flexboot_nodnic_enable_dma ( struct flexboot_nodnic *nodnic ) {
1281  int i;
1282 
1283  for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) {
1284  if ( ! ( nodnic->port_mask & ( i + 1 ) ) )
1285  continue;
1286  port_priv = & ( nodnic->port[i].port_priv );
1287  if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) )
1288  continue;
1289 
1290  if ( ( status = nodnic_port_enable_dma ( port_priv ) ) ) {
1291  MLX_DEBUG_WARN ( nodnic, "Failed to enable DMA %d\n", status );
1292  }
1293  }
1294 }
1295 
1296 __unused static void flexboot_nodnic_disable_dma ( struct flexboot_nodnic *nodnic ) {
1297  int i;
1298 
1299  for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) {
1300  if ( ! ( nodnic->port_mask & ( i + 1 ) ) )
1301  continue;
1302  flexboot_nodnic_port_disable_dma ( & ( nodnic->port[i] ) );
1303  }
1304 }
1305 
1307  mlx_utils utils;
1310  int is_supported = 0;
1311 
1312  DBG ( "%s: start\n", __FUNCTION__ );
1313 
1314  memset ( &utils, 0, sizeof ( utils ) );
1315 
1316  status = mlx_utils_init ( &utils, pci );
1317  MLX_CHECK_STATUS ( pci, status, utils_init_err, "mlx_utils_init failed" );
1318 
1319  status = mlx_pci_gw_init ( &utils );
1320  MLX_CHECK_STATUS ( pci, status, pci_gw_init_err, "mlx_pci_gw_init failed" );
1321 
1324 
1325  if ( status == MLX_SUCCESS ) {
1327  is_supported = ( buffer & 0x1 );
1328  }
1329 
1330  mlx_pci_gw_teardown( &utils );
1331 
1332 pci_gw_init_err:
1333  mlx_utils_teardown(&utils);
1334 utils_init_err:
1335  DBG ( "%s: NODNIC is %s supported (status = %d)\n",
1336  __FUNCTION__, ( is_supported ? "": "not" ), status );
1337  return is_supported;
1338 }
1339 
1340 
1341 void flexboot_nodnic_copy_mac ( uint8_t mac_addr[], uint32_t low_byte,
1342  uint16_t high_byte ) {
1343  union mac_addr {
1344  struct {
1345  uint32_t low_byte;
1346  uint16_t high_byte;
1347  };
1348  uint8_t mac_addr[ETH_ALEN];
1349  } mac_addr_aux;
1350 
1351  mac_addr_aux.high_byte = high_byte;
1352  mac_addr_aux.low_byte = low_byte;
1353 
1354  mac_addr[0] = mac_addr_aux.mac_addr[5];
1355  mac_addr[1] = mac_addr_aux.mac_addr[4];
1356  mac_addr[2] = mac_addr_aux.mac_addr[3];
1357  mac_addr[3] = mac_addr_aux.mac_addr[2];
1358  mac_addr[4] = mac_addr_aux.mac_addr[1];
1359  mac_addr[5] = mac_addr_aux.mac_addr[0];
1360 }
1361 
1363  struct flexboot_nodnic *flexboot_nodnic_priv, uint8_t port __unused ) {
1364  struct mlx_vmac_query_virt_mac virt_mac;
1366 
1367  memset ( & virt_mac, 0, sizeof ( virt_mac ) );
1368  status = mlx_vmac_query_virt_mac ( flexboot_nodnic_priv->device_priv.utils,
1369  &virt_mac );
1370  if ( ! status ) {
1371  DBGC ( flexboot_nodnic_priv, "NODNIC %p Failed to set the virtual MAC\n"
1372  ,flexboot_nodnic_priv );
1373  }
1374 
1375  return status;
1376 }
1377 
1378 
1379 /**
1380  * Set port masking
1381  *
1382  * @v flexboot_nodnic nodnic device
1383  * @ret rc Return status code
1384  */
1386  unsigned int i;
1388 
1390  for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
1391  flexboot_nodnic->port_mask |= (i + 1);
1392  }
1393 
1394  if ( ! flexboot_nodnic->port_mask ) {
1395  /* No port was enabled */
1396  DBGC ( flexboot_nodnic, "NODNIC %p No port was enabled for "
1397  "booting\n", flexboot_nodnic );
1398  return -ENETUNREACH;
1399  }
1400 
1401  return 0;
1402 }
1403 
1404 int init_mlx_utils ( mlx_utils **utils, struct pci_device *pci ) {
1405  int rc = 0;
1406 
1407  *utils = ( mlx_utils * ) zalloc ( sizeof ( mlx_utils ) );
1408  if ( *utils == NULL ) {
1409  DBGC ( utils, "%s: Failed to allocate utils\n", __FUNCTION__ );
1410  rc = -1;
1411  goto err_utils_alloc;
1412  }
1413  if ( mlx_utils_init ( *utils, pci ) ) {
1414  DBGC ( utils, "%s: mlx_utils_init failed\n", __FUNCTION__ );
1415  rc = -1;
1416  goto err_utils_init;
1417  }
1418  if ( mlx_pci_gw_init ( *utils ) ){
1419  DBGC ( utils, "%s: mlx_pci_gw_init failed\n", __FUNCTION__ );
1420  rc = -1;
1421  goto err_cmd_init;
1422  }
1423 
1424  return 0;
1425 
1426  mlx_pci_gw_teardown ( *utils );
1427 err_cmd_init:
1428  mlx_utils_teardown ( *utils );
1429 err_utils_init:
1430  free ( *utils );
1431 err_utils_alloc:
1432  *utils = NULL;
1433 
1434  return rc;
1435 }
1436 
1437 void free_mlx_utils ( mlx_utils **utils ) {
1438 
1439  mlx_pci_gw_teardown ( *utils );
1440  mlx_utils_teardown ( *utils );
1441  free ( *utils );
1442  *utils = NULL;
1443 }
1444 
1445 /**
1446  * Initialise Nodnic PCI parameters
1447  *
1448  * @v hermon Nodnic device
1449  */
1452  struct pci_device *pci = flexboot_nodnic->pci;
1454 
1456  DBGC ( flexboot_nodnic, "%s: tx db using uar is not supported \n", __FUNCTION__ );
1457  return -ENOTSUP;
1458  }
1459  /* read uar offset then allocate */
1461  DBGC ( flexboot_nodnic, "%s: nodnic_port_set_send_uar_offset failed,"
1462  "status = %d\n", __FUNCTION__, status );
1463  return -EINVAL;
1464  }
1465  uar->phys = ( pci_bar_start ( pci, FLEXBOOT_NODNIC_HCA_BAR ) + (mlx_uint32)uar->offset );
1466  uar->virt = ( void * )( pci_ioremap ( pci, uar->phys, FLEXBOOT_NODNIC_PAGE_SIZE ) );
1467 
1468  return status;
1469 }
1470 
1473 
1474  if ( uar->virt ) {
1475  iounmap( uar->virt );
1476  uar->virt = NULL;
1477  }
1478 
1479  return MLX_SUCCESS;
1480 }
1481 
1482 
1484  struct flexboot_nodnic_callbacks *callbacks,
1485  void *drv_priv __unused ) {
1487  struct flexboot_nodnic *flexboot_nodnic_priv = NULL;
1489  int i = 0;
1490 
1491  if ( ( pci == NULL ) || ( callbacks == NULL ) ) {
1492  DBGC ( flexboot_nodnic_priv, "%s: Bad Parameter\n", __FUNCTION__ );
1493  return -EINVAL;
1494  }
1495 
1496  flexboot_nodnic_priv = zalloc( sizeof ( *flexboot_nodnic_priv ) );
1497  if ( flexboot_nodnic_priv == NULL ) {
1498  DBGC ( flexboot_nodnic_priv, "%s: Failed to allocate priv data\n", __FUNCTION__ );
1500  goto device_err_alloc;
1501  }
1502 
1503  /* Register settings
1504  * Note that pci->priv will be the device private data */
1505  flexboot_nodnic_priv->pci = pci;
1506  flexboot_nodnic_priv->callbacks = callbacks;
1507  pci_set_drvdata ( pci, flexboot_nodnic_priv );
1508 
1509  device_priv = &flexboot_nodnic_priv->device_priv;
1510  /* init mlx utils */
1512  MLX_FATAL_CHECK_STATUS(status, err_utils_init,
1513  "init_mlx_utils failed");
1514 
1515  /* init device */
1517  MLX_FATAL_CHECK_STATUS(status, device_init_err,
1518  "nodnic_device_init failed");
1519 
1521  MLX_FATAL_CHECK_STATUS(status, get_cap_err,
1522  "nodnic_device_get_cap failed");
1523 
1525  MLX_DEBUG_ERROR( device_priv->utils, "Failed to set admin mtu\n" );
1526  }
1527 
1528  status = flexboot_nodnic_set_port_masking ( flexboot_nodnic_priv );
1529  MLX_FATAL_CHECK_STATUS(status, err_set_masking,
1530  "flexboot_nodnic_set_port_masking failed");
1531 
1532  status = flexboot_nodnic_allocate_infiniband_devices( flexboot_nodnic_priv );
1533  MLX_FATAL_CHECK_STATUS(status, err_alloc_ibdev,
1534  "flexboot_nodnic_allocate_infiniband_devices failed");
1535 
1536  /* port init */
1537  status = flexboot_nodnic_thin_init_ports( flexboot_nodnic_priv );
1538  MLX_FATAL_CHECK_STATUS(status, err_thin_init_ports,
1539  "flexboot_nodnic_thin_init_ports failed");
1540 
1541  if ( ( status = flexboot_nodnic_alloc_uar ( flexboot_nodnic_priv ) ) ) {
1542  DBGC(flexboot_nodnic_priv, "%s: flexboot_nodnic_alloc_uar failed"
1543  " ( status = %d )\n",__FUNCTION__, status );
1544  }
1545 
1546  /* device reg */
1547  status = flexboot_nodnic_set_ports_type( flexboot_nodnic_priv );
1548  MLX_CHECK_STATUS( flexboot_nodnic_priv, status, err_set_ports_types,
1549  "flexboot_nodnic_set_ports_type failed");
1550 
1551  status = flexboot_nodnic_ports_register_dev( flexboot_nodnic_priv );
1552  MLX_FATAL_CHECK_STATUS(status, reg_err,
1553  "flexboot_nodnic_ports_register_dev failed");
1554 
1555  for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
1556  if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
1557  continue;
1558  flexboot_nodnic_get_factory_mac ( flexboot_nodnic_priv, i );
1559  }
1560 
1561  /* Update ETH operations with IRQ function if supported */
1562  DBGC ( flexboot_nodnic_priv, "%s: %s IRQ function\n",
1563  __FUNCTION__, ( callbacks->irq ? "Valid" : "No" ) );
1565  return 0;
1566 
1567  flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv );
1568 reg_err:
1569 err_set_ports_types:
1570  flexboot_nodnic_dealloc_uar ( flexboot_nodnic_priv );
1571 err_thin_init_ports:
1572 err_alloc_ibdev:
1573 err_set_masking:
1574 get_cap_err:
1576 device_init_err:
1578 err_utils_init:
1579  free ( flexboot_nodnic_priv );
1580 device_err_alloc:
1581  return status;
1582 }
1583 
1585 {
1586  struct flexboot_nodnic *flexboot_nodnic_priv = pci_get_drvdata ( pci );
1587  nodnic_device_priv *device_priv = & ( flexboot_nodnic_priv->device_priv );
1588 
1589  flexboot_nodnic_dealloc_uar ( flexboot_nodnic_priv );
1590  flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv );
1593  free( flexboot_nodnic_priv );
1594 }
struct nodnic_ring nodnic_ring
#define EINVAL
Invalid argument.
Definition: errno.h:428
static __always_inline void ib_set_drvdata(struct ib_device *ibdev, void *priv)
Set Infiniband device driver-private data.
Definition: infiniband.h:697
mlx_status mlx_vmac_query_virt_mac(IN mlx_utils *utils, OUT struct mlx_vmac_query_virt_mac *virt_mac)
Definition: mlx_vmac.c:27
mlx_status nodnic_device_get_cap(IN nodnic_device_priv *device_priv)
Definition: mlx_device.c:230
static void flexboot_nodnic_ib_close(struct ib_device *ibdev __attribute__((unused)))
Close Infiniband link.
void ib_poll_eq(struct ib_device *ibdev)
Poll event queue.
Definition: infiniband.c:878
iPXE I/O API
mlx_status nodnic_port_allocate_eq(IN nodnic_port_priv *port_priv, IN mlx_uint8 log_eq_size)
Definition: mlx_port.c:915
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
wmb()
mlx_status nodnic_port_get_state(IN nodnic_port_priv *port_priv, OUT nodnic_port_state *state)
Definition: mlx_port.c:88
static mlx_status flexboot_nodnic_thin_init_ports(struct flexboot_nodnic *flexboot_nodnic_priv)
#define iob_put(iobuf, len)
Definition: iobuf.h:124
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition: netdevice.c:586
struct nodnic_send_ring send
#define NODNIC_PORT_DISABLING_DMA
#define NODNIC_NIC_INTERFACE_SUPPORTED_BIT
Definition: mlx_device.h:41
Infiniband device operations.
Definition: infiniband.h:254
mlx_status nodnic_port_close(IN nodnic_port_priv *port_priv)
Definition: mlx_port.c:1255
void __asmcall int val
Definition: setjmp.h:12
uint8_t state
State.
Definition: eth_slow.h:47
void flexboot_nodnic_copy_mac(uint8_t mac_addr[], uint32_t low_byte, uint16_t high_byte)
int flexboot_nodnic_is_supported(struct pci_device *pci)
struct ib_device * ibdev
Infiniband device.
int(* open)(struct net_device *netdev)
Open network device.
Definition: netdevice.h:222
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
mlx_status nodnic_device_init(IN nodnic_device_priv *device_priv)
Definition: mlx_device.c:195
mlx_status mlx_pci_gw_read(IN mlx_utils *utils, IN mlx_pci_gw_space space, IN mlx_uint32 address, OUT mlx_pci_gw_buffer *buffer)
Definition: mlx_pci_gw.c:258
mlx_status mlx_pci_mem_write(IN mlx_utils *utils, IN mlx_pci_width width, IN mlx_uint8 bar_index, IN mlx_uint64 offset, IN mlx_uintn count, IN mlx_void *buffer)
Definition: mlx_pci.c:116
Error codes.
mlx_uint32 is_error
static mlx_status flexboot_nodnic_set_ports_type(struct flexboot_nodnic *flexboot_nodnic_priv)
static int flexboot_nodnic_set_port_masking(struct flexboot_nodnic *flexboot_nodnic)
Set port masking.
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)
Definition: mlx_port.c:585
#define FLEXBOOT_NODNIC_HCA_BAR
static int flexboot_nodnic_post_recv(struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf)
Post receive work queue entry.
static int flexboot_nodnic_modify_qp(struct ib_device *ibdev __attribute__((unused)), struct ib_queue_pair *qp __attribute__((unused)))
Modify queue pair.
uint32_t type
Operating system type.
Definition: ena.h:12
nodnic_device_priv device_priv
nodnic device
int ib_create_cq(struct ib_device *ibdev, unsigned int num_cqes, struct ib_completion_queue_operations *op, struct ib_completion_queue **new_cq)
Create completion queue.
Definition: infiniband.c:98
#define NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET
Definition: mlx_device.h:33
void ib_refill_recv(struct ib_device *ibdev, struct ib_queue_pair *qp)
Refill receive work queue.
Definition: infiniband.c:556
#define DBGC(...)
Definition: compiler.h:505
__be32 byte_count
Definition: CIB_PRM.h:28
mlx_uint32 byte_cnt
struct io_buffer *(* alloc_iob)(size_t len)
Allocate receive I/O buffer.
Definition: infiniband.h:153
static void flexboot_nodnic_unregister_netdev(struct flexboot_nodnic *flexboot_nodnic __attribute__((unused)), struct flexboot_nodnic_port *port)
Unregister flexboot_nodnic Ethernet device.
static int flexboot_nodnic_dealloc_uar(struct flexboot_nodnic *flexboot_nodnic)
struct device * dev
Underlying device.
Definition: infiniband.h:410
nodnic_device_priv * device
static int flexboot_nodnic_alloc_uar(struct flexboot_nodnic *flexboot_nodnic)
Initialise Nodnic PCI parameters.
static __always_inline void * ib_qp_get_drvdata(struct ib_queue_pair *qp)
Get Infiniband queue pair driver-private data.
Definition: infiniband.h:642
static struct net_device_operations flexboot_nodnic_eth_operations
flexboot_nodnic Ethernet network device operations
mlx_status nodnic_device_clear_int(IN nodnic_device_priv *device_priv)
Definition: mlx_device.c:165
struct pci_device * pci
PCI device.
static struct ib_queue_pair_operations flexboot_nodnic_eth_qp_op
flexboot nodnic Ethernet queue pair operations
int init_mlx_utils(mlx_utils **utils, struct pci_device *pci)
void netdev_link_down(struct net_device *netdev)
Mark network device as having link down.
Definition: netdevice.c:230
#define FLEX_NODNIC_TX_POLL_USLEEP
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
uint8_t mac[ETH_ALEN]
MAC address.
Definition: ena.h:24
u16 port_mask
Port masking.
mlx_status mlx_pci_gw_init(IN mlx_utils *utils)
Definition: mlx_pci_gw.c:218
mlx_void * cq_virt
cq entries
mlx_status nodnic_port_free_eq(IN nodnic_port_priv *port_priv)
Definition: mlx_port.c:968
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:130
An Infiniband Global Identifier.
Definition: ib_packet.h:33
struct nodnic_send_wqbb * wqe_virt
__be32 qpn
Definition: CIB_PRM.h:29
#define ARM_CQ_UAR_CMDSN_MASK
#define htonl(value)
Definition: byteswap.h:133
struct device dev
Generic device.
Definition: pci.h:212
#define MLX_DEBUG_WARN(...)
Definition: mlx_logging.h:30
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
void ib_destroy_cq(struct ib_device *ibdev, struct ib_completion_queue *cq)
Destroy completion queue.
Definition: infiniband.c:145
static int flexboot_nodnic_create_cq(struct ib_device *ibdev, struct ib_completion_queue *cq)
Create completion queue.
mlx_status(* cqe_set_owner)(void *cq, unsigned int num_cqes)
Dynamic memory allocation.
mlx_status nodnic_port_add_mac_filter(IN nodnic_port_priv *port_priv, IN mlx_mac_address mac)
Definition: mlx_port.c:992
static struct ib_work_queue * flexboot_nodnic_find_wq(struct ib_device *ibdev, struct ib_completion_queue *cq, unsigned long qpn, int is_send)
An Infiniband device.
Definition: infiniband.h:398
struct ib_completion_queue * cq
Associated completion queue.
Definition: infiniband.h:106
mlx_uint32 dword[2]
uint32_t mlx_uint32
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition: netdevice.h:518
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
void(* irq)(struct net_device *netdev, int enable)
Enable or disable interrupts.
Definition: netdevice.h:276
#define ARM_CQ_UAR_CQ_CI_OFFSET
static void pci_set_drvdata(struct pci_device *pci, void *priv)
Set PCI driver-private data.
Definition: pci.h:365
Infiniband completion queue operations.
Definition: infiniband.h:194
mlx_status nodnic_device_teardown(IN nodnic_device_priv *device_priv)
Definition: mlx_device.c:218
void * memcpy(void *dest, const void *src, size_t len) __nonnull
Infiniband queue pair operations.
Definition: infiniband.h:147
u8 port
Port number.
Definition: CIB_PRM.h:31
nodnic_port_state
Definition: mlx_port.h:69
static __always_inline void * ib_get_drvdata(struct ib_device *ibdev)
Get Infiniband device driver-private data.
Definition: infiniband.h:708
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:661
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
mlx_status nodnic_port_enable_dma(IN nodnic_port_priv *port_priv)
Definition: mlx_port.c:1275
static void flexboot_nodnic_poll_cq(struct ib_device *ibdev, struct ib_completion_queue *cq)
Poll completion queue.
#define FLEX_NODNIC_TX_POLL_TOUT
mlx_status nodnic_port_disable_dma(IN nodnic_port_priv *port_priv)
Definition: mlx_port.c:1295
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES
Number of flexboot_nodnic Ethernet receive work queue entries.
static mlx_status flexboot_nodnic_ports_unregister_dev(struct flexboot_nodnic *flexboot_nodnic_priv)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:575
Ethernet protocol.
struct ib_device_operations * op
Infiniband operations.
Definition: infiniband.h:416
void flexboot_nodnic_eth_irq(struct net_device *netdev, int enable)
static void flexboot_nodnic_destroy_cq(struct ib_device *ibdev, struct ib_completion_queue *cq)
Destroy completion queue.
#define FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES
Number of flexboot_nodnic Ethernet send work queue entries.
An Infiniband Work Queue.
Definition: infiniband.h:100
struct nodnic_wqe_segment_data_ptr data[NODNIC_MAX_SCATTER]
Definition: nodnic_prm.h:44
void * priv
Driver private data.
Definition: netdevice.h:431
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
mlx_status nodnic_port_create_cq(IN nodnic_port_priv *port_priv, IN mlx_size cq_size, OUT nodnic_cq **cq)
Definition: mlx_port.c:360
static mlx_status flexboot_nodnic_ports_register_dev(struct flexboot_nodnic *flexboot_nodnic_priv)
#define DBGC_HDA(...)
Definition: compiler.h:506
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static int flexboot_nodnic_inform_sma(struct ib_device *ibdev __attribute__((unused)), union ib_mad *mad __attribute__((unused)))
Inform embedded subnet management agent of a received MAD.
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition: netdevice.h:788
ring len
Length.
Definition: dwmac.h:231
void ib_complete_send(struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
Complete send work queue entry.
Definition: infiniband.c:515
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: timer.c:60
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition: netdevice.h:639
nodnic_device_capabilites device_cap
mlx_status nodnic_port_init(IN nodnic_port_priv *port_priv)
Definition: mlx_port.c:1235
static struct net_device * netdev
Definition: gdbudp.c:52
mlx_status(* tx_uar_send_doorbell_fn)(struct ib_device *ibdev, struct nodnic_send_wqbb *wqbb)
unsigned long pci_bar_start(struct pci_device *pci, unsigned int reg)
Find the start of a PCI BAR.
Definition: pci.c:96
mlx_status nodnic_port_get_type(IN nodnic_port_priv *port_priv, OUT nodnic_port_type *type)
Definition: mlx_port.c:105
mlx_status nodnic_port_thin_init(IN nodnic_device_priv *device_priv, IN nodnic_port_priv *port_priv, IN mlx_uint8 port_index)
Definition: mlx_port.c:1315
static int flexboot_nodnic_eth_open(struct net_device *netdev)
Open flexboot_nodnic Ethernet device.
#define MLX_SUCCESS
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition: netdevice.c:941
mlx_status(* fill_completion)(void *cqe, struct cqe_data *cqe_data)
unsigned int num_wqes
Number of work queue entries.
Definition: infiniband.h:112
struct list_head work_queues
List of work queues completing to this queue.
Definition: infiniband.h:242
A flexboot_nodnic device.
unsigned int port
Port number.
Definition: infiniband.h:418
static __always_inline void ibdev_put(struct ib_device *ibdev)
Drop reference to Infiniband device.
Definition: infiniband.h:598
static __always_inline void ib_cq_set_drvdata(struct ib_completion_queue *cq, void *priv)
Set Infiniband completion queue driver-private data.
Definition: infiniband.h:675
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
static void flexboot_nodnic_mcast_detach(struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
mlx_status(* register_dev)(struct flexboot_nodnic *flexboot_nodnic, struct flexboot_nodnic_port *port)
Register port.
static __always_inline void * ib_qp_get_ownerdata(struct ib_queue_pair *qp)
Get Infiniband queue pair owner-private data.
Definition: infiniband.h:664
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:661
struct nodnic_recv_ring receive
mlx_status nodnic_port_destroy_cq(IN nodnic_port_priv *port_priv, IN nodnic_cq *cq)
Definition: mlx_port.c:426
mlx_status mlx_utils_init(IN mlx_utils *utils, IN mlx_pci *pci)
Definition: mlx_utils.c:28
mlx_status nodnic_port_query(IN nodnic_port_priv *port_priv, IN nodnic_port_option option, OUT mlx_uint32 *out)
Definition: mlx_port.c:126
static void flexboot_nodnic_eth_complete_recv(struct ib_device *ibdev __attribute__((unused)), struct ib_queue_pair *qp, struct ib_address_vector *dest __attribute__((unused)), struct ib_address_vector *source, struct io_buffer *iobuf, int rc)
Handle flexboot_nodnic Ethernet device receive completion.
PCI bus.
A PCI device.
Definition: pci.h:210
int register_netdev(struct net_device *netdev)
Register network device.
Definition: netdevice.c:759
#define ARM_CQ_UAR_CQ_CI_MASK
struct ib_device * alloc_ibdev(size_t priv_size)
Allocate Infiniband device.
Definition: infiniband.c:917
mlx_status nodnic_port_get_cq_size(IN nodnic_port_priv *port_priv, OUT mlx_uint64 *cq_size)
Definition: mlx_port.c:899
static void flexboot_nodnic_poll_eq(struct ib_device *ibdev)
User memory allocation.
#define FLEXBOOT_NODNIC_PORT_BASE
A network device.
Definition: netdevice.h:352
#define MLX_FATAL_CHECK_STATUS(status, label, message)
Definition: mlx_bail.h:29
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:179
static void flexboot_nodnic_destroy_qp(struct ib_device *ibdev, struct ib_queue_pair *qp)
Destroy queue pair.
static void flexboot_nodnic_eth_close(struct net_device *netdev)
Close flexboot_nodnic Ethernet device.
#define MLX_UNSUPPORTED
unsigned int fill
Number of occupied work queue entries.
Definition: infiniband.h:114
An Infiniband Completion Queue.
Definition: infiniband.h:224
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:531
static int flexboot_nodnic_post_send(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf)
Post send work queue entry.
#define MLX_FILL_1(_ptr, _index,...)
Definition: mlx_bitops.h:167
size_t mlx_size
#define MLX_FILL_H(_structure_st, _index, _field, _address)
Definition: mlx_bitops.h:240
unsigned char uint8_t
Definition: stdint.h:10
static int flexboot_nodnic_ib_open(struct ib_device *ibdev __attribute__((unused)))
Initialise Infiniband link.
void ib_destroy_qp(struct ib_device *ibdev, struct ib_queue_pair *qp)
Destroy queue pair.
Definition: infiniband.c:314
#define EN_DEFAULT_ADMIN_MTU
mlx_uint32 vendor_err_syndrome
mlx_uint64 qword
static mlx_status flexboot_nodnic_get_factory_mac(struct flexboot_nodnic *flexboot_nodnic_priv, uint8_t port __attribute__((unused)))
#define NODNIC_PORT_OPENED
mlx_status nodnic_port_set(IN nodnic_port_priv *port_priv, IN nodnic_port_option option, IN mlx_uint32 in)
Definition: mlx_port.c:155
unsigned long qpn
Queue Pair Number.
Definition: infiniband.h:74
#define ETH_ALEN
Definition: if_ether.h:8
A flexboot_nodnic port type.
void flexboot_nodnic_remove(struct pci_device *pci)
struct ib_queue_pair * qp
Containing queue pair.
Definition: infiniband.h:102
static int flexboot_nodnic_eth_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet via flexboot_nodnic Ethernet device.
unsigned int ports
Total ports on device.
Definition: infiniband.h:420
unsigned int uint32_t
Definition: stdint.h:12
mlx_status mlx_utils_teardown(IN mlx_utils *utils)
Definition: mlx_utils.c:46
static struct ib_completion_queue_operations flexboot_nodnic_eth_cq_op
flexboot_nodnic Ethernet device completion operations
unsigned long next_idx
Next work queue entry index.
Definition: infiniband.h:122
#define MLX_FAILED
#define TRUE
Definition: tlan.h:46
uint16_t mlx_uint16
#define ENETDOWN
Network is down.
Definition: errno.h:478
mlx_status mlx_set_admin_mtu(IN mlx_utils *utils, IN mlx_uint8 port_num, IN mlx_uint32 admin_mtu)
Definition: mlx_mtu.c:63
unsigned long next_idx
Next completion queue entry index.
Definition: infiniband.h:240
uint8_t status
Status.
Definition: ena.h:16
Network device operations.
Definition: netdevice.h:213
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition: netdevice.c:548
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
struct list_head list
List of work queues on this completion queue.
Definition: infiniband.h:108
An Infiniband Queue Pair.
Definition: infiniband.h:157
struct list_head cqs
List of completion queues.
Definition: infiniband.h:412
unsigned long mlx_uintn
static int flexboot_nodnic_complete(struct ib_device *ibdev, struct ib_completion_queue *cq, struct cqe_data *cqe_data)
Handle completion.
nodnic_port_priv port_priv
nodic port
static void * pci_get_drvdata(struct pci_device *pci)
Get PCI driver-private data.
Definition: pci.h:375
mlx_status nodnic_port_destroy_qp(IN nodnic_port_priv *port_priv, IN nodnic_queue_pair_type type, IN nodnic_qp *qp)
Definition: mlx_port.c:726
struct arbelprm_qp_db_record qp
Definition: arbel.h:13
int ib_post_send(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct io_buffer *iobuf)
Post send work queue entry.
Definition: infiniband.c:416
#define cpu_to_be32(value)
Definition: byteswap.h:110
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
static mlx_status flexboot_nodnic_allocate_infiniband_devices(struct flexboot_nodnic *flexboot_nodnic_priv)
#define MLX_OUT_OF_RESOURCES
static struct flexboot_nodnic_port_type flexboot_nodnic_port_type_eth
flexboot_nodnic Ethernet port type
void netdev_tx_complete_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Complete network transmission.
Definition: netdevice.c:470
static int flexboot_nodnic_create_qp(struct ib_device *ibdev, struct ib_queue_pair *qp)
Create queue pair.
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
mlx_uint32 syndrome
static void flexboot_nodnic_eth_complete_send(struct ib_device *ibdev __attribute__((unused)), struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
Handle flexboot_nodnic Ethernet device send completion.
#define ENOBUFS
No buffer space available.
Definition: errno.h:498
struct flexboot_nodnic_port port[FLEXBOOT_NODNIC_MAX_PORTS]
flexboot_nodnic ports
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
int ib_create_qp(struct ib_device *ibdev, enum ib_queue_pair_type type, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq, struct ib_queue_pair_operations *op, const char *name, struct ib_queue_pair **new_qp)
Create queue pair.
Definition: infiniband.c:199
static void flexboot_nodnic_eth_poll(struct net_device *netdev)
Poll flexboot_nodnic Ethernet device.
void * data
Start of data.
Definition: iobuf.h:52
static int flexboot_nodnic_arm_cq(struct flexboot_nodnic_port *port)
#define EIO
Input/output error.
Definition: errno.h:433
#define MLX_DEBUG_ERROR(...)
Definition: mlx_logging.h:29
void ib_poll_cq(struct ib_device *ibdev, struct ib_completion_queue *cq)
Poll completion queue.
Definition: infiniband.c:161
#define FLEXBOOT_NODNIC_PAGE_SIZE
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition: ethernet.c:264
void(* complete_send)(struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
Complete Send WQE.
Definition: infiniband.h:203
unsigned long cqn
Completion queue number.
Definition: infiniband.h:230
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
void iounmap(volatile const void *io_addr)
Unmap I/O address.
uint8_t data[48]
Additional event data.
Definition: ena.h:22
unsigned int num_cqes
Number of completion queue entries.
Definition: infiniband.h:232
Virtual LANs.
A management datagram.
Definition: ib_mad.h:610
A flexboot nodnic port.
#define DBGCP(...)
Definition: compiler.h:539
#define FALSE
Definition: tlan.h:45
void ib_complete_recv(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct ib_address_vector *source, struct io_buffer *iobuf, int rc)
Complete receive work queue entry.
Definition: infiniband.c:536
void free_mlx_utils(mlx_utils **utils)
An Infiniband Address Vector.
Definition: infiniband.h:72
mlx_boolean owner
int mlx_status
mlx_status nodnic_port_set_send_uar_offset(IN nodnic_port_priv *port_priv)
Definition: mlx_port.c:197
Network interface management.
void timeout(int)
int flexboot_nodnic_probe(struct pci_device *pci, struct flexboot_nodnic_callbacks *callbacks, void *drv_priv __attribute__((unused)))
mlx_status nodnic_port_get_qpn(IN nodnic_port_priv *port_priv, IN struct nodnic_ring *ring, OUT mlx_uint32 *qpn)
Definition: mlx_port.c:796
mlx_status nodnic_port_set_promisc(IN nodnic_port_priv *port_priv, IN mlx_boolean value)
Definition: mlx_port.c:1205
struct flexboot_nodnic_callbacks * callbacks
nic specific data
mlx_uint32 qpn
static void flexboot_nodnic_port_disable_dma(struct flexboot_nodnic_port *port)
static int flexboot_nodnic_register_netdev(struct flexboot_nodnic *flexboot_nodnic, struct flexboot_nodnic_port *port)
Register flexboot_nodnic Ethernet device.
mlx_status mlx_pci_gw_teardown(IN mlx_utils *utils)
Definition: mlx_pci_gw.c:247
mlx_uint32 wqe_counter
uint64_t mlx_uint64
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static int flexboot_nodnic_mcast_attach(struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
static struct ib_device_operations flexboot_nodnic_ib_operations
flexboot_nodnic Infiniband operations
__be32 cqn
Definition: CIB_PRM.h:29
void * pci_ioremap(struct pci_device *pci, unsigned long bus_addr, size_t len)
Map PCI bus address as an I/O address.
#define MLX_CHECK_STATUS(id, status, label, message)
Definition: mlx_bail.h:37
int is_send
"Is a send queue" flag
Definition: infiniband.h:104
uint8_t bytes[64]
Definition: ib_mad.h:16
u8 gid[16]
Definition: CIB_PRM.h:31
#define ENETUNREACH
Network unreachable.
Definition: errno.h:488
struct flexboot_nodnic_port_type * type
Port type.
static __always_inline void * ib_cq_get_drvdata(struct ib_completion_queue *cq)
Get Infiniband completion queue driver-private data.
Definition: infiniband.h:686
FILE_LICENCE(GPL2_OR_LATER)
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:381
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
static __always_inline void ib_qp_set_ownerdata(struct ib_queue_pair *qp, void *priv)
Set Infiniband queue pair owner-private data.
Definition: infiniband.h:653
String functions.
void(* irq)(struct net_device *netdev, int enable)
void writeq(uint64_t data, volatile uint64_t *io_addr)
Write 64-bit qword to memory-mapped device.
#define ARM_CQ_UAR_CMDSN_OFFSET
union ib_mad mad
Definition: arbel.h:12
static __always_inline void ib_qp_set_drvdata(struct ib_queue_pair *qp, void *priv)
Set Infiniband queue pair driver-private data.
Definition: infiniband.h:631
int(* create_cq)(struct ib_device *ibdev, struct ib_completion_queue *cq)
Create completion queue.
Definition: infiniband.h:261
static void flexboot_nodnic_state_change_netdev(struct flexboot_nodnic *flexboot_nodnic __attribute__((unused)), struct flexboot_nodnic_port *port, int link_up)
Handle flexboot_nodnic Ethernet device port state change.
mlx_uint32 mlx_pci_gw_buffer
Definition: mlx_pci_gw.h:52
mlx_uint32 is_send
#define DBG2(...)
Definition: compiler.h:515
mlx_status nodnic_port_remove_mac_filter(IN nodnic_port_priv *port_priv, IN mlx_mac_address mac)
Definition: mlx_port.c:1073
static void flexboot_nodnic_complete_all_tx(struct flexboot_nodnic_port *port)
void * memset(void *dest, int character, size_t len) __nonnull
A flexboot nodnic queue pair.
A persistent I/O buffer.
Definition: iobuf.h:37
#define PCI_GW_SPACE_NODNIC
Definition: mlx_pci_gw.h:47
struct nodnic_ring nodnic_ring
struct io_buffer ** iobufs
I/O buffers assigned to work queue.
Definition: infiniband.h:124