iPXE
Defines | Functions | Variables
flexboot_nodnic.c File Reference
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <ipxe/pci.h>
#include <ipxe/malloc.h>
#include <ipxe/umalloc.h>
#include <ipxe/if_ether.h>
#include <ipxe/ethernet.h>
#include <ipxe/vlan.h>
#include <ipxe/io.h>
#include "flexboot_nodnic.h"
#include "mlx_utils/include/public/mlx_types.h"
#include "mlx_utils/include/public/mlx_utils.h"
#include "mlx_utils/include/public/mlx_bail.h"
#include "mlx_nodnic/include/mlx_cmd.h"
#include "mlx_utils/include/public/mlx_memory.h"
#include "mlx_utils/include/public/mlx_pci.h"
#include "mlx_nodnic/include/mlx_device.h"
#include "mlx_nodnic/include/mlx_port.h"
#include <byteswap.h>
#include <usr/ifmgmt.h>
#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h"
#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h"
#include "mlx_utils/include/public/mlx_pci_gw.h"
#include "mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.h"
#include "mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.h"

Go to the source code of this file.

Defines

#define ARM_CQ_UAR_CQ_CI_MASK   0xffffff
#define ARM_CQ_UAR_CMDSN_MASK   3
#define ARM_CQ_UAR_CMDSN_OFFSET   28
#define ARM_CQ_UAR_CQ_CI_OFFSET   0x20
#define FLEX_NODNIC_TX_POLL_TOUT   500000
#define FLEX_NODNIC_TX_POLL_USLEEP   10
#define FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES   64
 Number of flexboot_nodnic Ethernet send work queue entries.
#define FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES   64
 Number of flexboot_nodnic Ethernet receive work queue entries.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int flexboot_nodnic_arm_cq (struct flexboot_nodnic_port *port)
static int flexboot_nodnic_create_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Create completion queue.
static void flexboot_nodnic_destroy_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Destroy completion queue.
static struct ib_work_queueflexboot_nodnic_find_wq (struct ib_device *ibdev, struct ib_completion_queue *cq, unsigned long qpn, int is_send)
static int flexboot_nodnic_complete (struct ib_device *ibdev, struct ib_completion_queue *cq, struct cqe_data *cqe_data)
 Handle completion.
static void flexboot_nodnic_poll_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Poll completion queue.
static int flexboot_nodnic_create_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Create queue pair.
static int flexboot_nodnic_modify_qp (struct ib_device *ibdev __attribute__((unused)), struct ib_queue_pair *qp __attribute__((unused)))
 Modify queue pair.
static void flexboot_nodnic_destroy_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Destroy queue pair.
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.
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 void flexboot_nodnic_poll_eq (struct ib_device *ibdev)
static int flexboot_nodnic_mcast_attach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
static void flexboot_nodnic_mcast_detach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
static int flexboot_nodnic_ib_open (struct ib_device *ibdev __attribute__((unused)))
 Initialise Infiniband link.
static void flexboot_nodnic_ib_close (struct ib_device *ibdev __attribute__((unused)))
 Close Infiniband link.
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 flexboot_nodnic_complete_all_tx (struct flexboot_nodnic_port *port)
static void flexboot_nodnic_port_disable_dma (struct flexboot_nodnic_port *port)
static int flexboot_nodnic_eth_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet via flexboot_nodnic Ethernet device.
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.
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.
static void flexboot_nodnic_eth_poll (struct net_device *netdev)
 Poll flexboot_nodnic Ethernet device.
static int flexboot_nodnic_eth_open (struct net_device *netdev)
 Open flexboot_nodnic Ethernet device.
static void flexboot_nodnic_eth_close (struct net_device *netdev)
 Close flexboot_nodnic Ethernet device.
void flexboot_nodnic_eth_irq (struct net_device *netdev, int enable)
static int flexboot_nodnic_register_netdev (struct flexboot_nodnic *flexboot_nodnic, struct flexboot_nodnic_port *port)
 Register flexboot_nodnic Ethernet device.
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.
static void flexboot_nodnic_unregister_netdev (struct flexboot_nodnic *flexboot_nodnic __attribute__((unused)), struct flexboot_nodnic_port *port)
 Unregister flexboot_nodnic Ethernet device.
static mlx_status flexboot_nodnic_allocate_infiniband_devices (struct flexboot_nodnic *flexboot_nodnic_priv)
static mlx_status flexboot_nodnic_thin_init_ports (struct flexboot_nodnic *flexboot_nodnic_priv)
static mlx_status flexboot_nodnic_set_ports_type (struct flexboot_nodnic *flexboot_nodnic_priv)
static mlx_status flexboot_nodnic_ports_register_dev (struct flexboot_nodnic *flexboot_nodnic_priv)
static mlx_status flexboot_nodnic_ports_unregister_dev (struct flexboot_nodnic *flexboot_nodnic_priv)
 __attribute__ ((unused))
int flexboot_nodnic_is_supported (struct pci_device *pci)
void flexboot_nodnic_copy_mac (uint8_t mac_addr[], uint32_t low_byte, uint16_t high_byte)
static mlx_status flexboot_nodnic_get_factory_mac (struct flexboot_nodnic *flexboot_nodnic_priv, uint8_t port __attribute__((unused)))
static int flexboot_nodnic_set_port_masking (struct flexboot_nodnic *flexboot_nodnic)
 Set port masking.
int init_mlx_utils (mlx_utils **utils, struct pci_device *pci)
void free_mlx_utils (mlx_utils **utils)
static int flexboot_nodnic_alloc_uar (struct flexboot_nodnic *flexboot_nodnic)
 Initialise Nodnic PCI parameters.
static int flexboot_nodnic_dealloc_uar (struct flexboot_nodnic *flexboot_nodnic)
int flexboot_nodnic_probe (struct pci_device *pci, struct flexboot_nodnic_callbacks *callbacks, void *drv_priv __attribute__((unused)))
void flexboot_nodnic_remove (struct pci_device *pci)

Variables

static struct ib_device_operations flexboot_nodnic_ib_operations
 flexboot_nodnic Infiniband operations
static struct
ib_queue_pair_operations 
flexboot_nodnic_eth_qp_op
 flexboot nodnic Ethernet queue pair operations
static struct
ib_completion_queue_operations 
flexboot_nodnic_eth_cq_op
 flexboot_nodnic Ethernet device completion operations
static struct net_device_operations flexboot_nodnic_eth_operations
 flexboot_nodnic Ethernet network device operations
static struct
flexboot_nodnic_port_type 
flexboot_nodnic_port_type_eth
 flexboot_nodnic Ethernet port type

Define Documentation

#define ARM_CQ_UAR_CQ_CI_MASK   0xffffff

Referenced by flexboot_nodnic_arm_cq().

#define ARM_CQ_UAR_CMDSN_MASK   3

Referenced by flexboot_nodnic_arm_cq().

#define ARM_CQ_UAR_CMDSN_OFFSET   28

Referenced by flexboot_nodnic_arm_cq().

#define ARM_CQ_UAR_CQ_CI_OFFSET   0x20

Referenced by flexboot_nodnic_arm_cq().

#define FLEX_NODNIC_TX_POLL_TOUT   500000

Definition at line 701 of file flexboot_nodnic.c.

Referenced by flexboot_nodnic_complete_all_tx().

#define FLEX_NODNIC_TX_POLL_USLEEP   10

Definition at line 702 of file flexboot_nodnic.c.

Referenced by flexboot_nodnic_complete_all_tx().

Number of flexboot_nodnic Ethernet send work queue entries.

Definition at line 748 of file flexboot_nodnic.c.

Referenced by flexboot_nodnic_eth_open().

Number of flexboot_nodnic Ethernet receive work queue entries.

Definition at line 751 of file flexboot_nodnic.c.

Referenced by flexboot_nodnic_eth_open().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int flexboot_nodnic_arm_cq ( struct flexboot_nodnic_port port) [static]

Definition at line 55 of file flexboot_nodnic.c.

References _nodnic_port_priv::arm_cq_doorbell_record, ARM_CQ_UAR_CMDSN_MASK, ARM_CQ_UAR_CMDSN_OFFSET, ARM_CQ_UAR_CQ_CI_MASK, ARM_CQ_UAR_CQ_CI_OFFSET, flexboot_nodnic_port::cmdsn, cpu_to_be32, ib_completion_queue::cqn, data, _nodnic_port_priv::device, _nodnic_device_priv::device_cap, arm_cq_uar::dword, _nodnic_arm_cq_db::dword, flexboot_nodnic_port::eth_cq, MLX_DEBUG_ERROR, MLX_FAILED, mlx_pci_mem_write(), MlxPciWidthUint32, ib_completion_queue::next_idx, nodnic_port_option_arm_cq, nodnic_port_set(), flexboot_nodnic_port::port_priv, arm_cq_uar::qword, _nodnic_device_capabilites::support_bar_cq_ctrl, _nodnic_device_priv::uar, _nodnic_device_priv::utils, val, _nodnic_uar_priv::virt, wmb, and writeq().

Referenced by flexboot_nodnic_eth_irq().

                                                                        {
#ifndef DEVICE_CX3
        mlx_uint32 val32 = 0;
        union arm_cq_uar cq_uar;

#define ARM_CQ_UAR_CQ_CI_MASK 0xffffff
#define ARM_CQ_UAR_CMDSN_MASK 3
#define ARM_CQ_UAR_CMDSN_OFFSET 28
#define ARM_CQ_UAR_CQ_CI_OFFSET 0x20
        if ( port->port_priv.device->device_cap.support_bar_cq_ctrl ) {
                cq_uar.dword[0] = cpu_to_be32((port->eth_cq->next_idx  & ARM_CQ_UAR_CQ_CI_MASK) |
                                ((port->cmdsn++ & ARM_CQ_UAR_CMDSN_MASK) << ARM_CQ_UAR_CMDSN_OFFSET));
                cq_uar.dword[1] = cpu_to_be32(port->eth_cq->cqn);
                wmb();
                writeq(cq_uar.qword, port->port_priv.device->uar.virt + ARM_CQ_UAR_CQ_CI_OFFSET);
                port->port_priv.arm_cq_doorbell_record->dword[0] = cq_uar.dword[1];
                port->port_priv.arm_cq_doorbell_record->dword[1] = cq_uar.dword[0];
        } else {
                val32 = ( port->eth_cq->next_idx & 0xffffff );
                if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val32 ) ) {
                        MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" );
                        return MLX_FAILED;
                }
        }
#else
        mlx_utils *utils = port->port_priv.device->utils;
        nodnic_port_data_flow_gw *ptr = port->port_priv.data_flow_gw;
        mlx_uint32 data = 0;
        mlx_uint32 val = 0;

        if ( port->port_priv.device->device_cap.crspace_doorbells == 0 ) {
                val = ( port->eth_cq->next_idx & 0xffff );
                if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val ) ) {
                        MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" );
                        return MLX_FAILED;
                }
        } else {
                /* Arming the CQ with CQ CI should be with this format -
                 * 16 bit - CQ CI - same endianness as the FW (don't swap bytes)
                 * 15 bit - reserved
                 *  1 bit - arm CQ - must correct the endianness with the reserved above */
                data = ( ( ( port->eth_cq->next_idx & 0xffff ) << 16 ) | 0x0080 );
                /* Write the new index and update FW that new data was submitted */
                mlx_pci_mem_write ( utils, MlxPciWidthUint32, 0,
                                ( mlx_uintn ) & ( ptr->armcq_cq_ci_dword ), 1, &data );
        }
#endif
        return 0;
}
static int flexboot_nodnic_create_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
) [static]

Create completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue
Return values:
rcReturn status code

Definition at line 112 of file flexboot_nodnic.c.

References flexboot_nodnic::callbacks, _nodnic_cq::cq_virt, flexboot_nodnic_callbacks::cqe_set_owner, ib_completion_queue::cqn, cqn, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, free, flexboot_nodnic_callbacks::get_cqe_size, ib_cq_set_drvdata(), ib_get_drvdata(), MLX_FATAL_CHECK_STATUS, MLX_OUT_OF_RESOURCES, MLX_SUCCESS, flexboot_nodnic_completion_queue::nodnic_completion_queue, nodnic_port_create_cq(), nodnic_port_option_cq_n_index, nodnic_port_query(), NULL, ib_completion_queue::num_cqes, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, status, _nodnic_device_capabilites::support_bar_cq_ctrl, and zalloc().

                                                               {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq;
        mlx_status status = MLX_SUCCESS;
        mlx_uint32 cqn;

        flexboot_nodnic_cq = (struct flexboot_nodnic_completion_queue *)
                        zalloc(sizeof(*flexboot_nodnic_cq));
        if ( flexboot_nodnic_cq == NULL ) {
                status = MLX_OUT_OF_RESOURCES;
                goto qp_alloc_err;
        }

        status = nodnic_port_create_cq(&port->port_priv,
                        cq->num_cqes *
                        flexboot_nodnic->callbacks->get_cqe_size(),
                        &flexboot_nodnic_cq->nodnic_completion_queue
                        );
        MLX_FATAL_CHECK_STATUS(status, create_err,
                                "nodnic_port_create_cq failed");
        flexboot_nodnic->callbacks->cqe_set_owner(
                        flexboot_nodnic_cq->nodnic_completion_queue->cq_virt,
                        cq->num_cqes);
        if ( flexboot_nodnic->device_priv.device_cap.support_bar_cq_ctrl ) {
                status = nodnic_port_query(&port->port_priv,
                                        nodnic_port_option_cq_n_index,
                                        (mlx_uint32 *)&cqn );
                MLX_FATAL_CHECK_STATUS(status, read_cqn_err,
                                "failed to query cqn");
                cq->cqn = cqn;
        }

        ib_cq_set_drvdata ( cq, flexboot_nodnic_cq );
        return status;
read_cqn_err:
create_err:
        free(flexboot_nodnic_cq);
qp_alloc_err:
        return status;
}
static void flexboot_nodnic_destroy_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
) [static]

Destroy completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 161 of file flexboot_nodnic.c.

References free, ib_cq_get_drvdata(), ib_get_drvdata(), flexboot_nodnic_completion_queue::nodnic_completion_queue, nodnic_port_destroy_cq(), flexboot_nodnic::port, ib_device::port, port, and flexboot_nodnic_port::port_priv.

                                                                 {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq );

        nodnic_port_destroy_cq(&port->port_priv,
                        flexboot_nodnic_cq->nodnic_completion_queue);

        free(flexboot_nodnic_cq);
}
static struct ib_work_queue* flexboot_nodnic_find_wq ( struct ib_device ibdev,
struct ib_completion_queue cq,
unsigned long  qpn,
int  is_send 
) [static, read]

Definition at line 174 of file flexboot_nodnic.c.

References FALSE, ib_get_drvdata(), ib_qp_get_drvdata(), ib_work_queue::is_send, list_for_each_entry, nodnic_port_get_qpn(), flexboot_nodnic_queue_pair::nodnic_queue_pair, nodnic_send_ring::nodnic_ring, nodnic_recv_ring::nodnic_ring, NULL, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, ib_work_queue::qp, _nodnic_qp::receive, _nodnic_qp::send, TRUE, and ib_completion_queue::work_queues.

Referenced by flexboot_nodnic_complete().

                                                                                         {
        struct ib_work_queue *wq;
        struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp;
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct nodnic_ring  *ring;
        mlx_uint32 out_qpn;
        list_for_each_entry ( wq, &cq->work_queues, list ) {
                flexboot_nodnic_qp = ib_qp_get_drvdata ( wq->qp );
                if( wq->is_send == is_send && wq->is_send == TRUE ) {
                        ring = &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring;
                } else if( wq->is_send == is_send && wq->is_send == FALSE ) {
                        ring = &flexboot_nodnic_qp->nodnic_queue_pair->receive.nodnic_ring;
                } else {
                        continue;
                }
                nodnic_port_get_qpn(&port->port_priv, ring, &out_qpn);
                if ( out_qpn == qpn )
                        return wq;
        }
        return NULL;
}
static int flexboot_nodnic_complete ( struct ib_device ibdev,
struct ib_completion_queue cq,
struct cqe_data cqe_data 
) [static]

Handle completion.

Parameters:
ibdevInfiniband device
cqCompletion queue
cqeHardware completion queue entry
Return values:
rcReturn status code

Definition at line 207 of file flexboot_nodnic.c.

References assert, cqe_data::byte_cnt, ib_completion_queue::cqn, DBGC, DBGCP, EINVAL, EIO, flexboot_nodnic_find_wq(), ib_complete_recv(), ib_complete_send(), ib_get_drvdata(), IB_QPT_ETH, IB_QPT_GSI, IB_QPT_RC, IB_QPT_SMI, IB_QPT_UD, iob_put, iob_tailroom(), ib_work_queue::iobufs, cqe_data::is_error, cqe_data::is_send, len, memset(), NULL, ib_work_queue::num_wqes, ib_work_queue::qp, qp, ib_address_vector::qpn, cqe_data::qpn, ib_queue_pair::qpn, qpn, rc, cqe_data::syndrome, TRUE, ib_queue_pair::type, cqe_data::vendor_err_syndrome, and cqe_data::wqe_counter.

Referenced by flexboot_nodnic_poll_cq().

                                                             {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq;
        struct ib_queue_pair *qp;
        struct io_buffer *iobuf;
        struct ib_address_vector recv_dest;
        struct ib_address_vector recv_source;
        unsigned long qpn;
        unsigned long wqe_idx;
        unsigned long wqe_idx_mask;
        size_t len;
        int rc = 0;

        /* Parse completion */
        qpn = cqe_data->qpn;

        if ( cqe_data->is_error == TRUE ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx syndrome %x vendor %x\n",
                                flexboot_nodnic, cq->cqn, cqe_data->syndrome,
                                cqe_data->vendor_err_syndrome );
                rc = -EIO;
                /* Don't return immediately; propagate error to completer */
        }

        /* Identify work queue */
        wq = flexboot_nodnic_find_wq( ibdev, cq, qpn, cqe_data->is_send );
        if ( wq == NULL ) {
                DBGC ( flexboot_nodnic,
                                "flexboot_nodnic %p CQN %#lx unknown %s QPN %#lx\n",
                                flexboot_nodnic, cq->cqn,
                                ( cqe_data->is_send ? "send" : "recv" ), qpn );
                return -EIO;
        }
        qp = wq->qp;

        /* Identify work queue entry */
        wqe_idx = cqe_data->wqe_counter;
        wqe_idx_mask = ( wq->num_wqes - 1 );
        DBGCP ( flexboot_nodnic,
                        "NODNIC %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n",
                        flexboot_nodnic, cq->cqn, qp->qpn,
                        ( cqe_data->is_send ? "send" : "recv" ),
                wqe_idx );

        /* Identify I/O buffer */
        iobuf = wq->iobufs[wqe_idx & wqe_idx_mask];
        if ( iobuf == NULL ) {
                DBGC ( flexboot_nodnic,
                                "NODNIC %p CQN %#lx QPN %#lx empty %s WQE %#lx\n",
                                flexboot_nodnic, cq->cqn, qp->qpn,
                       ( cqe_data->is_send ? "send" : "recv" ), wqe_idx );
                return -EIO;
        }
        wq->iobufs[wqe_idx & wqe_idx_mask] = NULL;

        if ( cqe_data->is_send == TRUE ) {
                /* Hand off to completion handler */
                ib_complete_send ( ibdev, qp, iobuf, rc );
        } else if ( rc != 0 ) {
                /* Propagate error to receive completion handler */
                ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf, rc );
        } else {
                /* Set received length */
                len = cqe_data->byte_cnt;
                assert ( len <= iob_tailroom ( iobuf ) );
                iob_put ( iobuf, len );
                memset ( &recv_dest, 0, sizeof ( recv_dest ) );
                recv_dest.qpn = qpn;
                memset ( &recv_source, 0, sizeof ( recv_source ) );
                switch ( qp->type ) {
                case IB_QPT_SMI:
                case IB_QPT_GSI:
                case IB_QPT_UD:
                case IB_QPT_RC:
                        break;
                case IB_QPT_ETH:
                        break;
                default:
                        assert ( 0 );
                        return -EINVAL;
                }
                /* Hand off to completion handler */
                ib_complete_recv ( ibdev, qp, &recv_dest,
                                &recv_source, iobuf, rc );
        }

        return rc;
}
static void flexboot_nodnic_poll_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
) [static]

Poll completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queues

Definition at line 303 of file flexboot_nodnic.c.

References flexboot_nodnic::callbacks, _nodnic_cq::cq_virt, ib_completion_queue::cqn, DBGC, DBGC_HDA, flexboot_nodnic_callbacks::fill_completion, flexboot_nodnic_complete(), flexboot_nodnic_callbacks::get_cqe_size, ib_cq_get_drvdata(), ib_get_drvdata(), ib_completion_queue::next_idx, flexboot_nodnic_completion_queue::nodnic_completion_queue, ib_completion_queue::num_cqes, cqe_data::owner, rc, strerror(), TRUE, and virt_to_phys().

                                                             {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq );
        void *cqe;
        mlx_size cqe_size;
        struct cqe_data cqe_data;
        unsigned int cqe_idx_mask;
        int rc;

        cqe_size = flexboot_nodnic->callbacks->get_cqe_size();
        while ( TRUE ) {
                /* Look for completion entry */
                cqe_idx_mask = ( cq->num_cqes - 1 );
                cqe = ((uint8_t *)flexboot_nodnic_cq->nodnic_completion_queue->cq_virt) +
                                cqe_size * (cq->next_idx & cqe_idx_mask);

                /* TODO: check fill_completion */
                flexboot_nodnic->callbacks->fill_completion(cqe, &cqe_data);
                if ( cqe_data.owner ^
                                ( ( cq->next_idx & cq->num_cqes ) ? 1 : 0 ) ) {
                        /* Entry still owned by hardware; end of poll */
                        break;
                }
                /* Handle completion */
                rc = flexboot_nodnic_complete ( ibdev, cq, &cqe_data );
                if ( rc != 0 ) {
                        DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx failed to complete: %s\n",
                                        flexboot_nodnic, cq->cqn, strerror ( rc ) );
                        DBGC_HDA ( flexboot_nodnic, virt_to_phys ( cqe ),
                                   cqe, sizeof ( *cqe ) );
                }

                /* Update completion queue's index */
                cq->next_idx++;
        }
}
static int flexboot_nodnic_create_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Create queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair
Return values:
rcReturn status code

Definition at line 355 of file flexboot_nodnic.c.

References free, ib_get_drvdata(), ib_qp_set_drvdata(), MLX_FATAL_CHECK_STATUS, MLX_OUT_OF_RESOURCES, MLX_SUCCESS, nodnic_port_create_qp(), flexboot_nodnic_queue_pair::nodnic_queue_pair, NULL, ib_work_queue::num_wqes, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, ib_queue_pair::recv, ib_queue_pair::send, status, ib_queue_pair::type, and zalloc().

                                                         {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp;
        mlx_status status = MLX_SUCCESS;

        flexboot_nodnic_qp = (struct flexboot_nodnic_queue_pair *)zalloc(sizeof(*flexboot_nodnic_qp));
        if ( flexboot_nodnic_qp == NULL ) {
                status = MLX_OUT_OF_RESOURCES;
                goto qp_alloc_err;
        }

        status = nodnic_port_create_qp(&port->port_priv, qp->type,
                        qp->send.num_wqes * sizeof(struct nodnic_send_wqbb),
                        qp->send.num_wqes,
                        qp->recv.num_wqes * sizeof(struct nodnic_recv_wqe),
                        qp->recv.num_wqes,
                        &flexboot_nodnic_qp->nodnic_queue_pair);
        MLX_FATAL_CHECK_STATUS(status, create_err,
                        "nodnic_port_create_qp failed");
        ib_qp_set_drvdata ( qp, flexboot_nodnic_qp );
        return status;
create_err:
        free(flexboot_nodnic_qp);
qp_alloc_err:
        return status;
}
static int flexboot_nodnic_modify_qp ( struct ib_device *ibdev   __attribute__(unused),
struct ib_queue_pair *qp   __attribute__(unused) 
) [static]

Modify queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair
Return values:
rcReturn status code

Definition at line 391 of file flexboot_nodnic.c.

                                                                 {
        /*not needed*/
        return 0;
}
static void flexboot_nodnic_destroy_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Destroy queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 403 of file flexboot_nodnic.c.

References free, ib_get_drvdata(), ib_qp_get_drvdata(), nodnic_port_destroy_qp(), flexboot_nodnic_queue_pair::nodnic_queue_pair, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, and ib_queue_pair::type.

                                                           {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );

        nodnic_port_destroy_qp(&port->port_priv, qp->type,
                        flexboot_nodnic_qp->nodnic_queue_pair);

        free(flexboot_nodnic_qp);
}
static int flexboot_nodnic_post_send ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_address_vector av,
struct io_buffer iobuf 
) [static]

Post send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
avAddress vector
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 431 of file flexboot_nodnic.c.

References assert, flexboot_nodnic::callbacks, DBGC, _nodnic_port_priv::dma_state, ENETDOWN, ENOBUFS, FALSE, ib_get_drvdata(), ib_qp_get_drvdata(), ib_work_queue::iobufs, MLX_SUCCESS, ib_work_queue::next_idx, NODNIC_PORT_DISABLING_DMA, flexboot_nodnic_queue_pair::nodnic_queue_pair, nodnic_send_ring::nodnic_ring, NULL, ib_work_queue::num_wqes, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, _nodnic_port_priv::port_state, qp, ib_queue_pair::qpn, _nodnic_qp::send, ib_queue_pair::send, _nodnic_port_priv::send_doorbell, status, flexboot_nodnic_callbacks::tx_uar_send_doorbell_fn, ib_queue_pair::type, and nodnic_send_ring::wqe_virt.

                                                       {

        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct ib_work_queue *wq = &qp->send;
        struct nodnic_send_wqbb *wqbb;
        nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair;
        struct nodnic_send_ring *send_ring = &nodnic_qp->send;
        mlx_status status = MLX_SUCCESS;
        unsigned int wqe_idx_mask;
        unsigned long wqe_idx;

        if ( ( port->port_priv.dma_state == FALSE ) ||
                 ( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic DMA disabled\n");
                status = -ENETDOWN;
                goto post_send_done;
        }

        /* Allocate work queue entry */
        wqe_idx = wq->next_idx;
        wqe_idx_mask = ( wq->num_wqes - 1 );
        if ( wq->iobufs[wqe_idx & wqe_idx_mask] ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx send queue full\n",
                                flexboot_nodnic, qp->qpn );
                status = -ENOBUFS;
                goto post_send_done;
        }
        wqbb = &send_ring->wqe_virt[wqe_idx & wqe_idx_mask];
        wq->iobufs[wqe_idx & wqe_idx_mask] = iobuf;

        assert ( flexboot_nodnic->callbacks->
                        fill_send_wqe[qp->type] != NULL );
        status = flexboot_nodnic->callbacks->
                        fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf,
                                        wqbb, wqe_idx );
        if ( status != 0 ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx fill send wqe failed\n",
                                flexboot_nodnic, qp->qpn );
                goto post_send_done;
        }

        wq->next_idx++;

        status = port->port_priv.send_doorbell ( &port->port_priv,
                                &send_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx );
        if ( flexboot_nodnic->callbacks->tx_uar_send_doorbell_fn ) {
                flexboot_nodnic->callbacks->tx_uar_send_doorbell_fn ( ibdev, wqbb );
        }
        if ( status != 0 ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring send doorbell failed\n", flexboot_nodnic );
        }

post_send_done:
        return status;
}
static int flexboot_nodnic_post_recv ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct io_buffer iobuf 
) [static]

Post receive work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 500 of file flexboot_nodnic.c.

References byte_count, io_buffer::data, DBGC, flexboot_nodnic::device_priv, ENOBUFS, ib_get_drvdata(), ib_qp_get_drvdata(), iob_tailroom(), ib_work_queue::iobufs, _nodnic_device_priv::lkey, MLX_FILL_1, MLX_FILL_H, MLX_SUCCESS, ib_work_queue::next_idx, flexboot_nodnic_queue_pair::nodnic_queue_pair, nodnic_recv_ring::nodnic_ring, ib_work_queue::num_wqes, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, ib_queue_pair::qpn, _nodnic_qp::receive, ib_queue_pair::recv, _nodnic_port_priv::recv_doorbell, status, virt_to_bus(), and nodnic_recv_ring::wqe_virt.

                                                        {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        struct ib_work_queue *wq = &qp->recv;
        nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair;
        struct nodnic_recv_ring *recv_ring = &nodnic_qp->receive;
        struct nodnic_recv_wqe *wqe;
        unsigned int wqe_idx_mask;
        mlx_status status = MLX_SUCCESS;

        /* Allocate work queue entry */
        wqe_idx_mask = ( wq->num_wqes - 1 );
        if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
                DBGC ( flexboot_nodnic,
                                "flexboot_nodnic %p QPN %#lx receive queue full\n",
                                flexboot_nodnic, qp->qpn );
                status = -ENOBUFS;
                goto post_recv_done;
        }
        wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
        wqe = &((struct nodnic_recv_wqe*)recv_ring->wqe_virt)[wq->next_idx & wqe_idx_mask];

        MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
        MLX_FILL_1 ( &wqe->data[0], 1, l_key, flexboot_nodnic->device_priv.lkey );
        MLX_FILL_H ( &wqe->data[0], 2,
                         local_address_h, virt_to_bus ( iobuf->data ) );
        MLX_FILL_1 ( &wqe->data[0], 3,
                         local_address_l, virt_to_bus ( iobuf->data ) );

        wq->next_idx++;

        status = port->port_priv.recv_doorbell ( &port->port_priv,
                                &recv_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx );
        if ( status != 0 ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring receive doorbell failed\n", flexboot_nodnic );
        }
post_recv_done:
        return status;
}
static void flexboot_nodnic_poll_eq ( struct ib_device ibdev) [static]

Definition at line 550 of file flexboot_nodnic.c.

References DBG, DBG2, ib_get_drvdata(), flexboot_nodnic_port::ibdev, MLX_FATAL_CHECK_STATUS, netdev, flexboot_nodnic_port::netdev, netdev_is_open(), netdev_link_ok(), nodnic_port_get_state(), nodnic_port_state_active, flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, state, flexboot_nodnic_port_type::state_change, status, and flexboot_nodnic_port::type.

                                                                {
        struct flexboot_nodnic *flexboot_nodnic;
        struct flexboot_nodnic_port *port;
        struct net_device *netdev;
        nodnic_port_state state = 0;
        mlx_status status;

        if ( ! ibdev ) {
                DBG ( "%s: ibdev = NULL!!!\n", __FUNCTION__ );
                return;
        }

        flexboot_nodnic = ib_get_drvdata ( ibdev );
        port = &flexboot_nodnic->port[ibdev->port - 1];
        netdev = port->netdev;

        if ( ! netdev_is_open ( netdev ) ) {
                DBG2( "%s: port %d is closed\n", __FUNCTION__, port->ibdev->port );
                return;
        }

        /* we don't poll EQ. Just poll link status if it's not active */
        if ( ! netdev_link_ok ( netdev ) ) {
                status = nodnic_port_get_state ( &port->port_priv, &state );
                MLX_FATAL_CHECK_STATUS(status, state_err, "nodnic_port_get_state failed");

                if ( state == nodnic_port_state_active ) {
                        DBG( "%s: port %d physical link is up\n", __FUNCTION__,
                                        port->ibdev->port );
                        port->type->state_change ( flexboot_nodnic, port, 1 );
                }
        }
state_err:
        return;
}
static int flexboot_nodnic_mcast_attach ( struct ib_device ibdev,
struct ib_queue_pair qp,
union ib_gid gid 
) [static]

Definition at line 592 of file flexboot_nodnic.c.

References flexboot_nodnic::device_priv, ib_get_drvdata(), IB_QPT_ETH, mac, memcpy(), MLX_CHECK_STATUS, MLX_SUCCESS, nodnic_port_add_mac_filter(), flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, status, and ib_queue_pair::type.

                                                    {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        mlx_mac_address mac;
        mlx_status status = MLX_SUCCESS;

        switch (qp->type) {
        case IB_QPT_ETH:
                memcpy(&mac, &gid, sizeof(mac));
                status = nodnic_port_add_mac_filter(&port->port_priv, mac);
                MLX_CHECK_STATUS(flexboot_nodnic->device_priv, status, mac_err,
                                "nodnic_port_add_mac_filter failed");
                break;
        default:
                break;
        }
mac_err:
        return status;
}
static void flexboot_nodnic_mcast_detach ( struct ib_device ibdev,
struct ib_queue_pair qp,
union ib_gid gid 
) [static]

Definition at line 613 of file flexboot_nodnic.c.

References flexboot_nodnic::device_priv, ib_get_drvdata(), IB_QPT_ETH, mac, memcpy(), MLX_CHECK_STATUS, MLX_SUCCESS, nodnic_port_remove_mac_filter(), flexboot_nodnic::port, ib_device::port, port, flexboot_nodnic_port::port_priv, status, and ib_queue_pair::type.

                                                      {
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1];
        mlx_mac_address mac;
        mlx_status status = MLX_SUCCESS;

        switch (qp->type) {
        case IB_QPT_ETH:
                memcpy(&mac, &gid, sizeof(mac));
                status = nodnic_port_remove_mac_filter(&port->port_priv, mac);
                MLX_CHECK_STATUS(flexboot_nodnic->device_priv, status, mac_err,
                                "nodnic_port_remove_mac_filter failed");
                break;
        default:
                break;
        }
mac_err:
        return;
}
static int flexboot_nodnic_ib_open ( struct ib_device *ibdev   __attribute__(unused)) [static]

Initialise Infiniband link.

Parameters:
ibdevInfiniband device
Return values:
rcReturn status code

Definition at line 647 of file flexboot_nodnic.c.

References rc.

                                                                       {
        int rc = 0;

        /*TODO: add implementation*/
        return rc;
}
static void flexboot_nodnic_ib_close ( struct ib_device *ibdev   __attribute__(unused)) [static]

Close Infiniband link.

Parameters:
ibdevInfiniband device

Definition at line 659 of file flexboot_nodnic.c.

                                                                         {
        /*TODO: add implementation*/
}
static int flexboot_nodnic_inform_sma ( struct ib_device *ibdev   __attribute__(unused),
union ib_mad *mad   __attribute__(unused) 
) [static]

Inform embedded subnet management agent of a received MAD.

Parameters:
ibdevInfiniband device
madMAD
Return values:
rcReturn status code

Definition at line 670 of file flexboot_nodnic.c.

                                                           {
        /*TODO: add implementation*/
        return 0;
}
static void flexboot_nodnic_complete_all_tx ( struct flexboot_nodnic_port port) [static]

Definition at line 704 of file flexboot_nodnic.c.

References ib_device::cqs, ib_work_queue::fill, FLEX_NODNIC_TX_POLL_TOUT, FLEX_NODNIC_TX_POLL_USLEEP, ib_poll_cq(), flexboot_nodnic_port::ibdev, ib_work_queue::is_send, ib_work_queue::list, list_for_each_entry, timeout(), udelay(), and ib_completion_queue::work_queues.

Referenced by flexboot_nodnic_port_disable_dma().

                                                                                  {
        struct ib_device *ibdev = port->ibdev;
        struct ib_completion_queue *cq;
        struct ib_work_queue *wq;
        int keep_polling = 0;
        int timeout = FLEX_NODNIC_TX_POLL_TOUT;

        list_for_each_entry ( cq, &ibdev->cqs, list ) {
                do {
                        ib_poll_cq ( ibdev, cq );
                        keep_polling = 0;
                        list_for_each_entry ( wq, &cq->work_queues, list ) {
                                if ( wq->is_send )
                                        keep_polling += ( wq->fill > 0 );
                        }
                        udelay ( FLEX_NODNIC_TX_POLL_USLEEP );
                } while ( keep_polling && ( timeout-- > 0 ) );
        }
}
static void flexboot_nodnic_port_disable_dma ( struct flexboot_nodnic_port port) [static]
static int flexboot_nodnic_eth_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet via flexboot_nodnic Ethernet device.

Parameters:
netdevNetwork device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 764 of file flexboot_nodnic.c.

References DBGC, flexboot_nodnic_port::eth_qp, ib_get_drvdata(), ib_post_send(), flexboot_nodnic_port::ibdev, NULL, ib_device::port, port, net_device::priv, rc, and strerror().

                                                          {
        struct flexboot_nodnic_port *port = netdev->priv;
        struct ib_device *ibdev = port->ibdev;
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        int rc;

        rc = ib_post_send ( ibdev, port->eth_qp, NULL, iobuf);
        /* Transmit packet */
        if ( rc != 0) {
                DBGC ( flexboot_nodnic, "NODNIC %p port %d could not transmit: %s\n",
                                flexboot_nodnic, ibdev->port, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void flexboot_nodnic_eth_complete_send ( struct ib_device *ibdev   __attribute__(unused),
struct ib_queue_pair qp,
struct io_buffer iobuf,
int  rc 
) [static]

Handle flexboot_nodnic Ethernet device send completion.

Parameters:
ibdevInfiniband device
qpQueue pair
iobufI/O buffer
rcCompletion status code

Definition at line 790 of file flexboot_nodnic.c.

References ib_qp_get_ownerdata(), netdev, and netdev_tx_complete_err().

                                                   {
        struct net_device *netdev = ib_qp_get_ownerdata ( qp );

        netdev_tx_complete_err ( netdev, iobuf, rc );
}
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 
) [static]

Handle flexboot_nodnic Ethernet device receive completion.

Parameters:
ibdevInfiniband device
qpQueue pair
avAddress vector, or NULL
iobufI/O buffer
rcCompletion status code

Definition at line 808 of file flexboot_nodnic.c.

References DBG, ENOTTY, ib_qp_get_ownerdata(), netdev, netdev_rx(), netdev_rx_err(), and NULL.

                                        {
        struct net_device *netdev = ib_qp_get_ownerdata ( qp );

        if ( rc != 0 ) {
                DBG ( "Received packet with error\n" );
                netdev_rx_err ( netdev, iobuf, rc );
                return;
        }

        if ( source == NULL ) {
                DBG ( "Received packet without address vector\n" );
                netdev_rx_err ( netdev, iobuf, -ENOTTY );
                return;
        }

        netdev_rx ( netdev, iobuf );
}
static void flexboot_nodnic_eth_poll ( struct net_device netdev) [static]

Poll flexboot_nodnic Ethernet device.

Parameters:
netdevNetwork device

Definition at line 842 of file flexboot_nodnic.c.

References ib_poll_eq(), flexboot_nodnic_port::ibdev, port, and net_device::priv.

                                                                  {
        struct flexboot_nodnic_port *port = netdev->priv;
        struct ib_device *ibdev = port->ibdev;

        ib_poll_eq ( ibdev );
}
static int flexboot_nodnic_eth_open ( struct net_device netdev) [static]

Open flexboot_nodnic Ethernet device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 855 of file flexboot_nodnic.c.

References flexboot_nodnic_port::cmdsn, ib_work_queue::cq, DBGC, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, flexboot_nodnic_port::eth_cq, flexboot_nodnic_port::eth_qp, FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES, FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES, free, ib_create_cq(), ib_create_qp(), ib_destroy_qp(), ib_get_drvdata(), ib_qp_get_drvdata(), ib_qp_set_ownerdata(), IB_QPT_ETH, ib_refill_recv(), flexboot_nodnic_port::ibdev, INIT_LIST_HEAD, ib_work_queue::list, list_add, list_del, _nodnic_device_capabilites::log_working_buffer_size, MLX_FATAL_CHECK_STATUS, MLX_OUT_OF_RESOURCES, MLX_SUCCESS, net_device::name, nodnic_port_allocate_eq(), nodnic_port_close(), nodnic_port_enable_dma(), nodnic_port_free_eq(), nodnic_port_get_cq_size(), nodnic_port_get_qpn(), nodnic_port_get_state(), nodnic_port_init(), NODNIC_PORT_OPENED, nodnic_port_set_promisc(), nodnic_port_state_active, nodnic_port_state_down, flexboot_nodnic_queue_pair::nodnic_queue_pair, nodnic_send_ring::nodnic_ring, NULL, ib_device::port, port, flexboot_nodnic_port::port_priv, _nodnic_port_priv::port_state, net_device::priv, ib_queue_pair::qpn, qpn, rc, ib_queue_pair::recv, _nodnic_qp::send, ib_queue_pair::send, state, flexboot_nodnic_port_type::state_change, status, _nodnic_device_capabilites::support_promisc_filter, TRUE, flexboot_nodnic_port::type, ib_completion_queue::work_queues, and zalloc().

                                                                  {
        struct flexboot_nodnic_port *port = netdev->priv;
        struct ib_device *ibdev = port->ibdev;
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        mlx_status status = MLX_SUCCESS;
        struct ib_completion_queue *dummy_cq = NULL;
        struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = NULL;
        mlx_uint64      cq_size = 0;
        mlx_uint32      qpn = 0;
        nodnic_port_state state = nodnic_port_state_down;
        int rc;

        if ( port->port_priv.port_state & NODNIC_PORT_OPENED ) {
                DBGC ( flexboot_nodnic, "%s: port %d is already opened\n",
                                __FUNCTION__, port->ibdev->port );
                return 0;
        }

        port->port_priv.port_state |= NODNIC_PORT_OPENED;

        dummy_cq = zalloc ( sizeof ( struct ib_completion_queue ) );
        if ( dummy_cq == NULL ) {
                DBGC ( flexboot_nodnic, "%s: Failed to allocate dummy CQ\n", __FUNCTION__ );
                status = MLX_OUT_OF_RESOURCES;
                goto err_create_dummy_cq;
        }
        INIT_LIST_HEAD ( &dummy_cq->work_queues );

        if ( ( rc = ib_create_qp ( ibdev, IB_QPT_ETH,
                                   FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES, dummy_cq,
                                   FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES, dummy_cq,
                                   &flexboot_nodnic_eth_qp_op, netdev->name,
                                   &port->eth_qp ) ) != 0 ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not create queue pair\n",
                                 flexboot_nodnic, ibdev->port );
                status = MLX_OUT_OF_RESOURCES;
                goto err_create_qp;
        }

        ib_qp_set_ownerdata ( port->eth_qp, netdev );

        status = nodnic_port_get_cq_size(&port->port_priv, &cq_size);
        MLX_FATAL_CHECK_STATUS(status, get_cq_size_err,
                        "nodnic_port_get_cq_size failed");

        if ( ( rc = ib_create_cq ( ibdev, cq_size, &flexboot_nodnic_eth_cq_op,
                                   &port->eth_cq ) ) != 0 ) {
                DBGC ( flexboot_nodnic,
                        "flexboot_nodnic %p port %d could not create completion queue\n",
                        flexboot_nodnic, ibdev->port );
                status = MLX_OUT_OF_RESOURCES;
                goto err_create_cq;
        }
        port->eth_qp->send.cq = port->eth_cq;
        list_del(&port->eth_qp->send.list);
        list_add ( &port->eth_qp->send.list, &port->eth_cq->work_queues );
        port->eth_qp->recv.cq = port->eth_cq;
        port->cmdsn = 0;
        list_del(&port->eth_qp->recv.list);
        list_add ( &port->eth_qp->recv.list, &port->eth_cq->work_queues );

        status = nodnic_port_allocate_eq(&port->port_priv,
                flexboot_nodnic->device_priv.device_cap.log_working_buffer_size);
        MLX_FATAL_CHECK_STATUS(status, eq_alloc_err,
                                "nodnic_port_allocate_eq failed");

        status = nodnic_port_init(&port->port_priv);
        MLX_FATAL_CHECK_STATUS(status, init_err,
                                        "nodnic_port_init failed");

        /* update qp - qpn */
        flexboot_nodnic_qp = ib_qp_get_drvdata ( port->eth_qp );
        status = nodnic_port_get_qpn(&port->port_priv,
                        &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring,
                        &qpn);
        MLX_FATAL_CHECK_STATUS(status, qpn_err,
                                                "nodnic_port_get_qpn failed");
        port->eth_qp->qpn = qpn;

        /* Fill receive rings */
        ib_refill_recv ( ibdev, port->eth_qp );

        status = nodnic_port_enable_dma(&port->port_priv);
        MLX_FATAL_CHECK_STATUS(status, dma_err,
                                        "nodnic_port_enable_dma failed");

        if (flexboot_nodnic->device_priv.device_cap.support_promisc_filter) {
                status = nodnic_port_set_promisc(&port->port_priv, TRUE);
                MLX_FATAL_CHECK_STATUS(status, promisc_err,
                                                        "nodnic_port_set_promisc failed");
        }

        status = nodnic_port_get_state(&port->port_priv, &state);
        MLX_FATAL_CHECK_STATUS(status, state_err,
                                                "nodnic_port_get_state failed");

        port->type->state_change (
                        flexboot_nodnic, port, state == nodnic_port_state_active );

        DBGC ( flexboot_nodnic, "%s: port %d opened (link is %s)\n",
                        __FUNCTION__, port->ibdev->port,
                        ( ( state == nodnic_port_state_active ) ? "Up" : "Down" ) );

        free(dummy_cq);
        return 0;
state_err:
promisc_err:
dma_err:
qpn_err:
        nodnic_port_close(&port->port_priv);
init_err:
        nodnic_port_free_eq(&port->port_priv);
eq_alloc_err:
err_create_cq:
get_cq_size_err:
        ib_destroy_qp(ibdev, port->eth_qp );
err_create_qp:
        free(dummy_cq);
err_create_dummy_cq:
        port->port_priv.port_state &= ~NODNIC_PORT_OPENED;
        return status;
}
static void flexboot_nodnic_eth_close ( struct net_device netdev) [static]

Close flexboot_nodnic Ethernet device.

Parameters:
netdevNetwork device

Definition at line 983 of file flexboot_nodnic.c.

References DBGC, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, flexboot_nodnic_port::eth_cq, flexboot_nodnic_port::eth_qp, FALSE, flexboot_nodnic_port_disable_dma(), ib_destroy_cq(), ib_destroy_qp(), ib_get_drvdata(), flexboot_nodnic_port::ibdev, MLX_SUCCESS, nodnic_port_close(), nodnic_port_free_eq(), NODNIC_PORT_OPENED, nodnic_port_set_promisc(), NULL, ib_device::port, port, flexboot_nodnic_port::port_priv, _nodnic_port_priv::port_state, net_device::priv, flexboot_nodnic_port_type::state_change, status, strerror(), _nodnic_device_capabilites::support_promisc_filter, and flexboot_nodnic_port::type.

                                                                   {
        struct flexboot_nodnic_port *port = netdev->priv;
        struct ib_device *ibdev = port->ibdev;
        struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev );
        mlx_status status = MLX_SUCCESS;

        if ( ! ( port->port_priv.port_state & NODNIC_PORT_OPENED ) ) {
                DBGC ( flexboot_nodnic, "%s: port %d is already closed\n",
                                __FUNCTION__, port->ibdev->port );
                return;
        }

        if (flexboot_nodnic->device_priv.device_cap.support_promisc_filter) {
                if ( ( status = nodnic_port_set_promisc( &port->port_priv, FALSE ) ) ) {
                        DBGC ( flexboot_nodnic,
                                        "nodnic_port_set_promisc failed (status = %d)\n", status );
                }
        }

        flexboot_nodnic_port_disable_dma ( port );

        port->port_priv.port_state &= ~NODNIC_PORT_OPENED;

        port->type->state_change ( flexboot_nodnic, port, FALSE );

        /* Close port */
        status = nodnic_port_close(&port->port_priv);
        if ( status != MLX_SUCCESS ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not close port: %s\n",
                                flexboot_nodnic, ibdev->port, strerror ( status ) );
                /* Nothing we can do about this */
        }

        ib_destroy_qp ( ibdev, port->eth_qp );
        port->eth_qp = NULL;
        ib_destroy_cq ( ibdev, port->eth_cq );
        port->eth_cq = NULL;

        nodnic_port_free_eq(&port->port_priv);

        DBGC ( flexboot_nodnic, "%s: port %d closed\n", __FUNCTION__, port->ibdev->port );
}
void flexboot_nodnic_eth_irq ( struct net_device netdev,
int  enable 
)
static int flexboot_nodnic_register_netdev ( struct flexboot_nodnic flexboot_nodnic,
struct flexboot_nodnic_port port 
) [static]

Register flexboot_nodnic Ethernet device.

Definition at line 1052 of file flexboot_nodnic.c.

References alloc_etherdev(), bytes, DBGC, net_device::dev, ib_device::dev, ETH_ALEN, htonl, net_device::hw_addr, flexboot_nodnic_port::ibdev, mac, memcpy(), MLX_FATAL_CHECK_STATUS, MLX_OUT_OF_RESOURCES, MLX_SUCCESS, netdev, flexboot_nodnic_port::netdev, netdev_init(), netdev_put(), nodnic_port_option_mac_high, nodnic_port_option_mac_low, nodnic_port_query(), NULL, ib_device::port, port, flexboot_nodnic_port::port_priv, net_device::priv, register_netdev(), status, and strerror().

                                                                       {
        mlx_status status = MLX_SUCCESS;
        struct net_device       *netdev;
        struct ib_device        *ibdev = port->ibdev;
        union {
                uint8_t bytes[8];
                uint32_t dwords[2];
        } mac;

        /* Allocate network devices */
        netdev = alloc_etherdev ( 0 );
        if ( netdev == NULL ) {
                DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not allocate net device\n",
                                flexboot_nodnic, ibdev->port );
                status = MLX_OUT_OF_RESOURCES;
                goto alloc_err;
        }
        port->netdev = netdev;
        netdev_init ( netdev, &flexboot_nodnic_eth_operations );
        netdev->dev = ibdev->dev;
        netdev->priv = port;

        status = nodnic_port_query(&port->port_priv,
                        nodnic_port_option_mac_high,
                        &mac.dwords[0]);
        MLX_FATAL_CHECK_STATUS(status, mac_err,
                        "failed to query mac high");
        status = nodnic_port_query(&port->port_priv,
                        nodnic_port_option_mac_low,
                        &mac.dwords[1]);
        MLX_FATAL_CHECK_STATUS(status, mac_err,
                                "failed to query mac low");
        mac.dwords[0] = htonl(mac.dwords[0]);
        mac.dwords[1] = htonl(mac.dwords[1]);
        memcpy ( netdev->hw_addr,
                         &mac.bytes[2], ETH_ALEN);
        /* Register network device */
        status = register_netdev ( netdev );
        if ( status != MLX_SUCCESS ) {
                DBGC ( flexboot_nodnic,
                        "flexboot_nodnic %p port %d could not register network device: %s\n",
                        flexboot_nodnic, ibdev->port, strerror ( status ) );
                goto reg_err;
        }
        return status;
reg_err:
mac_err:
        netdev_put ( netdev );
alloc_err:
        return status;
}
static void flexboot_nodnic_state_change_netdev ( struct flexboot_nodnic *flexboot_nodnic   __attribute__(unused),
struct flexboot_nodnic_port port,
int  link_up 
) [static]

Handle flexboot_nodnic Ethernet device port state change.

Definition at line 1108 of file flexboot_nodnic.c.

References netdev, flexboot_nodnic_port::netdev, netdev_link_down(), and netdev_link_up().

                                                       {
        struct net_device *netdev = port->netdev;

        if ( link_up )
                netdev_link_up ( netdev );
        else
                netdev_link_down ( netdev );

}
static void flexboot_nodnic_unregister_netdev ( struct flexboot_nodnic *flexboot_nodnic   __attribute__(unused),
struct flexboot_nodnic_port port 
) [static]

Unregister flexboot_nodnic Ethernet device.

Definition at line 1123 of file flexboot_nodnic.c.

References netdev, flexboot_nodnic_port::netdev, netdev_nullify(), netdev_put(), and unregister_netdev().

                                                                           {
        struct net_device *netdev = port->netdev;
        unregister_netdev ( netdev );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
}
static mlx_status flexboot_nodnic_allocate_infiniband_devices ( struct flexboot_nodnic flexboot_nodnic_priv) [static]

Definition at line 1146 of file flexboot_nodnic.c.

References alloc_ibdev(), pci_device::dev, ib_device::dev, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, flexboot_nodnic_ib_operations, FLEXBOOT_NODNIC_PORT_BASE, ib_set_drvdata(), flexboot_nodnic_port::ibdev, ibdev_put(), MLX_OUT_OF_RESOURCES, MLX_SUCCESS, NULL, _nodnic_device_capabilites::num_ports, ib_device::op, flexboot_nodnic::pci, flexboot_nodnic::port, ib_device::port, flexboot_nodnic::port_mask, and status.

Referenced by flexboot_nodnic_probe().

                                                                                            {
        mlx_status status = MLX_SUCCESS;
        nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
        struct pci_device *pci = flexboot_nodnic_priv->pci;
        struct ib_device *ibdev = NULL;
        unsigned int i = 0;

        /* Allocate Infiniband devices */
        for (; i < device_priv->device_cap.num_ports; i++) {
                if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
                        continue;
                ibdev = alloc_ibdev(0);
                if (ibdev == NULL) {
                        status = MLX_OUT_OF_RESOURCES;
                        goto err_alloc_ibdev;
                }
                flexboot_nodnic_priv->port[i].ibdev = ibdev;
                ibdev->op = &flexboot_nodnic_ib_operations;
                ibdev->dev = &pci->dev;
                ibdev->port = ( FLEXBOOT_NODNIC_PORT_BASE + i);
                ib_set_drvdata(ibdev, flexboot_nodnic_priv);
        }
        return status;
err_alloc_ibdev:
        for ( i-- ; ( signed int ) i >= 0 ; i-- )
                ibdev_put ( flexboot_nodnic_priv->port[i].ibdev );
        return status;
}
static mlx_status flexboot_nodnic_thin_init_ports ( struct flexboot_nodnic flexboot_nodnic_priv) [static]

Definition at line 1177 of file flexboot_nodnic.c.

References _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, MLX_FATAL_CHECK_STATUS, MLX_SUCCESS, nodnic_port_thin_init(), NULL, _nodnic_device_capabilites::num_ports, flexboot_nodnic::port, flexboot_nodnic::port_mask, flexboot_nodnic_port::port_priv, and status.

Referenced by flexboot_nodnic_probe().

                                                                                {
        mlx_status status = MLX_SUCCESS;
        nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
        nodnic_port_priv *port_priv = NULL;
        unsigned int i = 0;

        for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
                if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
                        continue;
                port_priv = &flexboot_nodnic_priv->port[i].port_priv;
                status = nodnic_port_thin_init( device_priv, port_priv, i );
                MLX_FATAL_CHECK_STATUS(status, thin_init_err,
                                "flexboot_nodnic_thin_init_ports failed");
        }
thin_init_err:
        return status;
}
static mlx_status flexboot_nodnic_set_ports_type ( struct flexboot_nodnic flexboot_nodnic_priv) [static]

Definition at line 1198 of file flexboot_nodnic.c.

References DBGC, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, flexboot_nodnic_port_type_eth, MLX_FATAL_CHECK_STATUS, MLX_SUCCESS, MLX_UNSUPPORTED, nodnic_port_get_type(), NODNIC_PORT_TYPE_ETH, NODNIC_PORT_TYPE_IB, NODNIC_PORT_TYPE_UNKNOWN, NULL, _nodnic_device_capabilites::num_ports, flexboot_nodnic::port, flexboot_nodnic::port_mask, flexboot_nodnic_port::port_priv, status, flexboot_nodnic_port::type, and type.

Referenced by flexboot_nodnic_probe().

                                                                                {
        mlx_status status = MLX_SUCCESS;
        nodnic_device_priv      *device_priv = &flexboot_nodnic_priv->device_priv;
        nodnic_port_priv        *port_priv = NULL;
        nodnic_port_type        type = NODNIC_PORT_TYPE_UNKNOWN;
        unsigned int i = 0;

        for ( i = 0 ; i < device_priv->device_cap.num_ports ; i++ ) {
                if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
                        continue;
                port_priv = &flexboot_nodnic_priv->port[i].port_priv;
                status = nodnic_port_get_type(port_priv, &type);
                MLX_FATAL_CHECK_STATUS(status, type_err,
                                "nodnic_port_get_type failed");
                switch ( type ) {
                case NODNIC_PORT_TYPE_ETH:
                        DBGC ( flexboot_nodnic_priv, "Port %d type is Ethernet\n", i );
                        flexboot_nodnic_priv->port[i].type = &flexboot_nodnic_port_type_eth;
                        break;
                case NODNIC_PORT_TYPE_IB:
                        DBGC ( flexboot_nodnic_priv, "Port %d type is Infiniband\n", i );
                        status = MLX_UNSUPPORTED;
                        goto type_err;
                default:
                        DBGC ( flexboot_nodnic_priv, "Port %d type is unknown\n", i );
                        status = MLX_UNSUPPORTED;
                        goto type_err;
                }
        }
type_err:
        return status;
}
static mlx_status flexboot_nodnic_ports_register_dev ( struct flexboot_nodnic flexboot_nodnic_priv) [static]

Definition at line 1233 of file flexboot_nodnic.c.

References _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, MLX_FATAL_CHECK_STATUS, MLX_SUCCESS, NULL, _nodnic_device_capabilites::num_ports, flexboot_nodnic::port, port, flexboot_nodnic::port_mask, flexboot_nodnic_port_type::register_dev, status, and flexboot_nodnic_port::type.

Referenced by flexboot_nodnic_probe().

                                                                                   {
        mlx_status status = MLX_SUCCESS;
        nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv;
        struct flexboot_nodnic_port *port = NULL;
        unsigned int i = 0;

        for (; i < device_priv->device_cap.num_ports; i++) {
                if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
                        continue;
                port = &flexboot_nodnic_priv->port[i];
                status = port->type->register_dev ( flexboot_nodnic_priv, port );
                MLX_FATAL_CHECK_STATUS(status, reg_err,
                                "port register_dev failed");
        }
reg_err:
        return status;
}
static mlx_status flexboot_nodnic_ports_unregister_dev ( struct flexboot_nodnic flexboot_nodnic_priv) [static]

Definition at line 1253 of file flexboot_nodnic.c.

References _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, flexboot_nodnic_port::ibdev, ibdev_put(), MLX_SUCCESS, _nodnic_device_capabilites::num_ports, flexboot_nodnic::port, port, flexboot_nodnic::port_mask, flexboot_nodnic_port::type, and flexboot_nodnic_port_type::unregister_dev.

Referenced by flexboot_nodnic_probe(), and flexboot_nodnic_remove().

                                                                                      {
        struct flexboot_nodnic_port *port;
        nodnic_device_priv      *device_priv = &flexboot_nodnic_priv->device_priv;
        int i = (device_priv->device_cap.num_ports - 1);

        for (; i >= 0; i--) {
                if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
                        continue;
                port = &flexboot_nodnic_priv->port[i];
                port->type->unregister_dev(flexboot_nodnic_priv, port);
                ibdev_put(flexboot_nodnic_priv->port[i].ibdev);
        }
        return MLX_SUCCESS;
}

Definition at line 1274 of file flexboot_nodnic.c.

References _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, MLX_DEBUG_WARN, nodnic_port_enable_dma(), NODNIC_PORT_OPENED, _nodnic_device_capabilites::num_ports, flexboot_nodnic::port, flexboot_nodnic::port_mask, flexboot_nodnic_port::port_priv, _nodnic_port_priv::port_state, and status.

                                                                                   {
        nodnic_port_priv *port_priv;
        mlx_status status;
        int i;

        for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) {
                if ( ! ( nodnic->port_mask & ( i + 1 ) ) )
                        continue;
                port_priv = & ( nodnic->port[i].port_priv );
                if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) )
                        continue;

                if ( ( status = nodnic_port_enable_dma ( port_priv ) ) ) {
                        MLX_DEBUG_WARN ( nodnic, "Failed to enable DMA %d\n", status );
                }
        }
}

Definition at line 1302 of file flexboot_nodnic.c.

References buffer, DBG, memset(), MLX_CHECK_STATUS, mlx_pci_gw_init(), mlx_pci_gw_read(), mlx_pci_gw_teardown(), MLX_SUCCESS, mlx_utils_init(), mlx_utils_teardown(), NODNIC_NIC_INTERFACE_SUPPORTED_BIT, NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET, PCI_GW_SPACE_NODNIC, and status.

Referenced by shomron_nodnic_is_supported().

                                                            {
        mlx_utils utils;
        mlx_pci_gw_buffer buffer;
        mlx_status status;
        int is_supported = 0;

        DBG ( "%s: start\n", __FUNCTION__ );

        memset ( &utils, 0, sizeof ( utils ) );

        status = mlx_utils_init ( &utils, pci );
        MLX_CHECK_STATUS ( pci, status, utils_init_err, "mlx_utils_init failed" );

        status = mlx_pci_gw_init ( &utils );
        MLX_CHECK_STATUS ( pci, status, pci_gw_init_err, "mlx_pci_gw_init failed" );

        status = mlx_pci_gw_read ( &utils, PCI_GW_SPACE_NODNIC,
                        NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET, &buffer );

        if ( status == MLX_SUCCESS ) {
                buffer >>= NODNIC_NIC_INTERFACE_SUPPORTED_BIT;
                is_supported = ( buffer & 0x1 );
        }

        mlx_pci_gw_teardown( &utils );

pci_gw_init_err:
        mlx_utils_teardown(&utils);
utils_init_err:
        DBG ( "%s: NODNIC is %s supported (status = %d)\n",
                        __FUNCTION__, ( is_supported ? "": "not" ), status );
        return is_supported;
}
void flexboot_nodnic_copy_mac ( uint8_t  mac_addr[],
uint32_t  low_byte,
uint16_t  high_byte 
)

Definition at line 1337 of file flexboot_nodnic.c.

References ETH_ALEN.

                                     {
        union mac_addr {
                struct {
                        uint32_t low_byte;
                        uint16_t high_byte;
                };
                uint8_t mac_addr[ETH_ALEN];
        } mac_addr_aux;

        mac_addr_aux.high_byte = high_byte;
        mac_addr_aux.low_byte = low_byte;

        mac_addr[0] = mac_addr_aux.mac_addr[5];
        mac_addr[1] = mac_addr_aux.mac_addr[4];
        mac_addr[2] = mac_addr_aux.mac_addr[3];
        mac_addr[3] = mac_addr_aux.mac_addr[2];
        mac_addr[4] = mac_addr_aux.mac_addr[1];
        mac_addr[5] = mac_addr_aux.mac_addr[0];
}
static mlx_status flexboot_nodnic_get_factory_mac ( struct flexboot_nodnic flexboot_nodnic_priv,
uint8_t port   __attribute__(unused) 
) [static]

Definition at line 1358 of file flexboot_nodnic.c.

References DBGC, flexboot_nodnic::device_priv, memset(), mlx_vmac_query_virt_mac(), status, and _nodnic_device_priv::utils.

Referenced by flexboot_nodnic_probe().

                                                                                      {
        struct mlx_vmac_query_virt_mac virt_mac;
        mlx_status status;

        memset ( & virt_mac, 0, sizeof ( virt_mac ) );
        status = mlx_vmac_query_virt_mac ( flexboot_nodnic_priv->device_priv.utils,
                        &virt_mac );
        if ( ! status ) {
                DBGC ( flexboot_nodnic_priv, "NODNIC %p Failed to set the virtual MAC\n"
                        ,flexboot_nodnic_priv );
        }

        return status;
}
static int flexboot_nodnic_set_port_masking ( struct flexboot_nodnic flexboot_nodnic) [static]

Set port masking.

Parameters:
flexboot_nodnicnodnic device
Return values:
rcReturn status code

Definition at line 1381 of file flexboot_nodnic.c.

References DBGC, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, ENETUNREACH, _nodnic_device_capabilites::num_ports, and flexboot_nodnic::port_mask.

Referenced by flexboot_nodnic_probe().

                                                                                        {
        unsigned int i;
        nodnic_device_priv *device_priv = &flexboot_nodnic->device_priv;

        flexboot_nodnic->port_mask = 0;
        for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
                flexboot_nodnic->port_mask |= (i + 1);
        }

        if ( ! flexboot_nodnic->port_mask ) {
                /* No port was enabled */
                DBGC ( flexboot_nodnic, "NODNIC %p No port was enabled for "
                                "booting\n", flexboot_nodnic );
                return -ENETUNREACH;
        }

        return 0;
}
int init_mlx_utils ( mlx_utils **  utils,
struct pci_device pci 
)

Definition at line 1400 of file flexboot_nodnic.c.

References DBGC, free, mlx_pci_gw_init(), mlx_pci_gw_teardown(), mlx_utils_init(), mlx_utils_teardown(), NULL, rc, and zalloc().

Referenced by flexboot_nodnic_probe(), golan_probe_normal(), and golan_set_link_speed().

                                                                 {
        int rc = 0;

        *utils = ( mlx_utils * ) zalloc ( sizeof ( mlx_utils ) );
        if ( *utils == NULL ) {
                DBGC ( utils, "%s: Failed to allocate utils\n", __FUNCTION__ );
                rc = -1;
                goto err_utils_alloc;
        }
        if ( mlx_utils_init ( *utils, pci ) ) {
                DBGC ( utils, "%s: mlx_utils_init failed\n", __FUNCTION__ );
                rc = -1;
                goto err_utils_init;
        }
        if ( mlx_pci_gw_init ( *utils ) ){
                DBGC ( utils, "%s: mlx_pci_gw_init failed\n", __FUNCTION__ );
                rc = -1;
                goto err_cmd_init;
        }

        return 0;

        mlx_pci_gw_teardown ( *utils );
err_cmd_init:
        mlx_utils_teardown ( *utils );
err_utils_init:
        free ( *utils );
err_utils_alloc:
        *utils = NULL;

        return rc;
}
void free_mlx_utils ( mlx_utils **  utils)
static int flexboot_nodnic_alloc_uar ( struct flexboot_nodnic flexboot_nodnic) [static]

Initialise Nodnic PCI parameters.

Parameters:
hermonNodnic device

Definition at line 1446 of file flexboot_nodnic.c.

References DBGC, _nodnic_port_priv::device, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, EINVAL, ENOTSUP, FLEXBOOT_NODNIC_HCA_BAR, FLEXBOOT_NODNIC_PAGE_SIZE, ioremap(), MLX_SUCCESS, nodnic_port_set_send_uar_offset(), _nodnic_uar_priv::offset, flexboot_nodnic::pci, pci_bar_start(), _nodnic_uar_priv::phys, flexboot_nodnic::port, flexboot_nodnic_port::port_priv, status, _nodnic_device_capabilites::support_uar_tx_db, _nodnic_device_priv::uar, and _nodnic_uar_priv::virt.

Referenced by flexboot_nodnic_probe().

                                                                                 {
        mlx_status status = MLX_SUCCESS;
        struct pci_device *pci = flexboot_nodnic->pci;
        nodnic_uar *uar = &flexboot_nodnic->port[0].port_priv.device->uar;

        if  ( ! flexboot_nodnic->device_priv.device_cap.support_uar_tx_db ) {
                DBGC ( flexboot_nodnic, "%s: tx db using uar is not supported \n", __FUNCTION__ );
                return -ENOTSUP;
        }
        /* read uar offset then allocate */
        if  ( ( status = nodnic_port_set_send_uar_offset ( &flexboot_nodnic->port[0].port_priv ) ) ) {
                DBGC ( flexboot_nodnic, "%s: nodnic_port_set_send_uar_offset failed,"
                                "status = %d\n", __FUNCTION__, status );
                return -EINVAL;
        }
        uar->phys = ( pci_bar_start ( pci, FLEXBOOT_NODNIC_HCA_BAR ) + (mlx_uint32)uar->offset );
        uar->virt = ( void * )( ioremap ( uar->phys, FLEXBOOT_NODNIC_PAGE_SIZE ) );

        return status;
}
static int flexboot_nodnic_dealloc_uar ( struct flexboot_nodnic flexboot_nodnic) [static]
int flexboot_nodnic_probe ( struct pci_device pci,
struct flexboot_nodnic_callbacks callbacks,
void *drv_priv   __attribute__(unused) 
)

Definition at line 1479 of file flexboot_nodnic.c.

References flexboot_nodnic::callbacks, DBGC, _nodnic_device_priv::device_cap, flexboot_nodnic::device_priv, EINVAL, EN_DEFAULT_ADMIN_MTU, flexboot_nodnic_alloc_uar(), flexboot_nodnic_allocate_infiniband_devices(), flexboot_nodnic_dealloc_uar(), flexboot_nodnic_get_factory_mac(), flexboot_nodnic_ports_register_dev(), flexboot_nodnic_ports_unregister_dev(), flexboot_nodnic_set_port_masking(), flexboot_nodnic_set_ports_type(), flexboot_nodnic_thin_init_ports(), free, free_mlx_utils(), init_mlx_utils(), flexboot_nodnic_callbacks::irq, net_device_operations::irq, MLX_CHECK_STATUS, MLX_DEBUG_ERROR, MLX_FATAL_CHECK_STATUS, MLX_OUT_OF_RESOURCES, mlx_set_admin_mtu(), MLX_SUCCESS, nodnic_device_get_cap(), nodnic_device_init(), nodnic_device_teardown(), NULL, _nodnic_device_capabilites::num_ports, flexboot_nodnic::pci, pci_set_drvdata(), flexboot_nodnic::port_mask, status, _nodnic_device_priv::utils, and zalloc().

Referenced by golan_probe().

                                          {
        mlx_status status = MLX_SUCCESS;
        struct flexboot_nodnic *flexboot_nodnic_priv = NULL;
        nodnic_device_priv *device_priv = NULL;
        int i = 0;

        if ( ( pci == NULL ) || ( callbacks == NULL ) ) {
                DBGC ( flexboot_nodnic_priv, "%s: Bad Parameter\n", __FUNCTION__ );
                return -EINVAL;
        }

        flexboot_nodnic_priv = zalloc( sizeof ( *flexboot_nodnic_priv ) );
        if ( flexboot_nodnic_priv == NULL ) {
                DBGC ( flexboot_nodnic_priv, "%s: Failed to allocate priv data\n", __FUNCTION__ );
                status = MLX_OUT_OF_RESOURCES;
                goto device_err_alloc;
        }

        /* Register settings
         * Note that pci->priv will be the device private data */
        flexboot_nodnic_priv->pci = pci;
        flexboot_nodnic_priv->callbacks = callbacks;
        pci_set_drvdata ( pci, flexboot_nodnic_priv );

        device_priv = &flexboot_nodnic_priv->device_priv;
        /* init mlx utils */
        status = init_mlx_utils ( & device_priv->utils, pci );
        MLX_FATAL_CHECK_STATUS(status, err_utils_init,
                                "init_mlx_utils failed");

        /* init device */
        status = nodnic_device_init( device_priv );
        MLX_FATAL_CHECK_STATUS(status, device_init_err,
                                "nodnic_device_init failed");

        status = nodnic_device_get_cap( device_priv );
        MLX_FATAL_CHECK_STATUS(status, get_cap_err,
                                        "nodnic_device_get_cap failed");

        if ( mlx_set_admin_mtu ( device_priv->utils, 1, EN_DEFAULT_ADMIN_MTU ) ) {
                MLX_DEBUG_ERROR( device_priv->utils, "Failed to set admin mtu\n" );
        }

        status =  flexboot_nodnic_set_port_masking ( flexboot_nodnic_priv );
        MLX_FATAL_CHECK_STATUS(status, err_set_masking,
                                                "flexboot_nodnic_set_port_masking failed");

        status = flexboot_nodnic_allocate_infiniband_devices( flexboot_nodnic_priv );
        MLX_FATAL_CHECK_STATUS(status, err_alloc_ibdev,
                                        "flexboot_nodnic_allocate_infiniband_devices failed");

        /* port init */
        status = flexboot_nodnic_thin_init_ports( flexboot_nodnic_priv );
        MLX_FATAL_CHECK_STATUS(status, err_thin_init_ports,
                                                "flexboot_nodnic_thin_init_ports failed");

        if ( ( status = flexboot_nodnic_alloc_uar ( flexboot_nodnic_priv ) ) ) {
                DBGC(flexboot_nodnic_priv, "%s: flexboot_nodnic_alloc_uar failed"
                                " ( status = %d )\n",__FUNCTION__, status );
        }

        /* device reg */
        status = flexboot_nodnic_set_ports_type( flexboot_nodnic_priv );
        MLX_CHECK_STATUS( flexboot_nodnic_priv, status, err_set_ports_types,
                                                "flexboot_nodnic_set_ports_type failed");

        status = flexboot_nodnic_ports_register_dev( flexboot_nodnic_priv );
        MLX_FATAL_CHECK_STATUS(status, reg_err,
                                        "flexboot_nodnic_ports_register_dev failed");

        for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) {
                if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) )
                        continue;
                flexboot_nodnic_get_factory_mac ( flexboot_nodnic_priv, i );
        }

        /* Update ETH operations with IRQ function if supported */
        DBGC ( flexboot_nodnic_priv, "%s: %s IRQ function\n",
                        __FUNCTION__, ( callbacks->irq ? "Valid" : "No" ) );
        flexboot_nodnic_eth_operations.irq = callbacks->irq;
        return 0;

        flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv );
reg_err:
err_set_ports_types:
        flexboot_nodnic_dealloc_uar ( flexboot_nodnic_priv );
err_thin_init_ports:
err_alloc_ibdev:
err_set_masking:
get_cap_err:
        nodnic_device_teardown ( device_priv );
device_init_err:
        free_mlx_utils ( & device_priv->utils );
err_utils_init:
        free ( flexboot_nodnic_priv );
device_err_alloc:
        return status;
}
void flexboot_nodnic_remove ( struct pci_device pci)

Definition at line 1580 of file flexboot_nodnic.c.

References flexboot_nodnic::device_priv, flexboot_nodnic_dealloc_uar(), flexboot_nodnic_ports_unregister_dev(), free, free_mlx_utils(), nodnic_device_teardown(), pci_get_drvdata(), and _nodnic_device_priv::utils.

Referenced by golan_remove().

{
        struct flexboot_nodnic *flexboot_nodnic_priv = pci_get_drvdata ( pci );
        nodnic_device_priv *device_priv = & ( flexboot_nodnic_priv->device_priv );

        flexboot_nodnic_dealloc_uar ( flexboot_nodnic_priv );
        flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv );
        nodnic_device_teardown( device_priv );
        free_mlx_utils ( & device_priv->utils );
        free( flexboot_nodnic_priv );
}

Variable Documentation

Initial value:

flexboot_nodnic Infiniband operations

Definition at line 677 of file flexboot_nodnic.c.

Referenced by flexboot_nodnic_allocate_infiniband_devices().

Initial value:
 {
        .alloc_iob = alloc_iob,
}

flexboot nodnic Ethernet queue pair operations

Definition at line 753 of file flexboot_nodnic.c.

Initial value:

flexboot_nodnic Ethernet device completion operations

Definition at line 832 of file flexboot_nodnic.c.

Initial value:

flexboot_nodnic Ethernet network device operations

Definition at line 1042 of file flexboot_nodnic.c.

Initial value:

flexboot_nodnic Ethernet port type

Definition at line 1132 of file flexboot_nodnic.c.

Referenced by flexboot_nodnic_set_ports_type().