iPXE
Defines | Functions | Variables
hermon.c File Reference

Mellanox Hermon Infiniband HCA. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/io.h>
#include <ipxe/pci.h>
#include <ipxe/pcibackup.h>
#include <ipxe/malloc.h>
#include <ipxe/umalloc.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/infiniband.h>
#include <ipxe/ib_smc.h>
#include <ipxe/if_ether.h>
#include <ipxe/ethernet.h>
#include <ipxe/fcoe.h>
#include <ipxe/vlan.h>
#include <ipxe/bofm.h>
#include <ipxe/nvsvpd.h>
#include <ipxe/nvo.h>
#include "hermon.h"

Go to the source code of this file.

Defines

#define HERMON_MOD_STAT_CFG_OFFSET(field)
 Calculate offset within static configuration.
#define HERMON_ETH_NUM_SEND_WQES   2
 Number of Hermon Ethernet send work queue entries.
#define HERMON_ETH_NUM_RECV_WQES   4
 Number of Hermon Ethernet receive work queue entries.
#define HERMON_ETH_NUM_CQES   8
 Number of Hermon Ethernet completion entries.
#define HERMON_SENSE_PORT_TIMEOUT   ( TICKS_PER_SEC / 2 )
 Timeout for port sensing.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int hermon_bitmask_alloc (hermon_bitmask_t *bits, unsigned int bits_len, unsigned int num_bits)
 Allocate offsets within usage bitmask.
static void hermon_bitmask_free (hermon_bitmask_t *bits, int bit, unsigned int num_bits)
 Free offsets within usage bitmask.
static int hermon_cmd_wait (struct hermon *hermon, struct hermonprm_hca_command_register *hcr)
 Wait for Hermon command completion.
static int hermon_cmd (struct hermon *hermon, unsigned long command, unsigned int op_mod, const void *in, unsigned int in_mod, void *out)
 Issue HCA command.
static int hermon_cmd_query_dev_cap (struct hermon *hermon, struct hermonprm_query_dev_cap *dev_cap)
static int hermon_cmd_query_fw (struct hermon *hermon, struct hermonprm_query_fw *fw)
static int hermon_cmd_init_hca (struct hermon *hermon, const struct hermonprm_init_hca *init_hca)
static int hermon_cmd_close_hca (struct hermon *hermon)
static int hermon_cmd_init_port (struct hermon *hermon, unsigned int port)
static int hermon_cmd_close_port (struct hermon *hermon, unsigned int port)
static int hermon_cmd_set_port (struct hermon *hermon, int is_ethernet, unsigned int port_selector, const union hermonprm_set_port *set_port)
static int hermon_cmd_sw2hw_mpt (struct hermon *hermon, unsigned int index, const struct hermonprm_mpt *mpt)
static int hermon_cmd_write_mtt (struct hermon *hermon, const struct hermonprm_write_mtt *write_mtt)
static int hermon_cmd_map_eq (struct hermon *hermon, unsigned long index_map, const struct hermonprm_event_mask *mask)
static int hermon_cmd_sw2hw_eq (struct hermon *hermon, unsigned int index, const struct hermonprm_eqc *eqctx)
static int hermon_cmd_hw2sw_eq (struct hermon *hermon, unsigned int index, struct hermonprm_eqc *eqctx)
static int hermon_cmd_query_eq (struct hermon *hermon, unsigned int index, struct hermonprm_eqc *eqctx)
static int hermon_cmd_sw2hw_cq (struct hermon *hermon, unsigned long cqn, const struct hermonprm_completion_queue_context *cqctx)
static int hermon_cmd_hw2sw_cq (struct hermon *hermon, unsigned long cqn, struct hermonprm_completion_queue_context *cqctx)
static int hermon_cmd_query_cq (struct hermon *hermon, unsigned long cqn, struct hermonprm_completion_queue_context *cqctx)
static int hermon_cmd_rst2init_qp (struct hermon *hermon, unsigned long qpn, const struct hermonprm_qp_ee_state_transitions *ctx)
static int hermon_cmd_init2rtr_qp (struct hermon *hermon, unsigned long qpn, const struct hermonprm_qp_ee_state_transitions *ctx)
static int hermon_cmd_rtr2rts_qp (struct hermon *hermon, unsigned long qpn, const struct hermonprm_qp_ee_state_transitions *ctx)
static int hermon_cmd_rts2rts_qp (struct hermon *hermon, unsigned long qpn, const struct hermonprm_qp_ee_state_transitions *ctx)
static int hermon_cmd_2rst_qp (struct hermon *hermon, unsigned long qpn)
static int hermon_cmd_query_qp (struct hermon *hermon, unsigned long qpn, struct hermonprm_qp_ee_state_transitions *ctx)
static int hermon_cmd_conf_special_qp (struct hermon *hermon, unsigned int internal_qps, unsigned long base_qpn)
static int hermon_cmd_mad_ifc (struct hermon *hermon, unsigned int port, union hermonprm_mad *mad)
static int hermon_cmd_read_mcg (struct hermon *hermon, unsigned int index, struct hermonprm_mcg_entry *mcg)
static int hermon_cmd_write_mcg (struct hermon *hermon, unsigned int index, const struct hermonprm_mcg_entry *mcg)
static int hermon_cmd_mgid_hash (struct hermon *hermon, const union ib_gid *gid, struct hermonprm_mgm_hash *hash)
static int hermon_cmd_mod_stat_cfg (struct hermon *hermon, unsigned int mode, unsigned int input_mod, struct hermonprm_scalar_parameter *portion)
static int hermon_cmd_query_port (struct hermon *hermon, unsigned int port, struct hermonprm_query_port_cap *query_port)
static int hermon_cmd_sense_port (struct hermon *hermon, unsigned int port, struct hermonprm_sense_port *port_type)
static int hermon_cmd_run_fw (struct hermon *hermon)
static int hermon_cmd_unmap_icm (struct hermon *hermon, unsigned int page_count, const struct hermonprm_scalar_parameter *offset)
static int hermon_cmd_map_icm (struct hermon *hermon, const struct hermonprm_virtual_physical_mapping *map)
static int hermon_cmd_unmap_icm_aux (struct hermon *hermon)
static int hermon_cmd_map_icm_aux (struct hermon *hermon, const struct hermonprm_virtual_physical_mapping *map)
static int hermon_cmd_set_icm_size (struct hermon *hermon, const struct hermonprm_scalar_parameter *icm_size, struct hermonprm_scalar_parameter *icm_aux_size)
static int hermon_cmd_unmap_fa (struct hermon *hermon)
static int hermon_cmd_map_fa (struct hermon *hermon, const struct hermonprm_virtual_physical_mapping *map)
static int hermon_alloc_mtt (struct hermon *hermon, const void *memory, size_t len, struct hermon_mtt *mtt)
 Allocate MTT entries.
static void hermon_free_mtt (struct hermon *hermon, struct hermon_mtt *mtt)
 Free MTT entries.
static int hermon_mod_stat_cfg (struct hermon *hermon, unsigned int port, unsigned int mode, unsigned int offset, struct hermonprm_mod_stat_cfg *stat_cfg)
 Query or modify static configuration.
static int hermon_mad (struct ib_device *ibdev, union ib_mad *mad)
 Issue management datagram.
static int hermon_dump_cqctx (struct hermon *hermon, struct ib_completion_queue *cq)
 Dump completion queue context (for debugging only)
static int hermon_create_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Create completion queue.
static void hermon_destroy_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Destroy completion queue.
static int hermon_alloc_qpn (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Assign queue pair number.
static void hermon_free_qpn (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Free queue pair number.
static unsigned int hermon_rate (struct ib_address_vector *av)
 Calculate transmission rate.
static unsigned int hermon_sched_queue (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Calculate schedule queue.
static int hermon_dump_qpctx (struct hermon *hermon, struct ib_queue_pair *qp)
 Dump queue pair context (for debugging only)
static int hermon_create_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Create queue pair.
static int hermon_modify_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Modify queue pair.
static void hermon_destroy_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Destroy queue pair.
static unsigned int hermon_fill_nop_send_wqe (struct ib_device *ibdev __unused, struct ib_queue_pair *qp __unused, struct ib_address_vector *dest __unused, struct io_buffer *iobuf __unused, union hermon_send_wqe *wqe)
 Construct UD send work queue entry.
static unsigned int hermon_fill_ud_send_wqe (struct ib_device *ibdev, struct ib_queue_pair *qp __unused, struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe)
 Construct UD send work queue entry.
static unsigned int hermon_fill_mlx_send_wqe (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe)
 Construct MLX send work queue entry.
static unsigned int hermon_fill_rc_send_wqe (struct ib_device *ibdev, struct ib_queue_pair *qp __unused, struct ib_address_vector *dest __unused, struct io_buffer *iobuf, union hermon_send_wqe *wqe)
 Construct RC send work queue entry.
static unsigned int hermon_fill_eth_send_wqe (struct ib_device *ibdev, struct ib_queue_pair *qp __unused, struct ib_address_vector *dest __unused, struct io_buffer *iobuf, union hermon_send_wqe *wqe)
 Construct Ethernet send work queue entry.
static int hermon_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.
static int hermon_post_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf)
 Post receive work queue entry.
static int hermon_complete (struct ib_device *ibdev, struct ib_completion_queue *cq, union hermonprm_completion_entry *cqe)
 Handle completion.
static void hermon_poll_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Poll completion queue.
static int hermon_create_eq (struct hermon *hermon)
 Create event queue.
static void hermon_destroy_eq (struct hermon *hermon)
 Destroy event queue.
static void hermon_event_port_state_change (struct hermon *hermon, union hermonprm_event_entry *eqe)
 Handle port state event.
static void hermon_poll_eq (struct ib_device *ibdev)
 Poll event queue.
static int hermon_map_vpm (struct hermon *hermon, int(*map)(struct hermon *hermon, const struct hermonprm_virtual_physical_mapping *), uint64_t va, physaddr_t pa, size_t len)
 Map virtual to physical address for firmware usage.
static int hermon_start_firmware (struct hermon *hermon)
 Start firmware running.
static void hermon_stop_firmware (struct hermon *hermon)
 Stop firmware running.
static int hermon_get_cap (struct hermon *hermon)
 Get device limits.
static uint64_t icm_align (uint64_t icm_offset, size_t len)
 Align ICM table.
static int hermon_map_icm (struct hermon *hermon, struct hermonprm_init_hca *init_hca)
 Map ICM (allocating if necessary)
static void hermon_unmap_icm (struct hermon *hermon)
 Unmap ICM.
static void hermon_reset (struct hermon *hermon)
 Reset device.
static int hermon_setup_mpt (struct hermon *hermon)
 Set up memory protection table.
static int hermon_configure_special_qps (struct hermon *hermon)
 Configure special queue pairs.
static int hermon_start (struct hermon *hermon, int running)
 Start Hermon device.
static void hermon_stop (struct hermon *hermon)
 Stop Hermon device.
static int hermon_open (struct hermon *hermon)
 Open Hermon device.
static void hermon_close (struct hermon *hermon)
 Close Hermon device.
static int hermon_ib_open (struct ib_device *ibdev)
 Initialise Infiniband link.
static void hermon_ib_close (struct ib_device *ibdev)
 Close Infiniband link.
static int hermon_inform_sma (struct ib_device *ibdev, union ib_mad *mad)
 Inform embedded subnet management agent of a received MAD.
static int hermon_mcast_attach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
 Attach to multicast group.
static void hermon_mcast_detach (struct ib_device *ibdev, struct ib_queue_pair *qp __unused, union ib_gid *gid)
 Detach from multicast group.
static int hermon_register_ibdev (struct hermon *hermon, struct hermon_port *port)
 Register Hermon Infiniband device.
static void hermon_state_change_ibdev (struct hermon *hermon __unused, struct hermon_port *port, int link_up __unused)
 Handle Hermon Infiniband device port state change.
static void hermon_unregister_ibdev (struct hermon *hermon __unused, struct hermon_port *port)
 Unregister Hermon Infiniband device.
static int hermon_eth_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet via Hermon Ethernet device.
static void hermon_eth_complete_send (struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
 Handle Hermon Ethernet device send completion.
static void hermon_eth_complete_recv (struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct ib_address_vector *dest __unused, struct ib_address_vector *source, struct io_buffer *iobuf, int rc)
 Handle Hermon Ethernet device receive completion.
static void hermon_eth_poll (struct net_device *netdev)
 Poll Hermon Ethernet device.
static int hermon_eth_open (struct net_device *netdev)
 Open Hermon Ethernet device.
static void hermon_eth_close (struct net_device *netdev)
 Close Hermon Ethernet device.
static int hermon_register_netdev (struct hermon *hermon, struct hermon_port *port)
 Register Hermon Ethernet device.
static void hermon_state_change_netdev (struct hermon *hermon __unused, struct hermon_port *port, int link_up)
 Handle Hermon Ethernet device port state change.
static void hermon_unregister_netdev (struct hermon *hermon __unused, struct hermon_port *port)
 Unregister Hermon Ethernet device.
static const char * hermon_name_port_type (unsigned int port_type)
 Name port type.
static int hermon_sense_port_type (struct hermon *hermon, struct hermon_port *port)
 Sense port type.
static int hermon_set_port_type (struct hermon *hermon, struct hermon_port *port)
 Set port type.
static int hermon_bofm_harvest (struct bofm_device *bofm, unsigned int mport, uint8_t *mac)
 Harvest Ethernet MAC for BOFM.
static int hermon_bofm_update (struct bofm_device *bofm, unsigned int mport, const uint8_t *mac)
 Update Ethernet MAC for BOFM.
static struct hermonhermon_alloc (void)
 Allocate Hermon device.
static void hermon_free (struct hermon *hermon)
 Free Hermon device.
static int hermon_probe (struct pci_device *pci)
 Probe PCI device.
static void hermon_remove (struct pci_device *pci)
 Remove PCI device.
static int hermon_bofm_probe (struct pci_device *pci)
 Probe PCI device for BOFM.
static void hermon_bofm_remove (struct pci_device *pci)
 Remove PCI device for BOFM.

Variables

static uint8_t hermon_qp_st []
 Queue pair transport service type map.
static unsigned int(* hermon_fill_send_wqe [])(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe)
 Work queue entry constructors.
static struct ib_device_operations hermon_ib_operations
 Hermon Infiniband operations.
static struct hermon_port_type hermon_port_type_ib
 Hermon Infiniband port type.
static struct
ib_queue_pair_operations 
hermon_eth_qp_op
 Hermon Ethernet queue pair operations.
static struct
ib_completion_queue_operations 
hermon_eth_cq_op
 Hermon Ethernet device completion operations.
static struct net_device_operations hermon_eth_operations
 Hermon Ethernet network device operations.
static struct hermon_port_type hermon_port_type_eth
 Hermon Ethernet port type.
static struct bofm_operations hermon_bofm_operations
 Hermon BOFM operations.
static struct pci_device_id hermon_nics []
struct pci_driver hermon_driver __pci_driver
struct pci_driver
hermon_bofm_driver 
__bofm_driver

Detailed Description

Mellanox Hermon Infiniband HCA.

Definition in file hermon.c.


Define Documentation

#define HERMON_MOD_STAT_CFG_OFFSET (   field)
Value:
( ( MLX_BIT_OFFSET ( struct hermonprm_mod_stat_cfg_st, field ) / 8 ) \
          & ~( sizeof ( struct hermonprm_scalar_parameter ) - 1 ) )

Calculate offset within static configuration.

Parameters:
fieldField
Return values:
offsetOffset

Definition at line 717 of file hermon.c.

Referenced by hermon_bofm_harvest(), and hermon_bofm_update().

#define HERMON_ETH_NUM_SEND_WQES   2

Number of Hermon Ethernet send work queue entries.

Definition at line 3140 of file hermon.c.

Referenced by hermon_eth_open().

#define HERMON_ETH_NUM_RECV_WQES   4

Number of Hermon Ethernet receive work queue entries.

Definition at line 3143 of file hermon.c.

Referenced by hermon_eth_open().

#define HERMON_ETH_NUM_CQES   8

Number of Hermon Ethernet completion entries.

Definition at line 3146 of file hermon.c.

Referenced by hermon_eth_open().

Timeout for port sensing.

Definition at line 3498 of file hermon.c.

Referenced by hermon_set_port_type().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int hermon_bitmask_alloc ( hermon_bitmask_t bits,
unsigned int  bits_len,
unsigned int  num_bits 
) [static]

Allocate offsets within usage bitmask.

Parameters:
bitsUsage bitmask
bits_lenLength of usage bitmask
num_bitsNumber of contiguous bits to allocate within bitmask
Return values:
bitFirst free bit within bitmask, or negative error

Definition at line 71 of file hermon.c.

References ENFILE.

Referenced by hermon_alloc_mtt(), hermon_alloc_qpn(), and hermon_create_cq().

                                                          {
        unsigned int bit = 0;
        hermon_bitmask_t mask = 1;
        unsigned int found = 0;

        /* Search bits for num_bits contiguous free bits */
        while ( bit < bits_len ) {
                if ( ( mask & *bits ) == 0 ) {
                        if ( ++found == num_bits )
                                goto found;
                } else {
                        found = 0;
                }
                bit++;
                mask = ( mask << 1 ) | ( mask >> ( 8 * sizeof ( mask ) - 1 ) );
                if ( mask == 1 )
                        bits++;
        }
        return -ENFILE;

 found:
        /* Mark bits as in-use */
        do {
                *bits |= mask;
                if ( mask == 1 )
                        bits--;
                mask = ( mask >> 1 ) | ( mask << ( 8 * sizeof ( mask ) - 1 ) );
        } while ( --found );

        return ( bit - num_bits + 1 );
}
static void hermon_bitmask_free ( hermon_bitmask_t bits,
int  bit,
unsigned int  num_bits 
) [static]

Free offsets within usage bitmask.

Parameters:
bitsUsage bitmask
bitStarting bit within bitmask
num_bitsNumber of contiguous bits to free within bitmask

Definition at line 112 of file hermon.c.

Referenced by hermon_alloc_mtt(), hermon_create_cq(), hermon_destroy_cq(), hermon_free_mtt(), and hermon_free_qpn().

                                                                   {
        hermon_bitmask_t mask;

        for ( ; num_bits ; bit++, num_bits-- ) {
                mask = ( 1 << ( bit % ( 8 * sizeof ( mask ) ) ) );
                bits[ ( bit / ( 8 * sizeof ( mask ) ) ) ] &= ~mask;
        }
}
static int hermon_cmd_wait ( struct hermon hermon,
struct hermonprm_hca_command_register *  hcr 
) [static]

Wait for Hermon command completion.

Parameters:
hermonHermon device
hcrHCA command registers
Return values:
rcReturn status code

Definition at line 136 of file hermon.c.

References hermon::config, EBUSY, HERMON_HCR_MAX_WAIT_MS, HERMON_HCR_REG, mdelay(), MLX_GET, readl(), and hermon::toggle.

Referenced by hermon_cmd().

                                                                          {
        unsigned int wait;

        for ( wait = HERMON_HCR_MAX_WAIT_MS ; wait ; wait-- ) {
                hcr->u.dwords[6] =
                        readl ( hermon->config + HERMON_HCR_REG ( 6 ) );
                if ( ( MLX_GET ( hcr, go ) == 0 ) &&
                     ( MLX_GET ( hcr, t ) == hermon->toggle ) )
                        return 0;
                mdelay ( 1 );
        }
        return -EBUSY;
}
static int hermon_cmd ( struct hermon hermon,
unsigned long  command,
unsigned int  op_mod,
const void *  in,
unsigned int  in_mod,
void *  out 
) [static]

Issue HCA command.

Parameters:
hermonHermon device
commandCommand opcode, flags and input/output lengths
op_modOpcode modifier (0 if no modifier applicable)
inInput parameters
in_modInput modifier (0 if no modifier applicable)
outOutput parameters
Return values:
rcReturn status code

Definition at line 162 of file hermon.c.

References assert, barrier, hermon::config, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, EIO, hermon_cmd_wait(), HERMON_HCR_BASE, HERMON_HCR_IN_LEN, HERMON_HCR_IN_MBOX, HERMON_HCR_OPCODE, HERMON_HCR_OUT_LEN, HERMON_HCR_OUT_MBOX, HERMON_HCR_REG, HERMON_MBOX_SIZE, hermon::mailbox_in, hermon::mailbox_out, memcpy(), memset(), MLX_FILL_1, MLX_FILL_4, MLX_FILL_H, MLX_GET, opcode, rc, readl(), status, hermon::toggle, virt_to_bus(), virt_to_phys(), and writel().

Referenced by hermon_cmd_2rst_qp(), hermon_cmd_close_hca(), hermon_cmd_close_port(), hermon_cmd_conf_special_qp(), hermon_cmd_hw2sw_cq(), hermon_cmd_hw2sw_eq(), hermon_cmd_init2rtr_qp(), hermon_cmd_init_hca(), hermon_cmd_init_port(), hermon_cmd_mad_ifc(), hermon_cmd_map_eq(), hermon_cmd_map_fa(), hermon_cmd_map_icm(), hermon_cmd_map_icm_aux(), hermon_cmd_mgid_hash(), hermon_cmd_mod_stat_cfg(), hermon_cmd_query_cq(), hermon_cmd_query_dev_cap(), hermon_cmd_query_eq(), hermon_cmd_query_fw(), hermon_cmd_query_port(), hermon_cmd_query_qp(), hermon_cmd_read_mcg(), hermon_cmd_rst2init_qp(), hermon_cmd_rtr2rts_qp(), hermon_cmd_rts2rts_qp(), hermon_cmd_run_fw(), hermon_cmd_sense_port(), hermon_cmd_set_icm_size(), hermon_cmd_set_port(), hermon_cmd_sw2hw_cq(), hermon_cmd_sw2hw_eq(), hermon_cmd_sw2hw_mpt(), hermon_cmd_unmap_fa(), hermon_cmd_unmap_icm(), hermon_cmd_unmap_icm_aux(), hermon_cmd_write_mcg(), and hermon_cmd_write_mtt().

                                                         {
        struct hermonprm_hca_command_register hcr;
        unsigned int opcode = HERMON_HCR_OPCODE ( command );
        size_t in_len = HERMON_HCR_IN_LEN ( command );
        size_t out_len = HERMON_HCR_OUT_LEN ( command );
        void *in_buffer;
        void *out_buffer;
        unsigned int status;
        unsigned int i;
        int rc;

        assert ( in_len <= HERMON_MBOX_SIZE );
        assert ( out_len <= HERMON_MBOX_SIZE );

        DBGC2 ( hermon, "Hermon %p command %02x in %zx%s out %zx%s\n",
                hermon, opcode, in_len,
                ( ( command & HERMON_HCR_IN_MBOX ) ? "(mbox)" : "" ), out_len,
                ( ( command & HERMON_HCR_OUT_MBOX ) ? "(mbox)" : "" ) );

        /* Check that HCR is free */
        if ( ( rc = hermon_cmd_wait ( hermon, &hcr ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p command interface locked\n",
                       hermon );
                return rc;
        }

        /* Flip HCR toggle */
        hermon->toggle = ( 1 - hermon->toggle );

        /* Prepare HCR */
        memset ( &hcr, 0, sizeof ( hcr ) );
        in_buffer = &hcr.u.dwords[0];
        if ( in_len && ( command & HERMON_HCR_IN_MBOX ) ) {
                memset ( hermon->mailbox_in, 0, HERMON_MBOX_SIZE );
                in_buffer = hermon->mailbox_in;
                MLX_FILL_H ( &hcr, 0, in_param_h, virt_to_bus ( in_buffer ) );
                MLX_FILL_1 ( &hcr, 1, in_param_l, virt_to_bus ( in_buffer ) );
        }
        memcpy ( in_buffer, in, in_len );
        MLX_FILL_1 ( &hcr, 2, input_modifier, in_mod );
        out_buffer = &hcr.u.dwords[3];
        if ( out_len && ( command & HERMON_HCR_OUT_MBOX ) ) {
                out_buffer = hermon->mailbox_out;
                MLX_FILL_H ( &hcr, 3, out_param_h,
                             virt_to_bus ( out_buffer ) );
                MLX_FILL_1 ( &hcr, 4, out_param_l,
                             virt_to_bus ( out_buffer ) );
        }
        MLX_FILL_4 ( &hcr, 6,
                     opcode, opcode,
                     opcode_modifier, op_mod,
                     go, 1,
                     t, hermon->toggle );
        DBGC ( hermon, "Hermon %p issuing command %04x\n",
               hermon, opcode );
        DBGC2_HDA ( hermon, virt_to_phys ( hermon->config + HERMON_HCR_BASE ),
                    &hcr, sizeof ( hcr ) );
        if ( in_len && ( command & HERMON_HCR_IN_MBOX ) ) {
                DBGC2 ( hermon, "Input mailbox:\n" );
                DBGC2_HDA ( hermon, virt_to_phys ( in_buffer ), in_buffer,
                            ( ( in_len < 512 ) ? in_len : 512 ) );
        }

        /* Issue command */
        for ( i = 0 ; i < ( sizeof ( hcr ) / sizeof ( hcr.u.dwords[0] ) ) ;
              i++ ) {
                writel ( hcr.u.dwords[i],
                         hermon->config + HERMON_HCR_REG ( i ) );
                barrier();
        }

        /* Wait for command completion */
        if ( ( rc = hermon_cmd_wait ( hermon, &hcr ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p timed out waiting for command:\n",
                       hermon );
                DBGC_HDA ( hermon,
                           virt_to_phys ( hermon->config + HERMON_HCR_BASE ),
                           &hcr, sizeof ( hcr ) );
                return rc;
        }

        /* Check command status */
        status = MLX_GET ( &hcr, status );
        if ( status != 0 ) {
                DBGC ( hermon, "Hermon %p command failed with status %02x:\n",
                       hermon, status );
                DBGC_HDA ( hermon,
                           virt_to_phys ( hermon->config + HERMON_HCR_BASE ),
                           &hcr, sizeof ( hcr ) );
                return -EIO;
        }

        /* Read output parameters, if any */
        hcr.u.dwords[3] = readl ( hermon->config + HERMON_HCR_REG ( 3 ) );
        hcr.u.dwords[4] = readl ( hermon->config + HERMON_HCR_REG ( 4 ) );
        memcpy ( out, out_buffer, out_len );
        if ( out_len ) {
                DBGC2 ( hermon, "Output%s:\n",
                        ( command & HERMON_HCR_OUT_MBOX ) ? " mailbox" : "" );
                DBGC2_HDA ( hermon, virt_to_phys ( out_buffer ), out_buffer,
                            ( ( out_len < 512 ) ? out_len : 512 ) );
        }

        return 0;
}
static int hermon_cmd_query_dev_cap ( struct hermon hermon,
struct hermonprm_query_dev_cap *  dev_cap 
) [inline, static]

Definition at line 271 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_QUERY_DEV_CAP, and NULL.

Referenced by hermon_get_cap().

                                                                     {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_DEV_CAP,
                                                 1, sizeof ( *dev_cap ) ),
                            0, NULL, 0, dev_cap );
}
static int hermon_cmd_query_fw ( struct hermon hermon,
struct hermonprm_query_fw *  fw 
) [inline, static]

Definition at line 280 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_QUERY_FW, and NULL.

Referenced by hermon_start_firmware().

                                                                             {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_FW,
                                                 1, sizeof ( *fw ) ),
                            0, NULL, 0, fw );
}
static int hermon_cmd_init_hca ( struct hermon hermon,
const struct hermonprm_init_hca *  init_hca 
) [inline, static]

Definition at line 288 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_INIT_HCA, and NULL.

Referenced by hermon_start().

                                                                  {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_INIT_HCA,
                                                1, sizeof ( *init_hca ) ),
                            0, init_hca, 0, NULL );
}
static int hermon_cmd_close_hca ( struct hermon hermon) [inline, static]

Definition at line 297 of file hermon.c.

References hermon_cmd(), HERMON_HCR_CLOSE_HCA, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_start(), and hermon_stop().

                                               {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_CLOSE_HCA ),
                            0, NULL, 0, NULL );
}
static int hermon_cmd_init_port ( struct hermon hermon,
unsigned int  port 
) [inline, static]

Definition at line 304 of file hermon.c.

References hermon_cmd(), HERMON_HCR_INIT_PORT, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_eth_open(), and hermon_ib_open().

                                                                  {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_INIT_PORT ),
                            0, NULL, port, NULL );
}
static int hermon_cmd_close_port ( struct hermon hermon,
unsigned int  port 
) [inline, static]

Definition at line 311 of file hermon.c.

References hermon_cmd(), HERMON_HCR_CLOSE_PORT, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_eth_close(), and hermon_ib_close().

static int hermon_cmd_set_port ( struct hermon hermon,
int  is_ethernet,
unsigned int  port_selector,
const union hermonprm_set_port set_port 
) [inline, static]

Definition at line 318 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_SET_PORT, and NULL.

Referenced by hermon_eth_open(), and hermon_ib_open().

                                                                 {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_SET_PORT,
                                                1, sizeof ( *set_port ) ),
                            is_ethernet, set_port, port_selector, NULL );
}
static int hermon_cmd_sw2hw_mpt ( struct hermon hermon,
unsigned int  index,
const struct hermonprm_mpt *  mpt 
) [inline, static]

Definition at line 328 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_SW2HW_MPT, and NULL.

Referenced by hermon_setup_mpt().

                                                         {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_SW2HW_MPT,
                                                1, sizeof ( *mpt ) ),
                            0, mpt, index, NULL );
}
static int hermon_cmd_write_mtt ( struct hermon hermon,
const struct hermonprm_write_mtt write_mtt 
) [inline, static]

Definition at line 337 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_WRITE_MTT, and NULL.

Referenced by hermon_alloc_mtt().

                                                                     {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_WRITE_MTT,
                                                1, sizeof ( *write_mtt ) ),
                            0, write_mtt, 1, NULL );
}
static int hermon_cmd_map_eq ( struct hermon hermon,
unsigned long  index_map,
const struct hermonprm_event_mask *  mask 
) [inline, static]

Definition at line 346 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_MAP_EQ, and NULL.

Referenced by hermon_create_eq(), and hermon_destroy_eq().

                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_EQ,
                                                0, sizeof ( *mask ) ),
                            0, mask, index_map, NULL );
}
static int hermon_cmd_sw2hw_eq ( struct hermon hermon,
unsigned int  index,
const struct hermonprm_eqc *  eqctx 
) [inline, static]

Definition at line 355 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_SW2HW_EQ, and NULL.

Referenced by hermon_create_eq().

                                                          {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_SW2HW_EQ,
                                                1, sizeof ( *eqctx ) ),
                            0, eqctx, index, NULL );
}
static int hermon_cmd_hw2sw_eq ( struct hermon hermon,
unsigned int  index,
struct hermonprm_eqc *  eqctx 
) [inline, static]

Definition at line 364 of file hermon.c.

References hermon_cmd(), HERMON_HCR_HW2SW_EQ, HERMON_HCR_OUT_CMD, and NULL.

Referenced by hermon_create_eq(), and hermon_destroy_eq().

                                                    {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_HW2SW_EQ,
                                                 1, sizeof ( *eqctx ) ),
                            1, NULL, index, eqctx );
}
static int hermon_cmd_query_eq ( struct hermon hermon,
unsigned int  index,
struct hermonprm_eqc *  eqctx 
) [inline, static]

Definition at line 373 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_QUERY_EQ, and NULL.

                                                    {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_EQ,
                                                 1, sizeof ( *eqctx ) ),
                            0, NULL, index, eqctx );
}
static int hermon_cmd_sw2hw_cq ( struct hermon hermon,
unsigned long  cqn,
const struct hermonprm_completion_queue_context *  cqctx 
) [inline, static]

Definition at line 382 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_SW2HW_CQ, and NULL.

Referenced by hermon_create_cq().

                                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_SW2HW_CQ,
                                                1, sizeof ( *cqctx ) ),
                            0, cqctx, cqn, NULL );
}
static int hermon_cmd_hw2sw_cq ( struct hermon hermon,
unsigned long  cqn,
struct hermonprm_completion_queue_context *  cqctx 
) [inline, static]

Definition at line 391 of file hermon.c.

References hermon_cmd(), HERMON_HCR_HW2SW_CQ, HERMON_HCR_OUT_CMD, and NULL.

Referenced by hermon_destroy_cq().

                                                                         {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_HW2SW_CQ,
                                                 1, sizeof ( *cqctx ) ),
                            0, NULL, cqn, cqctx );
}
static int hermon_cmd_query_cq ( struct hermon hermon,
unsigned long  cqn,
struct hermonprm_completion_queue_context *  cqctx 
) [inline, static]

Definition at line 400 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_QUERY_CQ, and NULL.

Referenced by hermon_dump_cqctx().

                                                                         {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_CQ,
                                                 1, sizeof ( *cqctx ) ),
                            0, NULL, cqn, cqctx );
}
static int hermon_cmd_rst2init_qp ( struct hermon hermon,
unsigned long  qpn,
const struct hermonprm_qp_ee_state_transitions *  ctx 
) [inline, static]

Definition at line 409 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_RST2INIT_QP, and NULL.

Referenced by hermon_create_qp().

                                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_RST2INIT_QP,
                                                1, sizeof ( *ctx ) ),
                            0, ctx, qpn, NULL );
}
static int hermon_cmd_init2rtr_qp ( struct hermon hermon,
unsigned long  qpn,
const struct hermonprm_qp_ee_state_transitions *  ctx 
) [inline, static]

Definition at line 418 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_INIT2RTR_QP, and NULL.

Referenced by hermon_modify_qp().

                                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_INIT2RTR_QP,
                                                1, sizeof ( *ctx ) ),
                            0, ctx, qpn, NULL );
}
static int hermon_cmd_rtr2rts_qp ( struct hermon hermon,
unsigned long  qpn,
const struct hermonprm_qp_ee_state_transitions *  ctx 
) [inline, static]

Definition at line 427 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_RTR2RTS_QP, and NULL.

Referenced by hermon_modify_qp().

                                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_RTR2RTS_QP,
                                                1, sizeof ( *ctx ) ),
                            0, ctx, qpn, NULL );
}
static int hermon_cmd_rts2rts_qp ( struct hermon hermon,
unsigned long  qpn,
const struct hermonprm_qp_ee_state_transitions *  ctx 
) [inline, static]

Definition at line 436 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_RTS2RTS_QP, and NULL.

Referenced by hermon_modify_qp().

                                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_RTS2RTS_QP,
                                                1, sizeof ( *ctx ) ),
                            0, ctx, qpn, NULL );
}
static int hermon_cmd_2rst_qp ( struct hermon hermon,
unsigned long  qpn 
) [inline, static]

Definition at line 445 of file hermon.c.

References hermon_cmd(), HERMON_HCR_2RST_QP, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_create_qp(), and hermon_destroy_qp().

                                                                {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_2RST_QP ),
                            0x03, NULL, qpn, NULL );
}
static int hermon_cmd_query_qp ( struct hermon hermon,
unsigned long  qpn,
struct hermonprm_qp_ee_state_transitions *  ctx 
) [inline, static]

Definition at line 452 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_QUERY_QP, and NULL.

Referenced by hermon_dump_qpctx().

                                                                      {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_QP,
                                                 1, sizeof ( *ctx ) ),
                            0, NULL, qpn, ctx );
}
static int hermon_cmd_conf_special_qp ( struct hermon hermon,
unsigned int  internal_qps,
unsigned long  base_qpn 
) [inline, static]

Definition at line 461 of file hermon.c.

References hermon_cmd(), HERMON_HCR_CONF_SPECIAL_QP, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_configure_special_qps().

                                                      {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_CONF_SPECIAL_QP ),
                            internal_qps, NULL, base_qpn, NULL );
}
static int hermon_cmd_mad_ifc ( struct hermon hermon,
unsigned int  port,
union hermonprm_mad mad 
) [inline, static]

Definition at line 469 of file hermon.c.

References hermon_cmd(), HERMON_HCR_INOUT_CMD, and HERMON_HCR_MAD_IFC.

Referenced by hermon_mad().

                                                {
        return hermon_cmd ( hermon,
                            HERMON_HCR_INOUT_CMD ( HERMON_HCR_MAD_IFC,
                                                   1, sizeof ( *mad ),
                                                   1, sizeof ( *mad ) ),
                            0x03, mad, port, mad );
}
static int hermon_cmd_read_mcg ( struct hermon hermon,
unsigned int  index,
struct hermonprm_mcg_entry *  mcg 
) [inline, static]

Definition at line 479 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_READ_MCG, and NULL.

Referenced by hermon_mcast_attach().

                                                        {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_READ_MCG,
                                                 1, sizeof ( *mcg ) ),
                            0, NULL, index, mcg );
}
static int hermon_cmd_write_mcg ( struct hermon hermon,
unsigned int  index,
const struct hermonprm_mcg_entry *  mcg 
) [inline, static]

Definition at line 488 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_WRITE_MCG, and NULL.

Referenced by hermon_mcast_attach(), and hermon_mcast_detach().

                                                               {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_WRITE_MCG,
                                                1, sizeof ( *mcg ) ),
                            0, mcg, index, NULL );
}
static int hermon_cmd_mgid_hash ( struct hermon hermon,
const union ib_gid gid,
struct hermonprm_mgm_hash *  hash 
) [inline, static]

Definition at line 497 of file hermon.c.

References hermon_cmd(), HERMON_HCR_INOUT_CMD, and HERMON_HCR_MGID_HASH.

Referenced by hermon_mcast_attach(), and hermon_mcast_detach().

                                                         {
        return hermon_cmd ( hermon,
                            HERMON_HCR_INOUT_CMD ( HERMON_HCR_MGID_HASH,
                                                   1, sizeof ( *gid ),
                                                   0, sizeof ( *hash ) ),
                            0, gid, 0, hash );
}
static int hermon_cmd_mod_stat_cfg ( struct hermon hermon,
unsigned int  mode,
unsigned int  input_mod,
struct hermonprm_scalar_parameter *  portion 
) [inline, static]

Definition at line 507 of file hermon.c.

References hermon_cmd(), HERMON_HCR_INOUT_CMD, and HERMON_HCR_MOD_STAT_CFG.

Referenced by hermon_mod_stat_cfg().

                                                                       {
        return hermon_cmd ( hermon,
                            HERMON_HCR_INOUT_CMD ( HERMON_HCR_MOD_STAT_CFG,
                                                   0, sizeof ( *portion ),
                                                   0, sizeof ( *portion ) ),
                            mode, portion, input_mod, portion );
}
static int hermon_cmd_query_port ( struct hermon hermon,
unsigned int  port,
struct hermonprm_query_port_cap *  query_port 
) [inline, static]

Definition at line 518 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_QUERY_PORT, and NULL.

Referenced by hermon_register_netdev(), and hermon_set_port_type().

                                                                      {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_PORT,
                                                 1, sizeof ( *query_port ) ),
                            0, NULL, port, query_port );
}
static int hermon_cmd_sense_port ( struct hermon hermon,
unsigned int  port,
struct hermonprm_sense_port *  port_type 
) [inline, static]

Definition at line 527 of file hermon.c.

References hermon_cmd(), HERMON_HCR_OUT_CMD, HERMON_HCR_SENSE_PORT, and NULL.

Referenced by hermon_sense_port_type().

                                                                 {
        return hermon_cmd ( hermon,
                            HERMON_HCR_OUT_CMD ( HERMON_HCR_SENSE_PORT,
                                                 0, sizeof ( *port_type ) ),
                            0, NULL, port, port_type );
}
static int hermon_cmd_run_fw ( struct hermon hermon) [inline, static]

Definition at line 536 of file hermon.c.

References hermon_cmd(), HERMON_HCR_RUN_FW, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_start_firmware().

                                            {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_RUN_FW ),
                            0, NULL, 0, NULL );
}
static int hermon_cmd_unmap_icm ( struct hermon hermon,
unsigned int  page_count,
const struct hermonprm_scalar_parameter *  offset 
) [inline, static]

Definition at line 543 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_UNMAP_ICM, and NULL.

Referenced by hermon_unmap_icm().

                                                                         {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_UNMAP_ICM,
                                                0, sizeof ( *offset ) ),
                            0, offset, page_count, NULL );
}
static int hermon_cmd_map_icm ( struct hermon hermon,
const struct hermonprm_virtual_physical_mapping *  map 
) [inline, static]

Definition at line 552 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_MAP_ICM, and NULL.

Referenced by hermon_map_icm().

                                                                            {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_ICM,
                                                1, sizeof ( *map ) ),
                            0, map, 1, NULL );
}
static int hermon_cmd_unmap_icm_aux ( struct hermon hermon) [inline, static]

Definition at line 561 of file hermon.c.

References hermon_cmd(), HERMON_HCR_UNMAP_ICM_AUX, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_map_icm(), and hermon_unmap_icm().

                                                   {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_UNMAP_ICM_AUX ),
                            0, NULL, 0, NULL );
}
static int hermon_cmd_map_icm_aux ( struct hermon hermon,
const struct hermonprm_virtual_physical_mapping *  map 
) [inline, static]

Definition at line 568 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_MAP_ICM_AUX, and NULL.

Referenced by hermon_map_icm().

                                                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_ICM_AUX,
                                                1, sizeof ( *map ) ),
                            0, map, 1, NULL );
}
static int hermon_cmd_set_icm_size ( struct hermon hermon,
const struct hermonprm_scalar_parameter *  icm_size,
struct hermonprm_scalar_parameter *  icm_aux_size 
) [inline, static]

Definition at line 577 of file hermon.c.

References hermon_cmd(), HERMON_HCR_INOUT_CMD, and HERMON_HCR_SET_ICM_SIZE.

Referenced by hermon_map_icm().

                                                                            {
        return hermon_cmd ( hermon,
                            HERMON_HCR_INOUT_CMD ( HERMON_HCR_SET_ICM_SIZE,
                                                   0, sizeof ( *icm_size ),
                                                   0, sizeof (*icm_aux_size) ),
                            0, icm_size, 0, icm_aux_size );
}
static int hermon_cmd_unmap_fa ( struct hermon hermon) [inline, static]

Definition at line 588 of file hermon.c.

References hermon_cmd(), HERMON_HCR_UNMAP_FA, HERMON_HCR_VOID_CMD, and NULL.

Referenced by hermon_start_firmware(), and hermon_stop_firmware().

                                              {
        return hermon_cmd ( hermon,
                            HERMON_HCR_VOID_CMD ( HERMON_HCR_UNMAP_FA ),
                            0, NULL, 0, NULL );
}
static int hermon_cmd_map_fa ( struct hermon hermon,
const struct hermonprm_virtual_physical_mapping *  map 
) [inline, static]

Definition at line 595 of file hermon.c.

References hermon_cmd(), HERMON_HCR_IN_CMD, HERMON_HCR_MAP_FA, and NULL.

Referenced by hermon_start_firmware().

                                                                           {
        return hermon_cmd ( hermon,
                            HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_FA,
                                                1, sizeof ( *map ) ),
                            0, map, 1, NULL );
}
static int hermon_alloc_mtt ( struct hermon hermon,
const void *  memory,
size_t  len,
struct hermon_mtt mtt 
) [static]

Allocate MTT entries.

Parameters:
hermonHermon device
memoryMemory to map into MTT
lenLength of memory to map
mttMTT descriptor to fill in
Return values:
rcReturn status code

Definition at line 619 of file hermon.c.

References addr, hermon::cap, DBGC, hermon_bitmask_alloc(), hermon_bitmask_free(), hermon_cmd_write_mtt(), HERMON_MAX_MTTS, HERMON_PAGE_SIZE, memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_H, hermonprm_write_mtt::mtt, hermonprm_write_mtt::mtt_base_addr, hermon_mtt::mtt_base_addr, hermon_dev_cap::mtt_entry_size, hermon::mtt_inuse, hermon_mtt::mtt_offset, num_pages, hermon_mtt::num_pages, hermon_mtt::page_offset, page_offset, rc, hermon_dev_cap::reserved_mtts, start, value, and virt_to_phys().

Referenced by hermon_create_cq(), hermon_create_eq(), and hermon_create_qp().

                                                       {
        struct hermonprm_write_mtt write_mtt;
        physaddr_t start;
        physaddr_t addr;
        unsigned int page_offset;
        unsigned int num_pages;
        int mtt_offset;
        unsigned int mtt_base_addr;
        unsigned int i;
        int rc;

        /* Find available MTT entries */
        start = virt_to_phys ( memory );
        page_offset = ( start & ( HERMON_PAGE_SIZE - 1 ) );
        start -= page_offset;
        len += page_offset;
        num_pages = ( ( len + HERMON_PAGE_SIZE - 1 ) / HERMON_PAGE_SIZE );
        mtt_offset = hermon_bitmask_alloc ( hermon->mtt_inuse, HERMON_MAX_MTTS,
                                            num_pages );
        if ( mtt_offset < 0 ) {
                DBGC ( hermon, "Hermon %p could not allocate %d MTT entries\n",
                       hermon, num_pages );
                rc = mtt_offset;
                goto err_mtt_offset;
        }
        mtt_base_addr = ( ( hermon->cap.reserved_mtts + mtt_offset ) *
                          hermon->cap.mtt_entry_size );
        addr = start;

        /* Fill in MTT structure */
        mtt->mtt_offset = mtt_offset;
        mtt->num_pages = num_pages;
        mtt->mtt_base_addr = mtt_base_addr;
        mtt->page_offset = page_offset;

        /* Construct and issue WRITE_MTT commands */
        for ( i = 0 ; i < num_pages ; i++ ) {
                memset ( &write_mtt, 0, sizeof ( write_mtt ) );
                MLX_FILL_1 ( &write_mtt.mtt_base_addr, 1,
                             value, mtt_base_addr );
                MLX_FILL_H ( &write_mtt.mtt, 0, ptag_h, addr );
                MLX_FILL_2 ( &write_mtt.mtt, 1,
                             p, 1,
                             ptag_l, ( addr >> 3 ) );
                if ( ( rc = hermon_cmd_write_mtt ( hermon,
                                                   &write_mtt ) ) != 0 ) {
                        DBGC ( hermon, "Hermon %p could not write MTT at %x\n",
                               hermon, mtt_base_addr );
                        goto err_write_mtt;
                }
                addr += HERMON_PAGE_SIZE;
                mtt_base_addr += hermon->cap.mtt_entry_size;
        }

        DBGC ( hermon, "Hermon %p MTT entries [%#x,%#x] for "
               "[%08lx,%08lx,%08lx,%08lx)\n", hermon, mtt->mtt_offset,
               ( mtt->mtt_offset + mtt->num_pages - 1 ), start,
               ( start + page_offset ), ( start + len ), addr );

        return 0;

 err_write_mtt:
        hermon_bitmask_free ( hermon->mtt_inuse, mtt_offset, num_pages );
 err_mtt_offset:
        return rc;
}
static void hermon_free_mtt ( struct hermon hermon,
struct hermon_mtt mtt 
) [static]

Free MTT entries.

Parameters:
hermonHermon device
mttMTT descriptor

Definition at line 694 of file hermon.c.

References DBGC, hermon_bitmask_free(), hermon::mtt_inuse, hermon_mtt::mtt_offset, and hermon_mtt::num_pages.

Referenced by hermon_create_cq(), hermon_create_eq(), hermon_create_qp(), hermon_destroy_cq(), hermon_destroy_eq(), and hermon_destroy_qp().

                                                       {

        DBGC ( hermon, "Hermon %p MTT entries [%#x,%#x] freed\n",
               hermon, mtt->mtt_offset,
               ( mtt->mtt_offset + mtt->num_pages - 1 ) );
        hermon_bitmask_free ( hermon->mtt_inuse, mtt->mtt_offset,
                              mtt->num_pages );
}
static int hermon_mod_stat_cfg ( struct hermon hermon,
unsigned int  port,
unsigned int  mode,
unsigned int  offset,
struct hermonprm_mod_stat_cfg *  stat_cfg 
) [static]

Query or modify static configuration.

Parameters:
hermonHermon device
portPort
modeCommand mode
offsetOffset within static configuration
stat_cfgStatic configuration
Return values:
rcReturn status code

Definition at line 731 of file hermon.c.

References assert, be32_to_cpu, hermon_cmd_mod_stat_cfg(), memset(), MLX_FILL_2, and rc.

Referenced by hermon_bofm_harvest(), and hermon_bofm_update().

                                                                           {
        struct hermonprm_scalar_parameter *portion =
                ( ( void * ) &stat_cfg->u.bytes[offset] );
        struct hermonprm_mod_stat_cfg_input_mod mod;
        int rc;

        /* Sanity check */
        assert ( ( offset % sizeof ( *portion ) ) == 0 );

        /* Construct input modifier */
        memset ( &mod, 0, sizeof ( mod ) );
        MLX_FILL_2 ( &mod, 0,
                     portnum, port,
                     offset, offset );

        /* Issue command */
        if ( ( rc = hermon_cmd_mod_stat_cfg ( hermon, mode,
                                              be32_to_cpu ( mod.u.dwords[0] ),
                                              portion ) ) != 0 )
                return rc;

        return 0;
}
static int hermon_mad ( struct ib_device ibdev,
union ib_mad mad 
) [static]

Issue management datagram.

Parameters:
ibdevInfiniband device
madManagement datagram
Return values:
rcReturn status code

Definition at line 771 of file hermon.c.

References DBGC, EIO, ib_mad::hdr, hermon_cmd_mad_ifc(), ib_get_drvdata(), linker_assert, hermonprm_mad::mad, memcpy(), ntohs, ib_device::port, rc, ib_mad_hdr::status, and strerror().

Referenced by hermon_ib_open(), hermon_inform_sma(), hermon_poll_eq(), hermon_register_ibdev(), and hermon_state_change_ibdev().

                                                                     {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        union hermonprm_mad mad_ifc;
        int rc;

        linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ),
                        mad_size_mismatch );

        /* Copy in request packet */
        memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) );

        /* Issue MAD */
        if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
                                         &mad_ifc ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not issue MAD IFC: "
                       "%s\n", hermon, ibdev->port, strerror ( rc ) );
                return rc;
        }

        /* Copy out reply packet */
        memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) );

        if ( mad->hdr.status != 0 ) {
                DBGC ( hermon, "Hermon %p port %d MAD IFC status %04x\n",
                       hermon, ibdev->port, ntohs ( mad->hdr.status ) );
                return -EIO;
        }
        return 0;
}
static int hermon_dump_cqctx ( struct hermon hermon,
struct ib_completion_queue cq 
) [static]

Dump completion queue context (for debugging only)

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

Definition at line 816 of file hermon.c.

References DBGC, DBGC_HDA, hermon_cmd_query_cq(), memset(), rc, and strerror().

                                                                            {
        struct hermonprm_completion_queue_context cqctx;
        int rc;

        memset ( &cqctx, 0, sizeof ( cqctx ) );
        if ( ( rc = hermon_cmd_query_cq ( hermon, cq->cqn, &cqctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p CQN %#lx QUERY_CQ failed: %s\n",
                       hermon, cq->cqn, strerror ( rc ) );
                return rc;
        }
        DBGC ( hermon, "Hermon %p CQN %#lx context:\n", hermon, cq->cqn );
        DBGC_HDA ( hermon, 0, &cqctx, sizeof ( cqctx ) );

        return 0;
}
static int hermon_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 839 of file hermon.c.

References barrier, c_eqn, hermon::cap, hermon::cq_inuse, hermon_completion_queue::cqe, hermon_completion_queue::cqe_size, ib_completion_queue::cqn, DBGC, hermon_completion_queue::doorbell, ENOMEM, hermon::eq, hermon_event_queue::eqn, fls, free, free_dma(), hermon_alloc_mtt(), hermon_bitmask_alloc(), hermon_bitmask_free(), hermon_cmd_sw2hw_cq(), hermon_free_mtt(), HERMON_MAX_CQS, HERMON_UAR_NON_EQ_PAGE, ib_cq_set_drvdata(), ib_get_drvdata(), malloc_dma(), memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_H, hermon_completion_queue::mtt, hermon_mtt::mtt_base_addr, hermonprm_completion_entry::normal, ib_completion_queue::num_cqes, owner, hermon_mtt::page_offset, page_offset, rc, hermon_dev_cap::reserved_cqs, st, strerror(), virt_to_phys(), and zalloc().

                                                               {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_completion_queue *hermon_cq;
        struct hermonprm_completion_queue_context cqctx;
        int cqn_offset;
        unsigned int i;
        int rc;

        /* Find a free completion queue number */
        cqn_offset = hermon_bitmask_alloc ( hermon->cq_inuse,
                                            HERMON_MAX_CQS, 1 );
        if ( cqn_offset < 0 ) {
                DBGC ( hermon, "Hermon %p out of completion queues\n",
                       hermon );
                rc = cqn_offset;
                goto err_cqn_offset;
        }
        cq->cqn = ( hermon->cap.reserved_cqs + cqn_offset );

        /* Allocate control structures */
        hermon_cq = zalloc ( sizeof ( *hermon_cq ) );
        if ( ! hermon_cq ) {
                rc = -ENOMEM;
                goto err_hermon_cq;
        }

        /* Allocate doorbell */
        hermon_cq->doorbell = malloc_dma ( sizeof ( hermon_cq->doorbell[0] ),
                                           sizeof ( hermon_cq->doorbell[0] ) );
        if ( ! hermon_cq->doorbell ) {
                rc = -ENOMEM;
                goto err_doorbell;
        }
        memset ( hermon_cq->doorbell, 0, sizeof ( hermon_cq->doorbell[0] ) );

        /* Allocate completion queue itself */
        hermon_cq->cqe_size = ( cq->num_cqes * sizeof ( hermon_cq->cqe[0] ) );
        hermon_cq->cqe = malloc_dma ( hermon_cq->cqe_size,
                                      sizeof ( hermon_cq->cqe[0] ) );
        if ( ! hermon_cq->cqe ) {
                rc = -ENOMEM;
                goto err_cqe;
        }
        memset ( hermon_cq->cqe, 0, hermon_cq->cqe_size );
        for ( i = 0 ; i < cq->num_cqes ; i++ ) {
                MLX_FILL_1 ( &hermon_cq->cqe[i].normal, 7, owner, 1 );
        }
        barrier();

        /* Allocate MTT entries */
        if ( ( rc = hermon_alloc_mtt ( hermon, hermon_cq->cqe,
                                       hermon_cq->cqe_size,
                                       &hermon_cq->mtt ) ) != 0 )
                goto err_alloc_mtt;

        /* Hand queue over to hardware */
        memset ( &cqctx, 0, sizeof ( cqctx ) );
        MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
        MLX_FILL_1 ( &cqctx, 2,
                     page_offset, ( hermon_cq->mtt.page_offset >> 5 ) );
        MLX_FILL_2 ( &cqctx, 3,
                     usr_page, HERMON_UAR_NON_EQ_PAGE,
                     log_cq_size, fls ( cq->num_cqes - 1 ) );
        MLX_FILL_1 ( &cqctx, 5, c_eqn, hermon->eq.eqn );
        MLX_FILL_H ( &cqctx, 6, mtt_base_addr_h,
                     hermon_cq->mtt.mtt_base_addr );
        MLX_FILL_1 ( &cqctx, 7, mtt_base_addr_l,
                     ( hermon_cq->mtt.mtt_base_addr >> 3 ) );
        MLX_FILL_H ( &cqctx, 14, db_record_addr_h,
                     virt_to_phys ( hermon_cq->doorbell ) );
        MLX_FILL_1 ( &cqctx, 15, db_record_addr_l,
                     ( virt_to_phys ( hermon_cq->doorbell ) >> 3 ) );
        if ( ( rc = hermon_cmd_sw2hw_cq ( hermon, cq->cqn, &cqctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p CQN %#lx SW2HW_CQ failed: %s\n",
                       hermon, cq->cqn, strerror ( rc ) );
                goto err_sw2hw_cq;
        }

        DBGC ( hermon, "Hermon %p CQN %#lx ring [%08lx,%08lx), doorbell "
               "%08lx\n", hermon, cq->cqn, virt_to_phys ( hermon_cq->cqe ),
               ( virt_to_phys ( hermon_cq->cqe ) + hermon_cq->cqe_size ),
               virt_to_phys ( hermon_cq->doorbell ) );
        ib_cq_set_drvdata ( cq, hermon_cq );
        return 0;

 err_sw2hw_cq:
        hermon_free_mtt ( hermon, &hermon_cq->mtt );
 err_alloc_mtt:
        free_dma ( hermon_cq->cqe, hermon_cq->cqe_size );
 err_cqe:
        free_dma ( hermon_cq->doorbell, sizeof ( hermon_cq->doorbell[0] ) );
 err_doorbell:
        free ( hermon_cq );
 err_hermon_cq:
        hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 );
 err_cqn_offset:
        return rc;
}
static void hermon_destroy_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
) [static]

Destroy completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 945 of file hermon.c.

References hermon::cap, hermon::cq_inuse, hermon_completion_queue::cqe, hermon_completion_queue::cqe_size, ib_completion_queue::cqn, DBGC, hermon_completion_queue::doorbell, free, free_dma(), hermon_bitmask_free(), hermon_cmd_hw2sw_cq(), hermon_free_mtt(), ib_cq_get_drvdata(), ib_cq_set_drvdata(), ib_get_drvdata(), hermon_completion_queue::mtt, NULL, rc, hermon_dev_cap::reserved_cqs, and strerror().

                                                                 {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
        struct hermonprm_completion_queue_context cqctx;
        int cqn_offset;
        int rc;

        /* Take ownership back from hardware */
        if ( ( rc = hermon_cmd_hw2sw_cq ( hermon, cq->cqn, &cqctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p CQN %#lx FATAL HW2SW_CQ failed: "
                       "%s\n", hermon, cq->cqn, strerror ( rc ) );
                /* Leak memory and return; at least we avoid corruption */
                return;
        }

        /* Free MTT entries */
        hermon_free_mtt ( hermon, &hermon_cq->mtt );

        /* Free memory */
        free_dma ( hermon_cq->cqe, hermon_cq->cqe_size );
        free_dma ( hermon_cq->doorbell, sizeof ( hermon_cq->doorbell[0] ) );
        free ( hermon_cq );

        /* Mark queue number as free */
        cqn_offset = ( cq->cqn - hermon->cap.reserved_cqs );
        hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 );

        ib_cq_set_drvdata ( cq, NULL );
}
static int hermon_alloc_qpn ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Assign queue pair number.

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

Definition at line 990 of file hermon.c.

References DBGC, ENOTSUP, hermon_bitmask_alloc(), HERMON_MAX_QPS, HERMON_PORT_BASE, HERMON_QPN_RANDOM_MASK, ib_get_drvdata(), IB_QPT_ETH, IB_QPT_GSI, IB_QPT_RC, IB_QPT_SMI, IB_QPT_UD, ib_device::port, hermon::qp_inuse, ib_queue_pair::qpn, hermon::qpn_base, random(), hermon::special_qpn_base, and ib_queue_pair::type.

Referenced by hermon_create_qp().

                                                         {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        unsigned int port_offset;
        int qpn_offset;

        /* Calculate queue pair number */
        port_offset = ( ibdev->port - HERMON_PORT_BASE );

        switch ( qp->type ) {
        case IB_QPT_SMI:
                qp->qpn = ( hermon->special_qpn_base + port_offset );
                return 0;
        case IB_QPT_GSI:
                qp->qpn = ( hermon->special_qpn_base + 2 + port_offset );
                return 0;
        case IB_QPT_UD:
        case IB_QPT_RC:
        case IB_QPT_ETH:
                /* Find a free queue pair number */
                qpn_offset = hermon_bitmask_alloc ( hermon->qp_inuse,
                                                    HERMON_MAX_QPS, 1 );
                if ( qpn_offset < 0 ) {
                        DBGC ( hermon, "Hermon %p out of queue pairs\n",
                               hermon );
                        return qpn_offset;
                }
                qp->qpn = ( ( random() & HERMON_QPN_RANDOM_MASK ) |
                            ( hermon->qpn_base + qpn_offset ) );
                return 0;
        default:
                DBGC ( hermon, "Hermon %p unsupported QP type %d\n",
                       hermon, qp->type );
                return -ENOTSUP;
        }
}
static void hermon_free_qpn ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Free queue pair number.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 1033 of file hermon.c.

References hermon_bitmask_free(), HERMON_QPN_RANDOM_MASK, ib_get_drvdata(), hermon::qp_inuse, ib_queue_pair::qpn, and hermon::qpn_base.

Referenced by hermon_create_qp(), and hermon_destroy_qp().

                                                         {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        int qpn_offset;

        qpn_offset = ( ( qp->qpn & ~HERMON_QPN_RANDOM_MASK )
                       - hermon->qpn_base );
        if ( qpn_offset >= 0 )
                hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 );
}
static unsigned int hermon_rate ( struct ib_address_vector av) [static]

Calculate transmission rate.

Parameters:
avAddress vector
Return values:
hermon_rateHermon rate

Definition at line 1050 of file hermon.c.

References IB_RATE_120, IB_RATE_2_5, and ib_address_vector::rate.

Referenced by hermon_fill_mlx_send_wqe(), hermon_fill_ud_send_wqe(), and hermon_modify_qp().

                                                                 {
        return ( ( ( av->rate >= IB_RATE_2_5 ) && ( av->rate <= IB_RATE_120 ) )
                 ? ( av->rate + 5 ) : 0 );
}
static unsigned int hermon_sched_queue ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Calculate schedule queue.

Parameters:
ibdevInfiniband device
qpQueue pair
Return values:
sched_queueSchedule queue

Definition at line 1062 of file hermon.c.

References HERMON_SCHED_DEFAULT, HERMON_SCHED_QP0, IB_QPT_SMI, ib_device::port, and ib_queue_pair::type.

Referenced by hermon_modify_qp().

                                                                    {
        return ( ( ( qp->type == IB_QPT_SMI ) ?
                   HERMON_SCHED_QP0 : HERMON_SCHED_DEFAULT ) |
                 ( ( ibdev->port - 1 ) << 6 ) );
}
static int hermon_dump_qpctx ( struct hermon hermon,
struct ib_queue_pair qp 
) [static]

Dump queue pair context (for debugging only)

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

Definition at line 1086 of file hermon.c.

References DBGC, DBGC_HDA, hermon_cmd_query_qp(), memset(), rc, and strerror().

                                                                      {
        struct hermonprm_qp_ee_state_transitions qpctx;
        int rc;

        memset ( &qpctx, 0, sizeof ( qpctx ) );
        if ( ( rc = hermon_cmd_query_qp ( hermon, qp->qpn, &qpctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p QPN %#lx QUERY_QP failed: %s\n",
                       hermon, qp->qpn, strerror ( rc ) );
                return rc;
        }
        DBGC ( hermon, "Hermon %p QPN %#lx context:\n", hermon, qp->qpn );
        DBGC_HDA ( hermon, 0, &qpctx.u.dwords[2], ( sizeof ( qpctx ) - 8 ) );

        return 0;
}
static int hermon_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 1109 of file hermon.c.

References ib_work_queue::cq, ib_completion_queue::cqn, data, hermonprm_recv_wqe::data, DBGC, hermon_send_work_queue::doorbell, hermon_recv_work_queue::doorbell, ENOMEM, fls, free, free_dma(), hermon_recv_work_queue::grh, hermon_recv_work_queue::grh_size, hermon_alloc_mtt(), hermon_alloc_qpn(), hermon_cmd_2rst_qp(), hermon_cmd_rst2init_qp(), HERMON_DB_POST_SND_OFFSET, hermon_free_mtt(), hermon_free_qpn(), HERMON_GLOBAL_PD, HERMON_INVALID_LKEY, HERMON_PAGE_SIZE, HERMON_PM_STATE_MIGRATED, HERMON_QP_ST_INIT, HERMON_UAR_NON_EQ_PAGE, ib_get_drvdata(), ib_qp_set_drvdata(), IB_QPT_GSI, IB_QPT_SMI, IB_QPT_UD, malloc_dma(), memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_4, MLX_FILL_H, hermon_queue_pair::mtt, hermon_mtt::mtt_base_addr, ib_work_queue::num_wqes, hermon_send_work_queue::num_wqes, hermon_mtt::page_offset, ib_queue_pair::qpn, rc, ib_queue_pair::recv, hermon_recv_wqe::recv, hermon_queue_pair::recv, ib_queue_pair::send, hermon_queue_pair::send, hermon_queue_pair::state, strerror(), ib_queue_pair::type, hermon::uar, virt_to_phys(), hermon_send_work_queue::wqe, hermon_recv_work_queue::wqe, hermon_queue_pair::wqe, hermon_send_work_queue::wqe_size, hermon_recv_work_queue::wqe_size, hermon_queue_pair::wqe_size, and zalloc().

                                                         {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_queue_pair *hermon_qp;
        struct hermonprm_qp_ee_state_transitions qpctx;
        struct hermonprm_wqe_segment_data_ptr *data;
        unsigned int i;
        int rc;

        /* Calculate queue pair number */
        if ( ( rc = hermon_alloc_qpn ( ibdev, qp ) ) != 0 )
                goto err_alloc_qpn;

        /* Allocate control structures */
        hermon_qp = zalloc ( sizeof ( *hermon_qp ) );
        if ( ! hermon_qp ) {
                rc = -ENOMEM;
                goto err_hermon_qp;
        }

        /* Allocate doorbells */
        hermon_qp->recv.doorbell =
                malloc_dma ( sizeof ( hermon_qp->recv.doorbell[0] ),
                             sizeof ( hermon_qp->recv.doorbell[0] ) );
        if ( ! hermon_qp->recv.doorbell ) {
                rc = -ENOMEM;
                goto err_recv_doorbell;
        }
        memset ( hermon_qp->recv.doorbell, 0,
                 sizeof ( hermon_qp->recv.doorbell[0] ) );
        hermon_qp->send.doorbell =
                ( hermon->uar + HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE +
                  HERMON_DB_POST_SND_OFFSET );

        /* Allocate work queue buffer */
        hermon_qp->send.num_wqes = ( qp->send.num_wqes /* headroom */ + 1 +
                                ( 2048 / sizeof ( hermon_qp->send.wqe[0] ) ) );
        hermon_qp->send.num_wqes =
                ( 1 << fls ( hermon_qp->send.num_wqes - 1 ) ); /* round up */
        hermon_qp->send.wqe_size = ( hermon_qp->send.num_wqes *
                                     sizeof ( hermon_qp->send.wqe[0] ) );
        hermon_qp->recv.wqe_size = ( qp->recv.num_wqes *
                                     sizeof ( hermon_qp->recv.wqe[0] ) );
        if ( ( qp->type == IB_QPT_SMI ) || ( qp->type == IB_QPT_GSI ) ||
             ( qp->type == IB_QPT_UD ) ) {
                hermon_qp->recv.grh_size = ( qp->recv.num_wqes *
                                             sizeof ( hermon_qp->recv.grh[0] ));
        }
        hermon_qp->wqe_size = ( hermon_qp->send.wqe_size +
                                hermon_qp->recv.wqe_size +
                                hermon_qp->recv.grh_size );
        hermon_qp->wqe = malloc_dma ( hermon_qp->wqe_size,
                                      sizeof ( hermon_qp->send.wqe[0] ) );
        if ( ! hermon_qp->wqe ) {
                rc = -ENOMEM;
                goto err_alloc_wqe;
        }
        hermon_qp->send.wqe = hermon_qp->wqe;
        hermon_qp->recv.wqe = ( hermon_qp->wqe + hermon_qp->send.wqe_size );
        if ( hermon_qp->recv.grh_size ) {
                hermon_qp->recv.grh = ( hermon_qp->wqe +
                                        hermon_qp->send.wqe_size +
                                        hermon_qp->recv.wqe_size );
        }

        /* Initialise work queue entries */
        memset ( hermon_qp->send.wqe, 0xff, hermon_qp->send.wqe_size );
        memset ( hermon_qp->recv.wqe, 0, hermon_qp->recv.wqe_size );
        data = &hermon_qp->recv.wqe[0].recv.data[0];
        for ( i = 0 ; i < ( hermon_qp->recv.wqe_size / sizeof ( *data ) ); i++){
                MLX_FILL_1 ( data, 1, l_key, HERMON_INVALID_LKEY );
                data++;
        }

        /* Allocate MTT entries */
        if ( ( rc = hermon_alloc_mtt ( hermon, hermon_qp->wqe,
                                       hermon_qp->wqe_size,
                                       &hermon_qp->mtt ) ) != 0 ) {
                goto err_alloc_mtt;
        }

        /* Transition queue to INIT state */
        memset ( &qpctx, 0, sizeof ( qpctx ) );
        MLX_FILL_2 ( &qpctx, 2,
                     qpc_eec_data.pm_state, HERMON_PM_STATE_MIGRATED,
                     qpc_eec_data.st, hermon_qp_st[qp->type] );
        MLX_FILL_1 ( &qpctx, 3, qpc_eec_data.pd, HERMON_GLOBAL_PD );
        MLX_FILL_4 ( &qpctx, 4,
                     qpc_eec_data.log_rq_size, fls ( qp->recv.num_wqes - 1 ),
                     qpc_eec_data.log_rq_stride,
                     ( fls ( sizeof ( hermon_qp->recv.wqe[0] ) - 1 ) - 4 ),
                     qpc_eec_data.log_sq_size,
                     fls ( hermon_qp->send.num_wqes - 1 ),
                     qpc_eec_data.log_sq_stride,
                     ( fls ( sizeof ( hermon_qp->send.wqe[0] ) - 1 ) - 4 ) );
        MLX_FILL_1 ( &qpctx, 5,
                     qpc_eec_data.usr_page, HERMON_UAR_NON_EQ_PAGE );
        MLX_FILL_1 ( &qpctx, 33, qpc_eec_data.cqn_snd, qp->send.cq->cqn );
        MLX_FILL_4 ( &qpctx, 38,
                     qpc_eec_data.rre, 1,
                     qpc_eec_data.rwe, 1,
                     qpc_eec_data.rae, 1,
                     qpc_eec_data.page_offset,
                     ( hermon_qp->mtt.page_offset >> 6 ) );
        MLX_FILL_1 ( &qpctx, 41, qpc_eec_data.cqn_rcv, qp->recv.cq->cqn );
        MLX_FILL_H ( &qpctx, 42, qpc_eec_data.db_record_addr_h,
                     virt_to_phys ( hermon_qp->recv.doorbell ) );
        MLX_FILL_1 ( &qpctx, 43, qpc_eec_data.db_record_addr_l,
                     ( virt_to_phys ( hermon_qp->recv.doorbell ) >> 2 ) );
        MLX_FILL_H ( &qpctx, 52, qpc_eec_data.mtt_base_addr_h,
                     hermon_qp->mtt.mtt_base_addr );
        MLX_FILL_1 ( &qpctx, 53, qpc_eec_data.mtt_base_addr_l,
                     ( hermon_qp->mtt.mtt_base_addr >> 3 ) );
        if ( ( rc = hermon_cmd_rst2init_qp ( hermon, qp->qpn,
                                             &qpctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p QPN %#lx RST2INIT_QP failed: %s\n",
                       hermon, qp->qpn, strerror ( rc ) );
                goto err_rst2init_qp;
        }
        hermon_qp->state = HERMON_QP_ST_INIT;

        DBGC ( hermon, "Hermon %p QPN %#lx send ring [%08lx,%08lx), doorbell "
               "%08lx\n", hermon, qp->qpn,
               virt_to_phys ( hermon_qp->send.wqe ),
               ( virt_to_phys ( hermon_qp->send.wqe ) +
                 hermon_qp->send.wqe_size ),
               virt_to_phys ( hermon_qp->send.doorbell ) );
        DBGC ( hermon, "Hermon %p QPN %#lx receive ring [%08lx,%08lx), "
               "doorbell %08lx\n", hermon, qp->qpn,
               virt_to_phys ( hermon_qp->recv.wqe ),
               ( virt_to_phys ( hermon_qp->recv.wqe ) +
                 hermon_qp->recv.wqe_size ),
               virt_to_phys ( hermon_qp->recv.doorbell ) );
        DBGC ( hermon, "Hermon %p QPN %#lx send CQN %#lx receive CQN %#lx\n",
               hermon, qp->qpn, qp->send.cq->cqn, qp->recv.cq->cqn );
        ib_qp_set_drvdata ( qp, hermon_qp );
        return 0;

        hermon_cmd_2rst_qp ( hermon, qp->qpn );
 err_rst2init_qp:
        hermon_free_mtt ( hermon, &hermon_qp->mtt );
 err_alloc_mtt:
        free_dma ( hermon_qp->wqe, hermon_qp->wqe_size );
 err_alloc_wqe:
        free_dma ( hermon_qp->recv.doorbell,
                   sizeof ( hermon_qp->recv.doorbell[0] ) );
 err_recv_doorbell:
        free ( hermon_qp );
 err_hermon_qp:
        hermon_free_qpn ( ibdev, qp );
 err_alloc_qpn:
        return rc;
}
static int hermon_modify_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Modify queue pair.

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

Definition at line 1270 of file hermon.c.

References ib_queue_pair::av, DBGC, ib_address_vector::gid, hermon_cmd_init2rtr_qp(), hermon_cmd_rtr2rts_qp(), hermon_cmd_rts2rts_qp(), HERMON_MTU_2048, HERMON_MTU_ETH, HERMON_QP_OPT_PARAM_QKEY, HERMON_QP_ST_RTR, HERMON_QP_ST_RTS, hermon_rate(), HERMON_RETRY_MAX, hermon_sched_queue(), ib_get_drvdata(), ib_qp_get_drvdata(), IB_QPT_ETH, ib_address_vector::lid, memcpy(), memset(), MLX_FILL_1, MLX_FILL_2, opt_param_mask, ib_work_queue::psn, ib_queue_pair::qkey, ib_address_vector::qpn, ib_queue_pair::qpn, rc, ib_queue_pair::recv, ib_queue_pair::send, hermon_queue_pair::state, strerror(), and ib_queue_pair::type.

                                                         {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
        struct hermonprm_qp_ee_state_transitions qpctx;
        int rc;

        /* Transition queue to RTR state, if applicable */
        if ( hermon_qp->state < HERMON_QP_ST_RTR ) {
                memset ( &qpctx, 0, sizeof ( qpctx ) );
                MLX_FILL_2 ( &qpctx, 4,
                             qpc_eec_data.mtu,
                             ( ( qp->type == IB_QPT_ETH ) ?
                               HERMON_MTU_ETH : HERMON_MTU_2048 ),
                             qpc_eec_data.msg_max, 31 );
                MLX_FILL_1 ( &qpctx, 7,
                             qpc_eec_data.remote_qpn_een, qp->av.qpn );
                MLX_FILL_1 ( &qpctx, 9,
                             qpc_eec_data.primary_address_path.rlid,
                             qp->av.lid );
                MLX_FILL_1 ( &qpctx, 10,
                             qpc_eec_data.primary_address_path.max_stat_rate,
                             hermon_rate ( &qp->av ) );
                memcpy ( &qpctx.u.dwords[12], &qp->av.gid,
                         sizeof ( qp->av.gid ) );
                MLX_FILL_1 ( &qpctx, 16,
                             qpc_eec_data.primary_address_path.sched_queue,
                             hermon_sched_queue ( ibdev, qp ) );
                MLX_FILL_1 ( &qpctx, 39,
                             qpc_eec_data.next_rcv_psn, qp->recv.psn );
                if ( ( rc = hermon_cmd_init2rtr_qp ( hermon, qp->qpn,
                                                     &qpctx ) ) != 0 ) {
                        DBGC ( hermon, "Hermon %p QPN %#lx INIT2RTR_QP failed:"
                               " %s\n", hermon, qp->qpn, strerror ( rc ) );
                        return rc;
                }
                hermon_qp->state = HERMON_QP_ST_RTR;
        }

        /* Transition queue to RTS state */
        if ( hermon_qp->state < HERMON_QP_ST_RTS ) {
                memset ( &qpctx, 0, sizeof ( qpctx ) );
                MLX_FILL_1 ( &qpctx, 10,
                             qpc_eec_data.primary_address_path.ack_timeout,
                             14 /* 4.096us * 2^(14) = 67ms */ );
                MLX_FILL_2 ( &qpctx, 30,
                             qpc_eec_data.retry_count, HERMON_RETRY_MAX,
                             qpc_eec_data.rnr_retry, HERMON_RETRY_MAX );
                MLX_FILL_1 ( &qpctx, 32,
                             qpc_eec_data.next_send_psn, qp->send.psn );
                if ( ( rc = hermon_cmd_rtr2rts_qp ( hermon, qp->qpn,
                                                    &qpctx ) ) != 0 ) {
                        DBGC ( hermon, "Hermon %p QPN %#lx RTR2RTS_QP failed: "
                               "%s\n", hermon, qp->qpn, strerror ( rc ) );
                        return rc;
                }
                hermon_qp->state = HERMON_QP_ST_RTS;
        }

        /* Update parameters in RTS state */
        memset ( &qpctx, 0, sizeof ( qpctx ) );
        MLX_FILL_1 ( &qpctx, 0, opt_param_mask, HERMON_QP_OPT_PARAM_QKEY );
        MLX_FILL_1 ( &qpctx, 44, qpc_eec_data.q_key, qp->qkey );
        if ( ( rc = hermon_cmd_rts2rts_qp ( hermon, qp->qpn, &qpctx ) ) != 0 ){
                DBGC ( hermon, "Hermon %p QPN %#lx RTS2RTS_QP failed: %s\n",
                       hermon, qp->qpn, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void hermon_destroy_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Destroy queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 1348 of file hermon.c.

References DBGC, hermon_recv_work_queue::doorbell, free, free_dma(), hermon_cmd_2rst_qp(), hermon_free_mtt(), hermon_free_qpn(), ib_get_drvdata(), ib_qp_get_drvdata(), ib_qp_set_drvdata(), hermon_queue_pair::mtt, NULL, ib_queue_pair::qpn, rc, hermon_queue_pair::recv, strerror(), hermon_queue_pair::wqe, and hermon_queue_pair::wqe_size.

                                                           {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
        int rc;

        /* Take ownership back from hardware */
        if ( ( rc = hermon_cmd_2rst_qp ( hermon, qp->qpn ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p QPN %#lx FATAL 2RST_QP failed: %s\n",
                       hermon, qp->qpn, strerror ( rc ) );
                /* Leak memory and return; at least we avoid corruption */
                return;
        }

        /* Free MTT entries */
        hermon_free_mtt ( hermon, &hermon_qp->mtt );

        /* Free memory */
        free_dma ( hermon_qp->wqe, hermon_qp->wqe_size );
        free_dma ( hermon_qp->recv.doorbell,
                   sizeof ( hermon_qp->recv.doorbell[0] ) );
        free ( hermon_qp );

        /* Mark queue number as free */
        hermon_free_qpn ( ibdev, qp );

        ib_qp_set_drvdata ( qp, NULL );
}
static unsigned int hermon_fill_nop_send_wqe ( struct ib_device *ibdev  __unused,
struct ib_queue_pair *qp  __unused,
struct ib_address_vector *dest  __unused,
struct io_buffer *iobuf  __unused,
union hermon_send_wqe wqe 
) [static]

Construct UD send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector
iobufI/O buffer
wqeSend work queue entry
Return values:
opcodeControl opcode

Definition at line 1395 of file hermon.c.

References ds, HERMON_OPCODE_NOP, and MLX_FILL_1.

                                                        {

        MLX_FILL_1 ( &wqe->ctrl, 1, ds, ( sizeof ( wqe->ctrl ) / 16 ) );
        MLX_FILL_1 ( &wqe->ctrl, 2, c, 0x03 /* generate completion */ );
        return HERMON_OPCODE_NOP;
}
static unsigned int hermon_fill_ud_send_wqe ( struct ib_device ibdev,
struct ib_queue_pair *qp  __unused,
struct ib_address_vector dest,
struct io_buffer iobuf,
union hermon_send_wqe wqe 
) [static]

Construct UD send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector
iobufI/O buffer
wqeSend work queue entry
Return values:
opcodeControl opcode

Definition at line 1417 of file hermon.c.

References byte_count, hermonprm_ud_send_wqe::ctrl, io_buffer::data, data, hermonprm_ud_send_wqe::data, ds, ib_address_vector::gid, ib_address_vector::gid_present, HERMON_GLOBAL_PD, HERMON_OPCODE_SEND, hermon_rate(), ib_get_drvdata(), iob_len(), ib_address_vector::lid, hermon::lkey, memcpy(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_H, offsetof, ib_device::port, ib_address_vector::qkey, ib_address_vector::qpn, ib_address_vector::sl, hermonprm_ud_send_wqe::ud, hermon_send_wqe::ud, and virt_to_bus().

                                                       {
        struct hermon *hermon = ib_get_drvdata ( ibdev );

        MLX_FILL_1 ( &wqe->ud.ctrl, 1, ds,
                     ( ( offsetof ( typeof ( wqe->ud ), data[1] ) / 16 ) ) );
        MLX_FILL_1 ( &wqe->ud.ctrl, 2, c, 0x03 /* generate completion */ );
        MLX_FILL_2 ( &wqe->ud.ud, 0,
                     ud_address_vector.pd, HERMON_GLOBAL_PD,
                     ud_address_vector.port_number, ibdev->port );
        MLX_FILL_2 ( &wqe->ud.ud, 1,
                     ud_address_vector.rlid, dest->lid,
                     ud_address_vector.g, dest->gid_present );
        MLX_FILL_1 ( &wqe->ud.ud, 2,
                     ud_address_vector.max_stat_rate, hermon_rate ( dest ) );
        MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl );
        memcpy ( &wqe->ud.ud.u.dwords[4], &dest->gid, sizeof ( dest->gid ) );
        MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, dest->qpn );
        MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->qkey );
        MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) );
        MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, hermon->lkey );
        MLX_FILL_H ( &wqe->ud.data[0], 2,
                     local_address_h, virt_to_bus ( iobuf->data ) );
        MLX_FILL_1 ( &wqe->ud.data[0], 3,
                     local_address_l, virt_to_bus ( iobuf->data ) );
        return HERMON_OPCODE_SEND;
}
static unsigned int hermon_fill_mlx_send_wqe ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_address_vector dest,
struct io_buffer iobuf,
union hermon_send_wqe wqe 
) [static]

Construct MLX send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector
iobufI/O buffer
wqeSend work queue entry
Return values:
opcodeControl opcode

Definition at line 1459 of file hermon.c.

References byte_count, hermonprm_mlx_send_wqe::ctrl, io_buffer::data, data, hermonprm_mlx_send_wqe::data, ds, ib_queue_pair::ext_qpn, hermonprm_mlx_send_wqe::headers, HERMON_OPCODE_SEND, hermon_rate(), ib_get_drvdata(), ib_push(), IB_QPN_SMI, iob_len(), iob_populate(), iob_reserve, ib_address_vector::lid, hermon::lkey, hermon_send_wqe::mlx, MLX_FILL_1, MLX_FILL_5, MLX_FILL_H, offsetof, rlid, and virt_to_bus().

                                                        {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct io_buffer headers;

        /* Construct IB headers */
        iob_populate ( &headers, &wqe->mlx.headers, 0,
                       sizeof ( wqe->mlx.headers ) );
        iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) );
        ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest );

        /* Fill work queue entry */
        MLX_FILL_1 ( &wqe->mlx.ctrl, 1, ds,
                     ( ( offsetof ( typeof ( wqe->mlx ), data[2] ) / 16 ) ) );
        MLX_FILL_5 ( &wqe->mlx.ctrl, 2,
                     c, 0x03 /* generate completion */,
                     icrc, 0 /* generate ICRC */,
                     max_statrate, hermon_rate ( dest ),
                     slr, 0,
                     v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) );
        MLX_FILL_1 ( &wqe->mlx.ctrl, 3, rlid, dest->lid );
        MLX_FILL_1 ( &wqe->mlx.data[0], 0,
                     byte_count, iob_len ( &headers ) );
        MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, hermon->lkey );
        MLX_FILL_H ( &wqe->mlx.data[0], 2,
                     local_address_h, virt_to_bus ( headers.data ) );
        MLX_FILL_1 ( &wqe->mlx.data[0], 3,
                     local_address_l, virt_to_bus ( headers.data ) );
        MLX_FILL_1 ( &wqe->mlx.data[1], 0,
                     byte_count, ( iob_len ( iobuf ) + 4 /* ICRC */ ) );
        MLX_FILL_1 ( &wqe->mlx.data[1], 1, l_key, hermon->lkey );
        MLX_FILL_H ( &wqe->mlx.data[1], 2,
                     local_address_h, virt_to_bus ( iobuf->data ) );
        MLX_FILL_1 ( &wqe->mlx.data[1], 3,
                     local_address_l, virt_to_bus ( iobuf->data ) );
        return HERMON_OPCODE_SEND;
}
static unsigned int hermon_fill_rc_send_wqe ( struct ib_device ibdev,
struct ib_queue_pair *qp  __unused,
struct ib_address_vector *dest  __unused,
struct io_buffer iobuf,
union hermon_send_wqe wqe 
) [static]

Construct RC send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector
iobufI/O buffer
wqeSend work queue entry
Return values:
opcodeControl opcode

Definition at line 1511 of file hermon.c.

References byte_count, hermonprm_rc_send_wqe::ctrl, io_buffer::data, data, hermonprm_rc_send_wqe::data, ds, HERMON_OPCODE_SEND, ib_get_drvdata(), iob_len(), hermon::lkey, MLX_FILL_1, MLX_FILL_H, offsetof, hermon_send_wqe::rc, and virt_to_bus().

                                                       {
        struct hermon *hermon = ib_get_drvdata ( ibdev );

        MLX_FILL_1 ( &wqe->rc.ctrl, 1, ds,
                     ( ( offsetof ( typeof ( wqe->rc ), data[1] ) / 16 ) ) );
        MLX_FILL_1 ( &wqe->rc.ctrl, 2, c, 0x03 /* generate completion */ );
        MLX_FILL_1 ( &wqe->rc.data[0], 0, byte_count, iob_len ( iobuf ) );
        MLX_FILL_1 ( &wqe->rc.data[0], 1, l_key, hermon->lkey );
        MLX_FILL_H ( &wqe->rc.data[0], 2,
                     local_address_h, virt_to_bus ( iobuf->data ) );
        MLX_FILL_1 ( &wqe->rc.data[0], 3,
                     local_address_l, virt_to_bus ( iobuf->data ) );
        return HERMON_OPCODE_SEND;
}
static unsigned int hermon_fill_eth_send_wqe ( struct ib_device ibdev,
struct ib_queue_pair *qp  __unused,
struct ib_address_vector *dest  __unused,
struct io_buffer iobuf,
union hermon_send_wqe wqe 
) [static]

Construct Ethernet send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector
iobufI/O buffer
wqeSend work queue entry
Return values:
opcodeControl opcode

Definition at line 1541 of file hermon.c.

References byte_count, hermonprm_eth_send_wqe::ctrl, io_buffer::data, data, hermonprm_eth_send_wqe::data, ds, hermon_send_wqe::eth, HERMON_OPCODE_SEND, ib_get_drvdata(), iob_len(), hermon::lkey, hermon_send_wqe::mlx, MLX_FILL_1, MLX_FILL_2, MLX_FILL_H, offsetof, and virt_to_bus().

                                                        {
        struct hermon *hermon = ib_get_drvdata ( ibdev );

        /* Fill work queue entry */
        MLX_FILL_1 ( &wqe->eth.ctrl, 1, ds,
                     ( ( offsetof ( typeof ( wqe->mlx ), data[1] ) / 16 ) ) );
        MLX_FILL_2 ( &wqe->eth.ctrl, 2,
                     c, 0x03 /* generate completion */,
                     s, 1 /* inhibit ICRC */ );
        MLX_FILL_1 ( &wqe->eth.data[0], 0,
                     byte_count, iob_len ( iobuf ) );
        MLX_FILL_1 ( &wqe->eth.data[0], 1, l_key, hermon->lkey );
        MLX_FILL_H ( &wqe->eth.data[0], 2,
                     local_address_h, virt_to_bus ( iobuf->data ) );
        MLX_FILL_1 ( &wqe->eth.data[0], 3,
                     local_address_l, virt_to_bus ( iobuf->data ) );
        return HERMON_OPCODE_SEND;
}
static int hermon_post_send ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_address_vector dest,
struct io_buffer iobuf 
) [static]

Post send work queue entry.

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

Definition at line 1587 of file hermon.c.

References assert, barrier, DBGC, DBGCP, DBGCP_HDA, dest, hermon_send_work_queue::doorbell, hermonprm_doorbell_register::dword, ENOBUFS, hermon_fill_send_wqe, ib_get_drvdata(), ib_qp_get_drvdata(), ib_work_queue::iobufs, memset(), MLX_FILL_1, MLX_FILL_2, ib_work_queue::next_idx, NULL, ib_work_queue::num_wqes, hermon_send_work_queue::num_wqes, opcode, owner, qp, ib_queue_pair::qpn, ib_queue_pair::send, hermonprm_doorbell_register::send, hermon_queue_pair::send, ib_queue_pair::type, virt_to_phys(), hermon_send_work_queue::wqe, and writel().

                                                        {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
        struct ib_work_queue *wq = &qp->send;
        struct hermon_send_work_queue *hermon_send_wq = &hermon_qp->send;
        union hermon_send_wqe *wqe;
        union hermonprm_doorbell_register db_reg;
        unsigned long wqe_idx_mask;
        unsigned long wqe_idx;
        unsigned int owner;
        unsigned int opcode;

        /* Allocate work queue entry */
        wqe_idx = ( wq->next_idx & ( hermon_send_wq->num_wqes - 1 ) );
        owner = ( ( wq->next_idx & hermon_send_wq->num_wqes ) ? 1 : 0 );
        wqe_idx_mask = ( wq->num_wqes - 1 );
        if ( wq->iobufs[ wqe_idx & wqe_idx_mask ] ) {
                DBGC ( hermon, "Hermon %p QPN %#lx send queue full",
                       hermon, qp->qpn );
                return -ENOBUFS;
        }
        wq->iobufs[ wqe_idx & wqe_idx_mask ] = iobuf;
        wqe = &hermon_send_wq->wqe[wqe_idx];

        /* Construct work queue entry */
        memset ( ( ( ( void * ) wqe ) + 4 /* avoid ctrl.owner */ ), 0,
                   ( sizeof ( *wqe ) - 4 ) );
        assert ( qp->type < ( sizeof ( hermon_fill_send_wqe ) /
                              sizeof ( hermon_fill_send_wqe[0] ) ) );
        assert ( hermon_fill_send_wqe[qp->type] != NULL );
        opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, dest, iobuf, wqe );
        barrier();
        MLX_FILL_2 ( &wqe->ctrl, 0,
                     opcode, opcode,
                     owner, owner );
        DBGCP ( hermon, "Hermon %p QPN %#lx posting send WQE %#lx:\n",
                hermon, qp->qpn, wqe_idx );
        DBGCP_HDA ( hermon, virt_to_phys ( wqe ), wqe, sizeof ( *wqe ) );

        /* Ring doorbell register */
        MLX_FILL_1 ( &db_reg.send, 0, qn, qp->qpn );
        barrier();
        writel ( db_reg.dword[0], hermon_send_wq->doorbell );

        /* Update work queue's index */
        wq->next_idx++;

        return 0;
}
static int hermon_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 1648 of file hermon.c.

References barrier, byte_count, io_buffer::data, data, hermonprm_recv_wqe::data, DBGC, hermon_recv_work_queue::doorbell, ENOBUFS, grh, hermon_recv_work_queue::grh, ib_get_drvdata(), ib_qp_get_drvdata(), iob_tailroom(), ib_work_queue::iobufs, hermon::lkey, MLX_FILL_1, MLX_FILL_H, ib_work_queue::next_idx, ib_work_queue::num_wqes, ib_queue_pair::qpn, ib_queue_pair::recv, hermon_recv_wqe::recv, hermon_queue_pair::recv, virt_to_bus(), and hermon_recv_work_queue::wqe.

                                                        {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
        struct ib_work_queue *wq = &qp->recv;
        struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv;
        struct hermonprm_recv_wqe *wqe;
        struct hermonprm_wqe_segment_data_ptr *data;
        struct ib_global_route_header *grh;
        unsigned int wqe_idx_mask;

        /* Allocate work queue entry */
        wqe_idx_mask = ( wq->num_wqes - 1 );
        if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
                DBGC ( hermon, "Hermon %p QPN %#lx receive queue full",
                       hermon, qp->qpn );
                return -ENOBUFS;
        }
        wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
        wqe = &hermon_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv;

        /* Construct work queue entry */
        data = &wqe->data[0];
        if ( hermon_qp->recv.grh ) {
                grh = &hermon_qp->recv.grh[wq->next_idx & wqe_idx_mask];
                MLX_FILL_1 ( data, 0, byte_count, sizeof ( *grh ) );
                MLX_FILL_1 ( data, 1, l_key, hermon->lkey );
                MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( grh ) );
                MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( grh ) );
                data++;
        }
        MLX_FILL_1 ( data, 0, byte_count, iob_tailroom ( iobuf ) );
        MLX_FILL_1 ( data, 1, l_key, hermon->lkey );
        MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( iobuf->data ) );
        MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( iobuf->data ) );

        /* Update work queue's index */
        wq->next_idx++;

        /* Update doorbell record */
        barrier();
        MLX_FILL_1 ( hermon_recv_wq->doorbell, 0, receive_wqe_counter,
                     ( wq->next_idx & 0xffff ) );

        return 0;
}
static int hermon_complete ( struct ib_device ibdev,
struct ib_completion_queue cq,
union hermonprm_completion_entry cqe 
) [static]

Handle completion.

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

Definition at line 1704 of file hermon.c.

References assert, ib_queue_pair::av, byte_cnt, ib_completion_queue::cqn, DBGC, DBGCP, DBGCP_HDA, ib_global_route_header::dgid, EINVAL, EIO, hermonprm_completion_entry::error, ib_address_vector::gid, ib_address_vector::gid_present, grh, hermon_recv_work_queue::grh, HERMON_OPCODE_RECV_ERROR, HERMON_OPCODE_SEND_ERROR, ib_complete_recv(), ib_complete_send(), ib_find_wq(), ib_get_drvdata(), ib_qp_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, len, ib_address_vector::lid, memcpy(), memset(), MLX_GET, hermonprm_completion_entry::normal, NULL, ib_work_queue::num_wqes, opcode, ib_work_queue::qp, qp, ib_address_vector::qpn, ib_queue_pair::qpn, qpn, rc, hermon_queue_pair::recv, ib_global_route_header::sgid, ib_address_vector::sl, sl, syndrome, ib_queue_pair::type, virt_to_phys(), ib_address_vector::vlan, ib_address_vector::vlan_present, and wqe_counter.

Referenced by hermon_poll_cq().

                                                                     {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_queue_pair *hermon_qp;
        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;
        struct ib_global_route_header *grh;
        struct ib_address_vector *source;
        unsigned int opcode;
        unsigned long qpn;
        int is_send;
        unsigned long wqe_idx;
        unsigned long wqe_idx_mask;
        size_t len;
        int rc = 0;

        /* Parse completion */
        qpn = MLX_GET ( &cqe->normal, qpn );
        is_send = MLX_GET ( &cqe->normal, s_r );
        opcode = MLX_GET ( &cqe->normal, opcode );
        if ( opcode >= HERMON_OPCODE_RECV_ERROR ) {
                /* "s" field is not valid for error opcodes */
                is_send = ( opcode == HERMON_OPCODE_SEND_ERROR );
                DBGC ( hermon, "Hermon %p CQN %#lx syndrome %x vendor %x\n",
                       hermon, cq->cqn, MLX_GET ( &cqe->error, syndrome ),
                       MLX_GET ( &cqe->error, vendor_error_syndrome ) );
                rc = -EIO;
                /* Don't return immediately; propagate error to completer */
        }

        /* Identify work queue */
        wq = ib_find_wq ( cq, qpn, is_send );
        if ( ! wq ) {
                DBGC ( hermon, "Hermon %p CQN %#lx unknown %s QPN %#lx\n",
                       hermon, cq->cqn, ( is_send ? "send" : "recv" ), qpn );
                return -EIO;
        }
        qp = wq->qp;
        hermon_qp = ib_qp_get_drvdata ( qp );

        /* Identify work queue entry */
        wqe_idx = MLX_GET ( &cqe->normal, wqe_counter );
        wqe_idx_mask = ( wq->num_wqes - 1 );
        DBGCP ( hermon, "Hermon %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n",
                hermon, cq->cqn, qp->qpn, ( is_send ? "send" : "recv" ),
                wqe_idx );
        DBGCP_HDA ( hermon, virt_to_phys ( cqe ), cqe, sizeof ( *cqe ) );

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

        if ( is_send ) {
                /* Hand off to completion handler */
                ib_complete_send ( ibdev, qp, iobuf, rc );
        } else {
                /* Set received length */
                len = MLX_GET ( &cqe->normal, byte_cnt );
                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:
                        /* Locate corresponding GRH */
                        assert ( hermon_qp->recv.grh != NULL );
                        grh = &hermon_qp->recv.grh[ wqe_idx & wqe_idx_mask ];
                        len -= sizeof ( *grh );
                        /* Construct address vector */
                        source = &recv_source;
                        source->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
                        source->lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
                        source->sl = MLX_GET ( &cqe->normal, sl );
                        recv_dest.gid_present = source->gid_present =
                                MLX_GET ( &cqe->normal, g );
                        memcpy ( &recv_dest.gid, &grh->dgid,
                                 sizeof ( recv_dest.gid ) );
                        memcpy ( &source->gid, &grh->sgid,
                                 sizeof ( source->gid ) );
                        break;
                case IB_QPT_RC:
                        source = &qp->av;
                        break;
                case IB_QPT_ETH:
                        /* Construct address vector */
                        source = &recv_source;
                        source->vlan_present = MLX_GET ( &cqe->normal, vlan );
                        source->vlan = MLX_GET ( &cqe->normal, vid );
                        break;
                default:
                        assert ( 0 );
                        return -EINVAL;
                }
                assert ( len <= iob_tailroom ( iobuf ) );
                iob_put ( iobuf, len );
                /* Hand off to completion handler */
                ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc );
        }

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

Poll completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 1823 of file hermon.c.

References hermon_completion_queue::cqe, ib_completion_queue::cqn, DBGC, DBGC_HDA, hermon_completion_queue::doorbell, hermon_complete(), ib_cq_get_drvdata(), ib_get_drvdata(), MLX_FILL_1, MLX_GET, ib_completion_queue::next_idx, hermonprm_completion_entry::normal, ib_completion_queue::num_cqes, owner, rc, strerror(), and virt_to_phys().

                                                              {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
        union hermonprm_completion_entry *cqe;
        unsigned int cqe_idx_mask;
        int rc;

        while ( 1 ) {
                /* Look for completion entry */
                cqe_idx_mask = ( cq->num_cqes - 1 );
                cqe = &hermon_cq->cqe[cq->next_idx & cqe_idx_mask];
                if ( MLX_GET ( &cqe->normal, owner ) ^
                     ( ( cq->next_idx & cq->num_cqes ) ? 1 : 0 ) ) {
                        /* Entry still owned by hardware; end of poll */
                        break;
                }

                /* Handle completion */
                if ( ( rc = hermon_complete ( ibdev, cq, cqe ) ) != 0 ) {
                        DBGC ( hermon, "Hermon %p CQN %#lx failed to complete:"
                               " %s\n", hermon, cq->cqn, strerror ( rc ) );
                        DBGC_HDA ( hermon, virt_to_phys ( cqe ),
                                   cqe, sizeof ( *cqe ) );
                }

                /* Update completion queue's index */
                cq->next_idx++;

                /* Update doorbell record */
                MLX_FILL_1 ( hermon_cq->doorbell, 0, update_ci,
                             ( cq->next_idx & 0x00ffffffUL ) );
        }
}
static int hermon_create_eq ( struct hermon hermon) [static]

Create event queue.

Parameters:
hermonHermon device
Return values:
rcReturn status code

Definition at line 1871 of file hermon.c.

References barrier, hermon::cap, DBGC, hermon_event_queue::doorbell, ENOMEM, hermon::eq, hermon_event_queue::eqe, hermon_event_queue::eqe_size, hermon_event_queue::eqn, fls, free_dma(), hermonprm_event_entry::generic, hermon_alloc_mtt(), hermon_cmd_hw2sw_eq(), hermon_cmd_map_eq(), hermon_cmd_sw2hw_eq(), HERMON_DB_EQ_OFFSET, hermon_free_mtt(), HERMON_MAP_EQ, HERMON_NUM_EQES, malloc_dma(), memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_H, hermon_event_queue::mtt, hermon_mtt::mtt_base_addr, owner, hermon_mtt::page_offset, page_offset, rc, hermon_dev_cap::reserved_eqs, hermon_dev_cap::reserved_uars, st, strerror(), hermon::uar, and virt_to_phys().

Referenced by hermon_start().

                                                      {
        struct hermon_event_queue *hermon_eq = &hermon->eq;
        struct hermonprm_eqc eqctx;
        struct hermonprm_event_mask mask;
        unsigned int i;
        int rc;

        /* Select event queue number */
        hermon_eq->eqn = ( 4 * hermon->cap.reserved_uars );
        if ( hermon_eq->eqn < hermon->cap.reserved_eqs )
                hermon_eq->eqn = hermon->cap.reserved_eqs;

        /* Calculate doorbell address */
        hermon_eq->doorbell =
                ( hermon->uar + HERMON_DB_EQ_OFFSET ( hermon_eq->eqn ) );

        /* Allocate event queue itself */
        hermon_eq->eqe_size =
                ( HERMON_NUM_EQES * sizeof ( hermon_eq->eqe[0] ) );
        hermon_eq->eqe = malloc_dma ( hermon_eq->eqe_size,
                                      sizeof ( hermon_eq->eqe[0] ) );
        if ( ! hermon_eq->eqe ) {
                rc = -ENOMEM;
                goto err_eqe;
        }
        memset ( hermon_eq->eqe, 0, hermon_eq->eqe_size );
        for ( i = 0 ; i < HERMON_NUM_EQES ; i++ ) {
                MLX_FILL_1 ( &hermon_eq->eqe[i].generic, 7, owner, 1 );
        }
        barrier();

        /* Allocate MTT entries */
        if ( ( rc = hermon_alloc_mtt ( hermon, hermon_eq->eqe,
                                       hermon_eq->eqe_size,
                                       &hermon_eq->mtt ) ) != 0 )
                goto err_alloc_mtt;

        /* Hand queue over to hardware */
        memset ( &eqctx, 0, sizeof ( eqctx ) );
        MLX_FILL_2 ( &eqctx, 0,
                     st, 0xa /* "Fired" */,
                     oi, 1 );
        MLX_FILL_1 ( &eqctx, 2,
                     page_offset, ( hermon_eq->mtt.page_offset >> 5 ) );
        MLX_FILL_1 ( &eqctx, 3, log_eq_size, fls ( HERMON_NUM_EQES - 1 ) );
        MLX_FILL_H ( &eqctx, 6, mtt_base_addr_h,
                     hermon_eq->mtt.mtt_base_addr );
        MLX_FILL_1 ( &eqctx, 7, mtt_base_addr_l,
                     ( hermon_eq->mtt.mtt_base_addr >> 3 ) );
        if ( ( rc = hermon_cmd_sw2hw_eq ( hermon, hermon_eq->eqn,
                                          &eqctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p EQN %#lx SW2HW_EQ failed: %s\n",
                       hermon, hermon_eq->eqn, strerror ( rc ) );
                goto err_sw2hw_eq;
        }

        /* Map all events to this event queue */
        memset ( &mask, 0xff, sizeof ( mask ) );
        if ( ( rc = hermon_cmd_map_eq ( hermon,
                                        ( HERMON_MAP_EQ | hermon_eq->eqn ),
                                        &mask ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p EQN %#lx MAP_EQ failed: %s\n",
                       hermon, hermon_eq->eqn, strerror ( rc )  );
                goto err_map_eq;
        }

        DBGC ( hermon, "Hermon %p EQN %#lx ring [%08lx,%08lx), doorbell "
               "%08lx\n", hermon, hermon_eq->eqn,
               virt_to_phys ( hermon_eq->eqe ),
               ( virt_to_phys ( hermon_eq->eqe ) + hermon_eq->eqe_size ),
               virt_to_phys ( hermon_eq->doorbell ) );
        return 0;

 err_map_eq:
        hermon_cmd_hw2sw_eq ( hermon, hermon_eq->eqn, &eqctx );
 err_sw2hw_eq:
        hermon_free_mtt ( hermon, &hermon_eq->mtt );
 err_alloc_mtt:
        free_dma ( hermon_eq->eqe, hermon_eq->eqe_size );
 err_eqe:
        memset ( hermon_eq, 0, sizeof ( *hermon_eq ) );
        return rc;
}
static void hermon_destroy_eq ( struct hermon hermon) [static]

Destroy event queue.

Parameters:
hermonHermon device

Definition at line 1960 of file hermon.c.

References DBGC, hermon::eq, hermon_event_queue::eqe, hermon_event_queue::eqe_size, hermon_event_queue::eqn, free_dma(), hermon_cmd_hw2sw_eq(), hermon_cmd_map_eq(), hermon_free_mtt(), HERMON_UNMAP_EQ, memset(), hermon_event_queue::mtt, rc, and strerror().

Referenced by hermon_start(), and hermon_stop().

                                                        {
        struct hermon_event_queue *hermon_eq = &hermon->eq;
        struct hermonprm_eqc eqctx;
        struct hermonprm_event_mask mask;
        int rc;

        /* Unmap events from event queue */
        memset ( &mask, 0xff, sizeof ( mask ) );
        if ( ( rc = hermon_cmd_map_eq ( hermon,
                                        ( HERMON_UNMAP_EQ | hermon_eq->eqn ),
                                        &mask ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p EQN %#lx FATAL MAP_EQ failed to "
                       "unmap: %s\n", hermon, hermon_eq->eqn, strerror ( rc ) );
                /* Continue; HCA may die but system should survive */
        }

        /* Take ownership back from hardware */
        if ( ( rc = hermon_cmd_hw2sw_eq ( hermon, hermon_eq->eqn,
                                          &eqctx ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p EQN %#lx FATAL HW2SW_EQ failed: %s\n",
                       hermon, hermon_eq->eqn, strerror ( rc ) );
                /* Leak memory and return; at least we avoid corruption */
                return;
        }

        /* Free MTT entries */
        hermon_free_mtt ( hermon, &hermon_eq->mtt );

        /* Free memory */
        free_dma ( hermon_eq->eqe, hermon_eq->eqe_size );
        memset ( hermon_eq, 0, sizeof ( *hermon_eq ) );
}
static void hermon_event_port_state_change ( struct hermon hermon,
union hermonprm_event_entry eqe 
) [static]

Handle port state event.

Parameters:
hermonHermon device
eqePort state change event queue entry

Definition at line 1999 of file hermon.c.

References hermon::cap, data, DBGC, hermonprm_event_entry::generic, MLX_GET, hermon_dev_cap::num_ports, port, hermon::port, hermonprm_event_entry::port_state_change, hermon_port_type::state_change, and hermon_port::type.

Referenced by hermon_poll_eq().

                                                                              {
        unsigned int port;
        int link_up;

        /* Get port and link status */
        port = ( MLX_GET ( &eqe->port_state_change, data.p ) - 1 );
        link_up = ( MLX_GET ( &eqe->generic, event_sub_type ) & 0x04 );
        DBGC ( hermon, "Hermon %p port %d link %s\n", hermon, ( port + 1 ),
               ( link_up ? "up" : "down" ) );

        /* Sanity check */
        if ( port >= hermon->cap.num_ports ) {
                DBGC ( hermon, "Hermon %p port %d does not exist!\n",
                       hermon, ( port + 1 ) );
                return;
        }

        /* Notify device of port state change */
        hermon->port[port].type->state_change ( hermon, &hermon->port[port],
                                                link_up );
}
static void hermon_poll_eq ( struct ib_device ibdev) [static]

Poll event queue.

Parameters:
ibdevInfiniband device

Definition at line 2027 of file hermon.c.

References ci, DBGC, DBGC_HDA, DBGCP, DBGCP_HDA, hermon_event_queue::doorbell, hermonprm_doorbell_register::dword, hermon::eq, hermon_event_queue::eqe, hermon_event_queue::eqn, hermonprm_doorbell_register::event, hermonprm_event_entry::generic, HERMON_EV_PORT_STATE_CHANGE, hermon_event_port_state_change(), hermon_mad(), HERMON_NUM_EQES, ib_get_drvdata(), ib_is_open(), IB_PORT_STATE_DOWN, ib_smc_update(), MLX_FILL_1, MLX_GET, hermon_event_queue::next_idx, owner, ib_device::port_state, virt_to_phys(), and writel().

                                                       {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermon_event_queue *hermon_eq = &hermon->eq;
        union hermonprm_event_entry *eqe;
        union hermonprm_doorbell_register db_reg;
        unsigned int eqe_idx_mask;
        unsigned int event_type;

        /* No event is generated upon reaching INIT, so we must poll
         * separately for link state changes while we remain DOWN.
         */
        if ( ib_is_open ( ibdev ) &&
             ( ibdev->port_state == IB_PORT_STATE_DOWN ) ) {
                ib_smc_update ( ibdev, hermon_mad );
        }

        /* Poll event queue */
        while ( 1 ) {
                /* Look for event entry */
                eqe_idx_mask = ( HERMON_NUM_EQES - 1 );
                eqe = &hermon_eq->eqe[hermon_eq->next_idx & eqe_idx_mask];
                if ( MLX_GET ( &eqe->generic, owner ) ^
                     ( ( hermon_eq->next_idx & HERMON_NUM_EQES ) ? 1 : 0 ) ) {
                        /* Entry still owned by hardware; end of poll */
                        break;
                }
                DBGCP ( hermon, "Hermon %p EQN %#lx event:\n",
                        hermon, hermon_eq->eqn );
                DBGCP_HDA ( hermon, virt_to_phys ( eqe ),
                            eqe, sizeof ( *eqe ) );

                /* Handle event */
                event_type = MLX_GET ( &eqe->generic, event_type );
                switch ( event_type ) {
                case HERMON_EV_PORT_STATE_CHANGE:
                        hermon_event_port_state_change ( hermon, eqe );
                        break;
                default:
                        DBGC ( hermon, "Hermon %p EQN %#lx unrecognised event "
                               "type %#x:\n",
                               hermon, hermon_eq->eqn, event_type );
                        DBGC_HDA ( hermon, virt_to_phys ( eqe ),
                                   eqe, sizeof ( *eqe ) );
                        break;
                }

                /* Update event queue's index */
                hermon_eq->next_idx++;

                /* Ring doorbell */
                MLX_FILL_1 ( &db_reg.event, 0,
                             ci, ( hermon_eq->next_idx & 0x00ffffffUL ) );
                writel ( db_reg.dword[0], hermon_eq->doorbell );
        }
}
static int hermon_map_vpm ( struct hermon hermon,
int(*)(struct hermon *hermon, const struct hermonprm_virtual_physical_mapping *)  map,
uint64_t  va,
physaddr_t  pa,
size_t  len 
) [static]

Map virtual to physical address for firmware usage.

Parameters:
hermonHermon device
mapMapping function
vaVirtual address
paPhysical address
lenLength of region
Return values:
rcReturn status code

Definition at line 2100 of file hermon.c.

References assert, DBG_DISABLE, DBG_ENABLE, DBGC, DBGLVL_EXTRA, DBGLVL_LOG, end, fls, HERMON_PAGE_SIZE, high, len, low, memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_H, rc, size, start, and strerror().

Referenced by hermon_map_icm(), and hermon_start_firmware().

                                                                     {
        struct hermonprm_virtual_physical_mapping mapping;
        physaddr_t start;
        physaddr_t low;
        physaddr_t high;
        physaddr_t end;
        size_t size;
        int rc;

        /* Sanity checks */
        assert ( ( va & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
        assert ( ( pa & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
        assert ( ( len & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
        assert ( len != 0 );

        /* Calculate starting points */
        start = pa;
        end = ( start + len );
        size = ( 1UL << ( fls ( start ^ end ) - 1 ) );
        low = high = ( end & ~( size - 1 ) );
        assert ( start < low );
        assert ( high <= end );

        /* These mappings tend to generate huge volumes of
         * uninteresting debug data, which basically makes it
         * impossible to use debugging otherwise.
         */
        DBG_DISABLE ( DBGLVL_LOG | DBGLVL_EXTRA );

        /* Map blocks in descending order of size */
        while ( size >= HERMON_PAGE_SIZE ) {

                /* Find the next candidate block */
                if ( ( low - size ) >= start ) {
                        low -= size;
                        pa = low;
                } else if ( high <= ( end - size ) ) {
                        pa = high;
                        high += size;
                } else {
                        size >>= 1;
                        continue;
                }
                assert ( ( va & ( size - 1 ) ) == 0 );
                assert ( ( pa & ( size - 1 ) ) == 0 );

                /* Map this block */
                memset ( &mapping, 0, sizeof ( mapping ) );
                MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
                MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
                MLX_FILL_H ( &mapping, 2, pa_h, pa );
                MLX_FILL_2 ( &mapping, 3,
                             log2size, ( ( fls ( size ) - 1 ) - 12 ),
                             pa_l, ( pa >> 12 ) );
                if ( ( rc = map ( hermon, &mapping ) ) != 0 ) {
                        DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
                        DBGC ( hermon, "Hermon %p could not map %08llx+%zx to "
                               "%08lx: %s\n",
                               hermon, va, size, pa, strerror ( rc ) );
                        return rc;
                }
                va += size;
        }
        assert ( low == start );
        assert ( high == end );

        DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
        return 0;
}
static int hermon_start_firmware ( struct hermon hermon) [static]

Start firmware running.

Parameters:
hermonHermon device
Return values:
rcReturn status code

Definition at line 2179 of file hermon.c.

References assert, DBGC, ENOMEM, hermon::firmware_area, hermon::firmware_len, hermon_cmd_map_fa(), hermon_cmd_query_fw(), hermon_cmd_run_fw(), hermon_cmd_unmap_fa(), hermon_map_vpm(), HERMON_PAGE_SIZE, MLX_GET, rc, strerror(), umalloc(), and user_to_phys().

Referenced by hermon_probe(), and hermon_start().

                                                           {
        struct hermonprm_query_fw fw;
        unsigned int fw_pages;
        size_t fw_len;
        physaddr_t fw_base;
        int rc;

        /* Get firmware parameters */
        if ( ( rc = hermon_cmd_query_fw ( hermon, &fw ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not query firmware: %s\n",
                       hermon, strerror ( rc ) );
                goto err_query_fw;
        }
        DBGC ( hermon, "Hermon %p firmware version %d.%d.%d\n", hermon,
               MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
               MLX_GET ( &fw, fw_rev_subminor ) );
        fw_pages = MLX_GET ( &fw, fw_pages );
        DBGC ( hermon, "Hermon %p requires %d pages (%d kB) for firmware\n",
               hermon, fw_pages, ( fw_pages * 4 ) );

        /* Allocate firmware pages and map firmware area */
        fw_len = ( fw_pages * HERMON_PAGE_SIZE );
        if ( ! hermon->firmware_area ) {
                hermon->firmware_len = fw_len;
                hermon->firmware_area = umalloc ( hermon->firmware_len );
                if ( ! hermon->firmware_area ) {
                        rc = -ENOMEM;
                        goto err_alloc_fa;
                }
        } else {
                assert ( hermon->firmware_len == fw_len );
        }
        fw_base = user_to_phys ( hermon->firmware_area, 0 );
        DBGC ( hermon, "Hermon %p firmware area at physical [%08lx,%08lx)\n",
               hermon, fw_base, ( fw_base + fw_len ) );
        if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_fa,
                                     0, fw_base, fw_len ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not map firmware: %s\n",
                       hermon, strerror ( rc ) );
                goto err_map_fa;
        }

        /* Start firmware */
        if ( ( rc = hermon_cmd_run_fw ( hermon ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not run firmware: %s\n",
                       hermon, strerror ( rc ) );
                goto err_run_fw;
        }

        DBGC ( hermon, "Hermon %p firmware started\n", hermon );
        return 0;

 err_run_fw:
 err_map_fa:
        hermon_cmd_unmap_fa ( hermon );
 err_alloc_fa:
 err_query_fw:
        return rc;
}
static void hermon_stop_firmware ( struct hermon hermon) [static]

Stop firmware running.

Parameters:
hermonHermon device

Definition at line 2244 of file hermon.c.

References DBGC, hermon::firmware_area, hermon_cmd_unmap_fa(), rc, strerror(), and UNULL.

Referenced by hermon_probe(), hermon_start(), and hermon_stop().

                                                           {
        int rc;

        if ( ( rc = hermon_cmd_unmap_fa ( hermon ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p FATAL could not stop firmware: %s\n",
                       hermon, strerror ( rc ) );
                /* Leak memory and return; at least we avoid corruption */
                hermon->firmware_area = UNULL;
                return;
        }
}
static int hermon_get_cap ( struct hermon hermon) [static]

Get device limits.

Parameters:
hermonHermon device
Return values:
rcReturn status code

Definition at line 2269 of file hermon.c.

References hermon_dev_cap::altc_entry_size, hermon_dev_cap::auxc_entry_size, hermon::cap, hermon_dev_cap::cmpt_entry_size, hermon_dev_cap::cqc_entry_size, DBGC, hermon_dev_cap::dmpt_entry_size, hermon_dev_cap::dpdp, hermon_dev_cap::eqc_entry_size, hermon_cmd_query_dev_cap(), HERMON_MAX_PORTS, MLX_GET, hermon_dev_cap::mtt_entry_size, num_ports, hermon_dev_cap::num_ports, hermon_dev_cap::qpc_entry_size, rc, hermon_dev_cap::reserved_cqs, hermon_dev_cap::reserved_eqs, hermon_dev_cap::reserved_mrws, hermon_dev_cap::reserved_mtts, hermon_dev_cap::reserved_qps, hermon_dev_cap::reserved_srqs, hermon_dev_cap::reserved_uars, hermon_dev_cap::srqc_entry_size, and strerror().

Referenced by hermon_probe().

                                                    {
        struct hermonprm_query_dev_cap dev_cap;
        int rc;

        if ( ( rc = hermon_cmd_query_dev_cap ( hermon, &dev_cap ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not get device limits: %s\n",
                       hermon, strerror ( rc ) );
                return rc;
        }

        hermon->cap.cmpt_entry_size = MLX_GET ( &dev_cap, c_mpt_entry_sz );
        hermon->cap.reserved_qps =
                ( 1 << MLX_GET ( &dev_cap, log2_rsvd_qps ) );
        hermon->cap.qpc_entry_size = MLX_GET ( &dev_cap, qpc_entry_sz );
        hermon->cap.altc_entry_size = MLX_GET ( &dev_cap, altc_entry_sz );
        hermon->cap.auxc_entry_size = MLX_GET ( &dev_cap, aux_entry_sz );
        hermon->cap.reserved_srqs =
                ( 1 << MLX_GET ( &dev_cap, log2_rsvd_srqs ) );
        hermon->cap.srqc_entry_size = MLX_GET ( &dev_cap, srq_entry_sz );
        hermon->cap.reserved_cqs =
                ( 1 << MLX_GET ( &dev_cap, log2_rsvd_cqs ) );
        hermon->cap.cqc_entry_size = MLX_GET ( &dev_cap, cqc_entry_sz );
        hermon->cap.reserved_eqs = MLX_GET ( &dev_cap, num_rsvd_eqs );
        if ( hermon->cap.reserved_eqs == 0 ) {
                /* Backward compatibility */
                hermon->cap.reserved_eqs =
                        ( 1 << MLX_GET ( &dev_cap, log2_rsvd_eqs ) );
        }
        hermon->cap.eqc_entry_size = MLX_GET ( &dev_cap, eqc_entry_sz );
        hermon->cap.reserved_mtts =
                ( 1 << MLX_GET ( &dev_cap, log2_rsvd_mtts ) );
        hermon->cap.mtt_entry_size = MLX_GET ( &dev_cap, mtt_entry_sz );
        hermon->cap.reserved_mrws =
                ( 1 << MLX_GET ( &dev_cap, log2_rsvd_mrws ) );
        hermon->cap.dmpt_entry_size = MLX_GET ( &dev_cap, d_mpt_entry_sz );
        hermon->cap.reserved_uars = MLX_GET ( &dev_cap, num_rsvd_uars );
        hermon->cap.num_ports = MLX_GET ( &dev_cap, num_ports );
        hermon->cap.dpdp = MLX_GET ( &dev_cap, dpdp );

        /* Sanity check */
        if ( hermon->cap.num_ports > HERMON_MAX_PORTS ) {
                DBGC ( hermon, "Hermon %p has %d ports (only %d supported)\n",
                       hermon, hermon->cap.num_ports, HERMON_MAX_PORTS );
                hermon->cap.num_ports = HERMON_MAX_PORTS;
        }

        return 0;
}
static uint64_t icm_align ( uint64_t  icm_offset,
size_t  len 
) [static]

Align ICM table.

Parameters:
icm_offsetCurrent ICM offset
lenICM table length
Return values:
icm_offsetICM offset

Definition at line 2325 of file hermon.c.

References assert, and fls.

Referenced by hermon_map_icm().

                                                              {

        /* Round up to a multiple of the table size */
        assert ( len == ( 1UL << ( fls ( len ) - 1 ) ) );
        return ( ( icm_offset + len - 1 ) & ~( ( ( uint64_t ) len ) - 1 ) );
}
static int hermon_map_icm ( struct hermon hermon,
struct hermonprm_init_hca *  init_hca 
) [static]

Map ICM (allocating if necessary)

Parameters:
hermonHermon device
init_hcaINIT_HCA structure to fill in
Return values:
rcReturn status code

Definition at line 2339 of file hermon.c.

References hermon_dev_cap::altc_entry_size, assert, hermon_dev_cap::auxc_entry_size, hermon::cap, hermon_dev_cap::cmpt_entry_size, hermon_dev_cap::cqc_entry_size, DBGC, hermon_dev_cap::dmpt_entry_size, ENOMEM, hermon_dev_cap::eqc_entry_size, fls, hermon_cmd_map_icm(), hermon_cmd_map_icm_aux(), hermon_cmd_set_icm_size(), hermon_cmd_unmap_icm_aux(), HERMON_CMPT_MAX_ENTRIES, HERMON_ICM_CQ_CMPT, HERMON_ICM_EQ_CMPT, HERMON_ICM_NUM_REGIONS, HERMON_ICM_OTHER, HERMON_ICM_QP_CMPT, HERMON_ICM_SRQ_CMPT, HERMON_LOG_MULTICAST_HASH_SIZE, hermon_map_vpm(), HERMON_MAX_CQS, HERMON_MAX_EQS, HERMON_MAX_MTTS, HERMON_MAX_QPS, HERMON_PAGE_SIZE, HERMON_RSVD_SPECIAL_QPS, hermon::icm, icm_align(), hermon::icm_aux_len, hermon::icm_len, hermon::icm_map, len, hermon_icm_map::len, memset(), MLX_FILL_1, MLX_FILL_2, MLX_GET, hermon_dev_cap::mtt_entry_size, hermon_icm_map::offset, hermon_dev_cap::qpc_entry_size, rc, hermon_dev_cap::reserved_cqs, hermon_dev_cap::reserved_eqs, hermon_dev_cap::reserved_mrws, hermon_dev_cap::reserved_mtts, hermon_dev_cap::reserved_qps, hermon_dev_cap::reserved_srqs, hermon_dev_cap::srqc_entry_size, strerror(), umalloc(), user_to_phys(), and value.

Referenced by hermon_start().

                                                                  {
        struct hermonprm_scalar_parameter icm_size;
        struct hermonprm_scalar_parameter icm_aux_size;
        uint64_t icm_offset = 0;
        unsigned int log_num_qps, log_num_srqs, log_num_cqs, log_num_eqs;
        unsigned int log_num_mtts, log_num_mpts, log_num_mcs;
        size_t cmpt_max_len;
        size_t icm_len, icm_aux_len;
        size_t len;
        physaddr_t icm_phys;
        int i;
        int rc;

        /*
         * Start by carving up the ICM virtual address space
         *
         */

        /* Calculate number of each object type within ICM */
        log_num_qps = fls ( hermon->cap.reserved_qps +
                            HERMON_RSVD_SPECIAL_QPS + HERMON_MAX_QPS - 1 );
        log_num_srqs = fls ( hermon->cap.reserved_srqs - 1 );
        log_num_cqs = fls ( hermon->cap.reserved_cqs + HERMON_MAX_CQS - 1 );
        log_num_eqs = fls ( hermon->cap.reserved_eqs + HERMON_MAX_EQS - 1 );
        log_num_mtts = fls ( hermon->cap.reserved_mtts + HERMON_MAX_MTTS - 1 );
        log_num_mpts = fls ( hermon->cap.reserved_mrws + 1 - 1 );
        log_num_mcs = HERMON_LOG_MULTICAST_HASH_SIZE;

        /* ICM starts with the cMPT tables, which are sparse */
        cmpt_max_len = ( HERMON_CMPT_MAX_ENTRIES *
                         ( ( uint64_t ) hermon->cap.cmpt_entry_size ) );
        len = ( ( ( ( 1 << log_num_qps ) * hermon->cap.cmpt_entry_size ) +
                  HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
        hermon->icm_map[HERMON_ICM_QP_CMPT].offset = icm_offset;
        hermon->icm_map[HERMON_ICM_QP_CMPT].len = len;
        icm_offset += cmpt_max_len;
        len = ( ( ( ( 1 << log_num_srqs ) * hermon->cap.cmpt_entry_size ) +
                  HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
        hermon->icm_map[HERMON_ICM_SRQ_CMPT].offset = icm_offset;
        hermon->icm_map[HERMON_ICM_SRQ_CMPT].len = len;
        icm_offset += cmpt_max_len;
        len = ( ( ( ( 1 << log_num_cqs ) * hermon->cap.cmpt_entry_size ) +
                  HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
        hermon->icm_map[HERMON_ICM_CQ_CMPT].offset = icm_offset;
        hermon->icm_map[HERMON_ICM_CQ_CMPT].len = len;
        icm_offset += cmpt_max_len;
        len = ( ( ( ( 1 << log_num_eqs ) * hermon->cap.cmpt_entry_size ) +
                  HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
        hermon->icm_map[HERMON_ICM_EQ_CMPT].offset = icm_offset;
        hermon->icm_map[HERMON_ICM_EQ_CMPT].len = len;
        icm_offset += cmpt_max_len;

        hermon->icm_map[HERMON_ICM_OTHER].offset = icm_offset;

        /* Queue pair contexts */
        len = ( ( 1 << log_num_qps ) * hermon->cap.qpc_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 12,
                     qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_2 ( init_hca, 13,
                     qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_l,
                     ( icm_offset >> 5 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_qp,
                     log_num_qps );
        DBGC ( hermon, "Hermon %p ICM QPC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_qps ), hermon->cap.qpc_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Extended alternate path contexts */
        len = ( ( 1 << log_num_qps ) * hermon->cap.altc_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 24,
                     qpc_eec_cqc_eqc_rdb_parameters.altc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_1 ( init_hca, 25,
                     qpc_eec_cqc_eqc_rdb_parameters.altc_base_addr_l,
                     icm_offset );
        DBGC ( hermon, "Hermon %p ICM ALTC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_qps ), hermon->cap.altc_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Extended auxiliary contexts */
        len = ( ( 1 << log_num_qps ) * hermon->cap.auxc_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 28,
                     qpc_eec_cqc_eqc_rdb_parameters.auxc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_1 ( init_hca, 29,
                     qpc_eec_cqc_eqc_rdb_parameters.auxc_base_addr_l,
                     icm_offset );
        DBGC ( hermon, "Hermon %p ICM AUXC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_qps ), hermon->cap.auxc_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Shared receive queue contexts */
        len = ( ( 1 << log_num_srqs ) * hermon->cap.srqc_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 18,
                     qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_2 ( init_hca, 19,
                     qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_l,
                     ( icm_offset >> 5 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_srq,
                     log_num_srqs );
        DBGC ( hermon, "Hermon %p ICM SRQC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_srqs ), hermon->cap.srqc_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Completion queue contexts */
        len = ( ( 1 << log_num_cqs ) * hermon->cap.cqc_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 20,
                     qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_2 ( init_hca, 21,
                     qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_l,
                     ( icm_offset >> 5 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_cq,
                     log_num_cqs );
        DBGC ( hermon, "Hermon %p ICM CQC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_cqs ), hermon->cap.cqc_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Event queue contexts */
        len = ( ( 1 << log_num_eqs ) * hermon->cap.eqc_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 32,
                     qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_2 ( init_hca, 33,
                     qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_l,
                     ( icm_offset >> 5 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_eq,
                     log_num_eqs );
        DBGC ( hermon, "Hermon %p ICM EQC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_eqs ), hermon->cap.eqc_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Memory translation table */
        len = ( ( 1 << log_num_mtts ) * hermon->cap.mtt_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 64,
                     tpt_parameters.mtt_base_addr_h, ( icm_offset >> 32 ) );
        MLX_FILL_1 ( init_hca, 65,
                     tpt_parameters.mtt_base_addr_l, icm_offset );
        DBGC ( hermon, "Hermon %p ICM MTT is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_mtts ), hermon->cap.mtt_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Memory protection table */
        len = ( ( 1 << log_num_mpts ) * hermon->cap.dmpt_entry_size );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 60,
                     tpt_parameters.dmpt_base_adr_h, ( icm_offset >> 32 ) );
        MLX_FILL_1 ( init_hca, 61,
                     tpt_parameters.dmpt_base_adr_l, icm_offset );
        MLX_FILL_1 ( init_hca, 62,
                     tpt_parameters.log_dmpt_sz, log_num_mpts );
        DBGC ( hermon, "Hermon %p ICM DMPT is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_mpts ), hermon->cap.dmpt_entry_size,
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;

        /* Multicast table */
        len = ( ( 1 << log_num_mcs ) * sizeof ( struct hermonprm_mcg_entry ) );
        icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 48,
                     multicast_parameters.mc_base_addr_h,
                     ( icm_offset >> 32 ) );
        MLX_FILL_1 ( init_hca, 49,
                     multicast_parameters.mc_base_addr_l, icm_offset );
        MLX_FILL_1 ( init_hca, 52,
                     multicast_parameters.log_mc_table_entry_sz,
                     fls ( sizeof ( struct hermonprm_mcg_entry ) - 1 ) );
        MLX_FILL_1 ( init_hca, 53,
                     multicast_parameters.log_mc_table_hash_sz, log_num_mcs );
        MLX_FILL_1 ( init_hca, 54,
                     multicast_parameters.log_mc_table_sz, log_num_mcs );
        DBGC ( hermon, "Hermon %p ICM MC is %d x %#zx at [%08llx,%08llx)\n",
               hermon, ( 1 << log_num_mcs ),
               sizeof ( struct hermonprm_mcg_entry ),
               icm_offset, ( icm_offset + len ) );
        icm_offset += len;


        hermon->icm_map[HERMON_ICM_OTHER].len =
                ( icm_offset - hermon->icm_map[HERMON_ICM_OTHER].offset );

        /*
         * Allocate and map physical memory for (portions of) ICM
         *
         * Map is:
         *   ICM AUX area (aligned to its own size)
         *   cMPT areas
         *   Other areas
         */

        /* Calculate physical memory required for ICM */
        icm_len = 0;
        for ( i = 0 ; i < HERMON_ICM_NUM_REGIONS ; i++ ) {
                icm_len += hermon->icm_map[i].len;
        }

        /* Get ICM auxiliary area size */
        memset ( &icm_size, 0, sizeof ( icm_size ) );
        MLX_FILL_1 ( &icm_size, 0, value_hi, ( icm_offset >> 32 ) );
        MLX_FILL_1 ( &icm_size, 1, value, icm_offset );
        if ( ( rc = hermon_cmd_set_icm_size ( hermon, &icm_size,
                                              &icm_aux_size ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not set ICM size: %s\n",
                       hermon, strerror ( rc ) );
                goto err_set_icm_size;
        }
        icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * HERMON_PAGE_SIZE );

        /* Allocate ICM data and auxiliary area */
        DBGC ( hermon, "Hermon %p requires %zd kB ICM and %zd kB AUX ICM\n",
               hermon, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
        if ( ! hermon->icm ) {
                hermon->icm_len = icm_len;
                hermon->icm_aux_len = icm_aux_len;
                hermon->icm = umalloc ( hermon->icm_aux_len + hermon->icm_len );
                if ( ! hermon->icm ) {
                        rc = -ENOMEM;
                        goto err_alloc;
                }
        } else {
                assert ( hermon->icm_len == icm_len );
                assert ( hermon->icm_aux_len == icm_aux_len );
        }
        icm_phys = user_to_phys ( hermon->icm, 0 );

        /* Map ICM auxiliary area */
        DBGC ( hermon, "Hermon %p mapping ICM AUX => %08lx\n",
               hermon, icm_phys );
        if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_icm_aux,
                                     0, icm_phys, icm_aux_len ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not map AUX ICM: %s\n",
                       hermon, strerror ( rc ) );
                goto err_map_icm_aux;
        }
        icm_phys += icm_aux_len;

        /* MAP ICM area */
        for ( i = 0 ; i < HERMON_ICM_NUM_REGIONS ; i++ ) {
                DBGC ( hermon, "Hermon %p mapping ICM %llx+%zx => %08lx\n",
                       hermon, hermon->icm_map[i].offset,
                       hermon->icm_map[i].len, icm_phys );
                if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_icm,
                                             hermon->icm_map[i].offset,
                                             icm_phys,
                                             hermon->icm_map[i].len ) ) != 0 ){
                        DBGC ( hermon, "Hermon %p could not map ICM: %s\n",
                               hermon, strerror ( rc ) );
                        goto err_map_icm;
                }
                icm_phys += hermon->icm_map[i].len;
        }

        return 0;

 err_map_icm:
        assert ( i == 0 ); /* We don't handle partial failure at present */
 err_map_icm_aux:
        hermon_cmd_unmap_icm_aux ( hermon );
 err_alloc:
 err_set_icm_size:
        return rc;
}
static void hermon_unmap_icm ( struct hermon hermon) [static]

Unmap ICM.

Parameters:
hermonHermon device

Definition at line 2624 of file hermon.c.

References fls, hermon_cmd_unmap_icm(), hermon_cmd_unmap_icm_aux(), HERMON_ICM_NUM_REGIONS, HERMON_PAGE_SIZE, hermon::icm_map, hermon_icm_map::len, memset(), MLX_FILL_1, hermon_icm_map::offset, and value.

Referenced by hermon_start(), and hermon_stop().

                                                       {
        struct hermonprm_scalar_parameter unmap_icm;
        int i;

        for ( i = ( HERMON_ICM_NUM_REGIONS - 1 ) ; i >= 0 ; i-- ) {
                memset ( &unmap_icm, 0, sizeof ( unmap_icm ) );
                MLX_FILL_1 ( &unmap_icm, 0, value_hi,
                             ( hermon->icm_map[i].offset >> 32 ) );
                MLX_FILL_1 ( &unmap_icm, 1, value,
                             hermon->icm_map[i].offset );
                hermon_cmd_unmap_icm ( hermon,
                                       ( 1 << fls ( ( hermon->icm_map[i].len /
                                                      HERMON_PAGE_SIZE ) - 1)),
                                       &unmap_icm );
        }
        hermon_cmd_unmap_icm_aux ( hermon );
}
static void hermon_reset ( struct hermon hermon) [static]

Reset device.

Parameters:
hermonHermon device

Definition at line 2654 of file hermon.c.

References hermon::config, HERMON_RESET_MAGIC, HERMON_RESET_OFFSET, HERMON_RESET_WAIT_TIME_MS, mdelay(), hermon::pci, pci_backup(), PCI_CONFIG_BACKUP_EXCLUDE, pci_restore(), hermon::toggle, and writel().

Referenced by hermon_probe(), and hermon_stop().

                                                   {
        struct pci_device *pci = hermon->pci;
        struct pci_config_backup backup;
        static const uint8_t backup_exclude[] =
                PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );

        /* Perform device reset and preserve PCI configuration */
        pci_backup ( pci, &backup, backup_exclude );
        writel ( HERMON_RESET_MAGIC,
                 ( hermon->config + HERMON_RESET_OFFSET ) );
        mdelay ( HERMON_RESET_WAIT_TIME_MS );
        pci_restore ( pci, &backup, backup_exclude );

        /* Reset command interface toggle */
        hermon->toggle = 0;
}
static int hermon_setup_mpt ( struct hermon hermon) [static]

Set up memory protection table.

Parameters:
hermonHermon device
Return values:
rcReturn status code

Definition at line 2677 of file hermon.c.

References hermon::cap, DBGC, hermon_cmd_sw2hw_mpt(), HERMON_GLOBAL_PD, HERMON_MKEY_PREFIX, key, hermon::lkey, memset(), MLX_FILL_1, MLX_FILL_7, rc, hermon_dev_cap::reserved_mrws, and strerror().

Referenced by hermon_start().

                                                      {
        struct hermonprm_mpt mpt;
        uint32_t key;
        int rc;

        /* Derive key */
        key = ( hermon->cap.reserved_mrws | HERMON_MKEY_PREFIX );
        hermon->lkey = ( ( key << 8 ) | ( key >> 24 ) );

        /* Initialise memory protection table */
        memset ( &mpt, 0, sizeof ( mpt ) );
        MLX_FILL_7 ( &mpt, 0,
                     atomic, 1,
                     rw, 1,
                     rr, 1,
                     lw, 1,
                     lr, 1,
                     pa, 1,
                     r_w, 1 );
        MLX_FILL_1 ( &mpt, 2, mem_key, key );
        MLX_FILL_1 ( &mpt, 3,
                     pd, HERMON_GLOBAL_PD );
        MLX_FILL_1 ( &mpt, 10, len64, 1 );
        if ( ( rc = hermon_cmd_sw2hw_mpt ( hermon,
                                           hermon->cap.reserved_mrws,
                                           &mpt ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not set up MPT: %s\n",
                       hermon, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int hermon_configure_special_qps ( struct hermon hermon) [static]

Configure special queue pairs.

Parameters:
hermonHermon device
Return values:
rcReturn status code

Definition at line 2717 of file hermon.c.

References hermon::cap, DBGC, hermon_cmd_conf_special_qp(), HERMON_NUM_SPECIAL_QPS, hermon::qpn_base, rc, hermon_dev_cap::reserved_qps, hermon::special_qpn_base, and strerror().

Referenced by hermon_start().

                                                                  {
        int rc;

        /* Special QP block must be aligned on its own size */
        hermon->special_qpn_base = ( ( hermon->cap.reserved_qps +
                                       HERMON_NUM_SPECIAL_QPS - 1 )
                                     & ~( HERMON_NUM_SPECIAL_QPS - 1 ) );
        hermon->qpn_base = ( hermon->special_qpn_base +
                             HERMON_NUM_SPECIAL_QPS );
        DBGC ( hermon, "Hermon %p special QPs at [%lx,%lx]\n", hermon,
               hermon->special_qpn_base, ( hermon->qpn_base - 1 ) );

        /* Issue command to configure special QPs */
        if ( ( rc = hermon_cmd_conf_special_qp ( hermon, 0x00,
                                          hermon->special_qpn_base ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not configure special QPs: "
                       "%s\n", hermon, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int hermon_start ( struct hermon hermon,
int  running 
) [static]

Start Hermon device.

Parameters:
hermonHermon device
runningFirmware is already running
Return values:
rcReturn status code

Definition at line 2747 of file hermon.c.

References hermon::cap, DBGC, hermon_cmd_close_hca(), hermon_cmd_init_hca(), hermon_configure_special_qps(), hermon_create_eq(), hermon_destroy_eq(), hermon_map_icm(), hermon_setup_mpt(), hermon_start_firmware(), hermon_stop_firmware(), hermon_unmap_icm(), hermon_port::ibdev, hermon::lkey, memset(), MLX_FILL_1, hermon_dev_cap::num_ports, hermon::port, rc, ib_device::rdma_key, strerror(), and version.

Referenced by hermon_open(), and hermon_probe().

                                                               {
        struct hermonprm_init_hca init_hca;
        unsigned int i;
        int rc;

        /* Start firmware if not already running */
        if ( ! running ) {
                if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
                        goto err_start_firmware;
        }

        /* Allocate and map ICM */
        memset ( &init_hca, 0, sizeof ( init_hca ) );
        if ( ( rc = hermon_map_icm ( hermon, &init_hca ) ) != 0 )
                goto err_map_icm;

        /* Initialise HCA */
        MLX_FILL_1 ( &init_hca, 0, version, 0x02 /* "Must be 0x02" */ );
        MLX_FILL_1 ( &init_hca, 5, udp, 1 );
        MLX_FILL_1 ( &init_hca, 74, uar_parameters.log_max_uars, 8 );
        if ( ( rc = hermon_cmd_init_hca ( hermon, &init_hca ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not initialise HCA: %s\n",
                       hermon, strerror ( rc ) );
                goto err_init_hca;
        }

        /* Set up memory protection */
        if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
                goto err_setup_mpt;
        for ( i = 0 ; i < hermon->cap.num_ports ; i++ )
                hermon->port[i].ibdev->rdma_key = hermon->lkey;

        /* Set up event queue */
        if ( ( rc = hermon_create_eq ( hermon ) ) != 0 )
                goto err_create_eq;

        /* Configure special QPs */
        if ( ( rc = hermon_configure_special_qps ( hermon ) ) != 0 )
                goto err_conf_special_qps;

        return 0;

 err_conf_special_qps:
        hermon_destroy_eq ( hermon );
 err_create_eq:
 err_setup_mpt:
        hermon_cmd_close_hca ( hermon );
 err_init_hca:
        hermon_unmap_icm ( hermon );
 err_map_icm:
        hermon_stop_firmware ( hermon );
 err_start_firmware:
        return rc;
}
static void hermon_stop ( struct hermon hermon) [static]

Stop Hermon device.

Parameters:
hermonHermon device

Definition at line 2807 of file hermon.c.

References hermon_cmd_close_hca(), hermon_destroy_eq(), hermon_reset(), hermon_stop_firmware(), and hermon_unmap_icm().

Referenced by hermon_close(), and hermon_probe().

                                                  {
        hermon_destroy_eq ( hermon );
        hermon_cmd_close_hca ( hermon );
        hermon_unmap_icm ( hermon );
        hermon_stop_firmware ( hermon );
        hermon_reset ( hermon );
}
static int hermon_open ( struct hermon hermon) [static]

Open Hermon device.

Parameters:
hermonHermon device
Return values:
rcReturn status code

Definition at line 2821 of file hermon.c.

References hermon_start(), hermon::open_count, and rc.

Referenced by hermon_eth_open(), and hermon_ib_open().

                                                 {
        int rc;

        /* Start device if applicable */
        if ( hermon->open_count == 0 ) {
                if ( ( rc = hermon_start ( hermon, 0 ) ) != 0 )
                        return rc;
        }

        /* Increment open counter */
        hermon->open_count++;

        return 0;
}
static void hermon_close ( struct hermon hermon) [static]

Close Hermon device.

Parameters:
hermonHermon device

Definition at line 2841 of file hermon.c.

References assert, hermon_stop(), and hermon::open_count.

Referenced by hermon_eth_close(), hermon_eth_open(), hermon_ib_close(), and hermon_ib_open().

                                                   {

        /* Decrement open counter */
        assert ( hermon->open_count != 0 );
        hermon->open_count--;

        /* Stop device if applicable */
        if ( hermon->open_count == 0 )
                hermon_stop ( hermon );
}
static int hermon_ib_open ( struct ib_device ibdev) [static]

Initialise Infiniband link.

Parameters:
ibdevInfiniband device
Return values:
rcReturn status code

Definition at line 2865 of file hermon.c.

References DBGC, hermon_close(), hermon_cmd_init_port(), hermon_cmd_set_port(), hermon_mad(), hermon_open(), hermonprm_set_port::ib, ib_get_drvdata(), IB_MTU_2048, ib_smc_update(), IB_VL_0, memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_8, ib_device::port, rc, and strerror().

                                                      {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        union hermonprm_set_port set_port;
        int rc;

        /* Open hardware */
        if ( ( rc = hermon_open ( hermon ) ) != 0 )
                goto err_open;

        /* Set port parameters */
        memset ( &set_port, 0, sizeof ( set_port ) );
        MLX_FILL_8 ( &set_port.ib, 0,
                     mmc, 1,
                     mvc, 1,
                     mp, 1,
                     mg, 1,
                     mtu_cap, IB_MTU_2048,
                     vl_cap, IB_VL_0,
                     rcm, 1,
                     lss, 1 );
        MLX_FILL_2 ( &set_port.ib, 10,
                     max_pkey, 1,
                     max_gid, 1 );
        MLX_FILL_1 ( &set_port.ib, 28,
                     link_speed_supported, 1 );
        if ( ( rc = hermon_cmd_set_port ( hermon, 0, ibdev->port,
                                          &set_port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not set port: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                goto err_set_port;
        }

        /* Initialise port */
        if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not initialise port: "
                       "%s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_init_port;
        }

        /* Update MAD parameters */
        ib_smc_update ( ibdev, hermon_mad );

        return 0;

 err_init_port:
 err_set_port:
        hermon_close ( hermon );
 err_open:
        return rc;
}
static void hermon_ib_close ( struct ib_device ibdev) [static]

Close Infiniband link.

Parameters:
ibdevInfiniband device

Definition at line 2921 of file hermon.c.

References DBGC, hermon_close(), hermon_cmd_close_port(), ib_get_drvdata(), ib_device::port, rc, and strerror().

                                                        {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        int rc;

        /* Close port */
        if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                /* Nothing we can do about this */
        }

        /* Close hardware */
        hermon_close ( hermon );
}
static int hermon_inform_sma ( struct ib_device ibdev,
union ib_mad mad 
) [static]

Inform embedded subnet management agent of a received MAD.

Parameters:
ibdevInfiniband device
madMAD
Return values:
rcReturn status code

Definition at line 2943 of file hermon.c.

References hermon_mad(), ib_smc_update(), and rc.

                                                   {
        int rc;

        /* Send the MAD to the embedded SMA */
        if ( ( rc = hermon_mad ( ibdev, mad ) ) != 0 )
                return rc;

        /* Update parameters held in software */
        ib_smc_update ( ibdev, hermon_mad );

        return 0;
}
static int hermon_mcast_attach ( struct ib_device ibdev,
struct ib_queue_pair qp,
union ib_gid gid 
) [static]

Attach to multicast group.

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

Definition at line 2972 of file hermon.c.

References DBGC, EBUSY, hdr, hermon_cmd_mgid_hash(), hermon_cmd_read_mcg(), hermon_cmd_write_mcg(), ib_get_drvdata(), index, memcpy(), MLX_FILL_1, MLX_GET, ib_queue_pair::qpn, qpn, rc, and strerror().

                                                     {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermonprm_mgm_hash hash;
        struct hermonprm_mcg_entry mcg;
        unsigned int index;
        int rc;

        /* Generate hash table index */
        if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
                       hermon, strerror ( rc ) );
                return rc;
        }
        index = MLX_GET ( &hash, hash );

        /* Check for existing hash table entry */
        if ( ( rc = hermon_cmd_read_mcg ( hermon, index, &mcg ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not read MCG %#x: %s\n",
                       hermon, index, strerror ( rc ) );
                return rc;
        }
        if ( MLX_GET ( &mcg, hdr.members_count ) != 0 ) {
                /* FIXME: this implementation allows only a single QP
                 * per multicast group, and doesn't handle hash
                 * collisions.  Sufficient for IPoIB but may need to
                 * be extended in future.
                 */
                DBGC ( hermon, "Hermon %p MGID index %#x already in use\n",
                       hermon, index );
                return -EBUSY;
        }

        /* Update hash table entry */
        MLX_FILL_1 ( &mcg, 1, hdr.members_count, 1 );
        MLX_FILL_1 ( &mcg, 8, qp[0].qpn, qp->qpn );
        memcpy ( &mcg.u.dwords[4], gid, sizeof ( *gid ) );
        if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
                       hermon, index, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void hermon_mcast_detach ( struct ib_device ibdev,
struct ib_queue_pair *qp  __unused,
union ib_gid gid 
) [static]

Detach from multicast group.

Parameters:
ibdevInfiniband device
qpQueue pair
gidMulticast GID

Definition at line 3026 of file hermon.c.

References DBGC, hermon_cmd_mgid_hash(), hermon_cmd_write_mcg(), ib_get_drvdata(), index, memset(), MLX_GET, rc, and strerror().

                                                      {
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        struct hermonprm_mgm_hash hash;
        struct hermonprm_mcg_entry mcg;
        unsigned int index;
        int rc;

        /* Generate hash table index */
        if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
                       hermon, strerror ( rc ) );
                return;
        }
        index = MLX_GET ( &hash, hash );

        /* Clear hash table entry */
        memset ( &mcg, 0, sizeof ( mcg ) );
        if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
                       hermon, index, strerror ( rc ) );
                return;
        }
}
static int hermon_register_ibdev ( struct hermon hermon,
struct hermon_port port 
) [static]

Register Hermon Infiniband device.

Parameters:
hermonHermon device
portHermon port
Return values:
rcReturn status code

Definition at line 3078 of file hermon.c.

References DBGC, hermon_mad(), ib_smc_init(), hermon_port::ibdev, ib_device::port, rc, register_ibdev(), and strerror().

                                                              {
        struct ib_device *ibdev = port->ibdev;
        int rc;

        /* Initialise parameters using SMC */
        ib_smc_init ( ibdev, hermon_mad );

        /* Register Infiniband device */
        if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not register IB "
                       "device: %s\n", hermon, ibdev->port, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void hermon_state_change_ibdev ( struct hermon *hermon  __unused,
struct hermon_port port,
int link_up  __unused 
) [static]

Handle Hermon Infiniband device port state change.

Parameters:
hermonHermon device
portHermon port
link_upLink is up

Definition at line 3103 of file hermon.c.

References hermon_mad(), ib_smc_update(), and hermon_port::ibdev.

                                                               {
        struct ib_device *ibdev = port->ibdev;

        /* Update MAD parameters */
        ib_smc_update ( ibdev, hermon_mad );
}
static void hermon_unregister_ibdev ( struct hermon *hermon  __unused,
struct hermon_port port 
) [static]

Unregister Hermon Infiniband device.

Parameters:
hermonHermon device
portHermon port

Definition at line 3118 of file hermon.c.

References hermon_port::ibdev, and unregister_ibdev().

                                                                 {
        struct ib_device *ibdev = port->ibdev;

        unregister_ibdev ( ibdev );
}
static int hermon_eth_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet via Hermon Ethernet device.

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

Definition at line 3155 of file hermon.c.

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

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

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

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

Handle Hermon Ethernet device send completion.

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

Definition at line 3186 of file hermon.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 hermon_eth_complete_recv ( struct ib_device *ibdev  __unused,
struct ib_queue_pair qp,
struct ib_address_vector *dest  __unused,
struct ib_address_vector source,
struct io_buffer iobuf,
int  rc 
) [static]

Handle Hermon Ethernet device receive completion.

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

Definition at line 3204 of file hermon.c.

References ENODEV, ib_qp_get_ownerdata(), netdev, netdev_rx(), netdev_rx_err(), NULL, ib_address_vector::vlan, vlan_find(), and ib_address_vector::vlan_present.

                                                                         {
        struct net_device *netdev = ib_qp_get_ownerdata ( qp );
        struct net_device *vlan;

        /* Find VLAN device, if applicable */
        if ( source->vlan_present ) {
                if ( ( vlan = vlan_find ( netdev, source->vlan ) ) != NULL ) {
                        netdev = vlan;
                } else if ( rc == 0 ) {
                        rc = -ENODEV;
                }
        }

        /* Hand off to network layer */
        if ( rc == 0 ) {
                netdev_rx ( netdev, iobuf );
        } else {
                netdev_rx_err ( netdev, iobuf, rc );
        }
}
static void hermon_eth_poll ( struct net_device netdev) [static]

Poll Hermon Ethernet device.

Parameters:
netdevNetwork device

Definition at line 3240 of file hermon.c.

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

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

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

Open Hermon Ethernet device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 3253 of file hermon.c.

References DBGC, hermon_port::eth_cq, ETH_FRAME_LEN, hermon_port::eth_qp, FCOE_VLAN_PRIORITY, hermonprm_set_port::general, hermon_close(), hermon_cmd_init_port(), hermon_cmd_set_port(), HERMON_ETH_NUM_CQES, HERMON_ETH_NUM_RECV_WQES, HERMON_ETH_NUM_SEND_WQES, hermon_open(), HERMON_SET_PORT_GENERAL_PARAM, HERMON_SET_PORT_RECEIVE_QP, ib_create_cq(), ib_create_qp(), ib_destroy_cq(), ib_destroy_qp(), ib_get_drvdata(), ib_modify_qp(), ib_qp_set_ownerdata(), IB_QPT_ETH, ib_refill_recv(), hermon_port::ibdev, memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_3, mtu, net_device::name, ib_device::port, port, net_device::priv, ib_queue_pair::qpn, rc, hermonprm_set_port::rqp_calc, and strerror().

                                                         {
        struct hermon_port *port = netdev->priv;
        struct ib_device *ibdev = port->ibdev;
        struct hermon *hermon = ib_get_drvdata ( ibdev );
        union hermonprm_set_port set_port;
        int rc;

        /* Open hardware */
        if ( ( rc = hermon_open ( hermon ) ) != 0 )
                goto err_open;

        /* Allocate completion queue */
        if ( ( rc = ib_create_cq ( ibdev, HERMON_ETH_NUM_CQES,
                                   &hermon_eth_cq_op, &port->eth_cq ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not create completion "
                       "queue: %s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_create_cq;
        }

        /* Allocate queue pair */
        if ( ( rc = ib_create_qp ( ibdev, IB_QPT_ETH, HERMON_ETH_NUM_SEND_WQES,
                                   port->eth_cq, HERMON_ETH_NUM_RECV_WQES,
                                   port->eth_cq, &hermon_eth_qp_op,
                                   netdev->name, &port->eth_qp ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not create queue "
                       "pair: %s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_create_qp;
        }
        ib_qp_set_ownerdata ( port->eth_qp, netdev );

        /* Activate queue pair */
        if ( ( rc = ib_modify_qp ( ibdev, port->eth_qp ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not modify queue "
                       "pair: %s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_modify_qp;
        }

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

        /* Set port general parameters */
        memset ( &set_port, 0, sizeof ( set_port ) );
        MLX_FILL_3 ( &set_port.general, 0,
                     v_mtu, 1,
                     v_pprx, 1,
                     v_pptx, 1 );
        MLX_FILL_1 ( &set_port.general, 1,
                     mtu, ( ETH_FRAME_LEN + 40 /* Used by card */ ) );
        MLX_FILL_1 ( &set_port.general, 2,
                     pfctx, ( 1 << FCOE_VLAN_PRIORITY ) );
        MLX_FILL_1 ( &set_port.general, 3,
                     pfcrx, ( 1 << FCOE_VLAN_PRIORITY ) );
        if ( ( rc = hermon_cmd_set_port ( hermon, 1,
                                          ( HERMON_SET_PORT_GENERAL_PARAM |
                                            ibdev->port ),
                                          &set_port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not set port general "
                       "parameters: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                goto err_set_port_general_params;
        }

        /* Set port receive QP */
        memset ( &set_port, 0, sizeof ( set_port ) );
        MLX_FILL_1 ( &set_port.rqp_calc, 0, base_qpn, port->eth_qp->qpn );
        MLX_FILL_1 ( &set_port.rqp_calc, 2,
                     mac_miss_index, 128 /* MAC misses go to promisc QP */ );
        MLX_FILL_2 ( &set_port.rqp_calc, 3,
                     vlan_miss_index, 127 /* VLAN misses go to promisc QP */,
                     no_vlan_index, 126 /* VLAN-free go to promisc QP */ );
        MLX_FILL_2 ( &set_port.rqp_calc, 5,
                     promisc_qpn, port->eth_qp->qpn,
                     en_uc_promisc, 1 );
        MLX_FILL_2 ( &set_port.rqp_calc, 6,
                     def_mcast_qpn, port->eth_qp->qpn,
                     mc_promisc_mode, 2 /* Receive all multicasts */ );
        if ( ( rc = hermon_cmd_set_port ( hermon, 1,
                                          ( HERMON_SET_PORT_RECEIVE_QP |
                                            ibdev->port ),
                                          &set_port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not set port receive "
                       "QP: %s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_set_port_receive_qp;
        }

        /* Initialise port */
        if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not initialise port: "
                       "%s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_init_port;
        }

        return 0;

 err_init_port:
 err_set_port_receive_qp:
 err_set_port_general_params:
 err_modify_qp:
        ib_destroy_qp ( ibdev, port->eth_qp );
 err_create_qp:
        ib_destroy_cq ( ibdev, port->eth_cq );
 err_create_cq:
        hermon_close ( hermon );
 err_open:
        return rc;
}
static void hermon_eth_close ( struct net_device netdev) [static]

Close Hermon Ethernet device.

Parameters:
netdevNetwork device

Definition at line 3365 of file hermon.c.

References DBGC, hermon_port::eth_cq, hermon_port::eth_qp, hermon_close(), hermon_cmd_close_port(), ib_destroy_cq(), ib_destroy_qp(), ib_get_drvdata(), hermon_port::ibdev, ib_device::port, port, net_device::priv, rc, and strerror().

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

        /* Close port */
        if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                /* Nothing we can do about this */
        }

        /* Tear down the queues */
        ib_destroy_qp ( ibdev, port->eth_qp );
        ib_destroy_cq ( ibdev, port->eth_cq );

        /* Close hardware */
        hermon_close ( hermon );
}
static int hermon_register_netdev ( struct hermon hermon,
struct hermon_port port 
) [static]

Register Hermon Ethernet device.

Parameters:
hermonHermon device
portHermon port
Return values:
rcReturn status code

Definition at line 3401 of file hermon.c.

References bytes, DBGC, ETH_ALEN, hermon_cmd_query_port(), htonl, net_device::hw_addr, hermon_port::ibdev, mac, memcpy(), MLX_GET, netdev, hermon_port::netdev, netdev_settings(), hermon_port::nvo, ib_device::port, rc, register_netdev(), register_nvo(), strerror(), unregister_netdev(), and unregister_nvo().

                                                               {
        struct net_device *netdev = port->netdev;
        struct ib_device *ibdev = port->ibdev;
        struct hermonprm_query_port_cap query_port;
        union {
                uint8_t bytes[8];
                uint32_t dwords[2];
        } mac;
        int rc;

        /* Retrieve MAC address */
        if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
                                            &query_port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                goto err_query_port;
        }
        mac.dwords[0] = htonl ( MLX_GET ( &query_port, mac_47_32 ) );
        mac.dwords[1] = htonl ( MLX_GET ( &query_port, mac_31_0 ) );
        memcpy ( netdev->hw_addr,
                 &mac.bytes[ sizeof ( mac.bytes ) - ETH_ALEN ], ETH_ALEN );

        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not register network "
                       "device: %s\n", hermon, ibdev->port, strerror ( rc ) );
                goto err_register_netdev;
        }

        /* Register non-volatile options */
        if ( ( rc = register_nvo ( &port->nvo,
                                   netdev_settings ( netdev ) ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not register non-"
                       "volatile options: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                goto err_register_nvo;
        }

        return 0;

        unregister_nvo ( &port->nvo );
 err_register_nvo:
        unregister_netdev ( netdev );
 err_register_netdev:
 err_query_port:
        return rc;
}
static void hermon_state_change_netdev ( struct hermon *hermon  __unused,
struct hermon_port port,
int  link_up 
) [static]

Handle Hermon Ethernet device port state change.

Parameters:
hermonHermon device
portHermon port
link_upLink is up

Definition at line 3457 of file hermon.c.

References netdev, hermon_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 hermon_unregister_netdev ( struct hermon *hermon  __unused,
struct hermon_port port 
) [static]

Unregister Hermon Ethernet device.

Parameters:
hermonHermon device
portHermon port

Definition at line 3475 of file hermon.c.

References netdev, hermon_port::netdev, hermon_port::nvo, unregister_netdev(), and unregister_nvo().

                                                                  {
        struct net_device *netdev = port->netdev;

        unregister_nvo ( &port->nvo );
        unregister_netdev ( netdev );
}
static const char* hermon_name_port_type ( unsigned int  port_type) [inline, static]

Name port type.

Parameters:
port_typePort type
port_type_namePort type name

Definition at line 3506 of file hermon.c.

References HERMON_PORT_TYPE_ETH, HERMON_PORT_TYPE_IB, and HERMON_PORT_TYPE_UNKNOWN.

Referenced by hermon_sense_port_type().

                                                                            {
        switch ( port_type ) {
        case HERMON_PORT_TYPE_UNKNOWN:  return "unknown";
        case HERMON_PORT_TYPE_IB:       return "Infiniband";
        case HERMON_PORT_TYPE_ETH:      return "Ethernet";
        default:                        return "INVALID";
        }
}
static int hermon_sense_port_type ( struct hermon hermon,
struct hermon_port port 
) [static]

Sense port type.

Parameters:
hermonHermon device
portHermon port
Return values:
port_typePort type, or negative error

Definition at line 3522 of file hermon.c.

References hermon::cap, DBGC, hermon_dev_cap::dpdp, hermon_cmd_sense_port(), hermon_name_port_type(), HERMON_PORT_TYPE_IB, hermon_port::ibdev, MLX_GET, ib_device::port, rc, and strerror().

Referenced by hermon_set_port_type().

                                                               {
        struct ib_device *ibdev = port->ibdev;
        struct hermonprm_sense_port sense_port;
        int port_type;
        int rc;

        /* If DPDP is not supported, always assume Infiniband */
        if ( ! hermon->cap.dpdp ) {
                port_type = HERMON_PORT_TYPE_IB;
                DBGC ( hermon, "Hermon %p port %d does not support DPDP; "
                       "assuming an %s network\n", hermon, ibdev->port,
                       hermon_name_port_type ( port_type ) );
                return port_type;
        }

        /* Sense the port type */
        if ( ( rc = hermon_cmd_sense_port ( hermon, ibdev->port,
                                            &sense_port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d sense failed: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                return rc;
        }
        port_type = MLX_GET ( &sense_port, port_type );

        DBGC ( hermon, "Hermon %p port %d sensed an %s network\n",
               hermon, ibdev->port, hermon_name_port_type ( port_type ) );
        return port_type;
}
static int hermon_set_port_type ( struct hermon hermon,
struct hermon_port port 
) [static]

Set port type.

Parameters:
hermonHermon device
portHermon port
Return values:
rcReturn status code

Definition at line 3559 of file hermon.c.

References assert, currticks(), DBGC, EINVAL, hermon_cmd_query_port(), HERMON_PORT_TYPE_ETH, hermon_port_type_eth, HERMON_PORT_TYPE_IB, hermon_port_type_ib, HERMON_PORT_TYPE_UNKNOWN, HERMON_SENSE_PORT_TIMEOUT, hermon_sense_port_type(), hermon_port::ibdev, MLX_GET, NULL, ib_device::port, rc, start, strerror(), and hermon_port::type.

Referenced by hermon_probe().

                                                             {
        struct ib_device *ibdev = port->ibdev;
        struct hermonprm_query_port_cap query_port;
        int ib_supported;
        int eth_supported;
        int port_type;
        unsigned long start;
        unsigned long elapsed;
        int rc;

        /* Check to see which types are supported */
        if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
                                            &query_port ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
                       hermon, ibdev->port, strerror ( rc ) );
                return rc;
        }
        ib_supported = MLX_GET ( &query_port, ib );
        eth_supported = MLX_GET ( &query_port, eth );
        DBGC ( hermon, "Hermon %p port %d supports%s%s%s\n",
               hermon, ibdev->port, ( ib_supported ? " Infiniband" : "" ),
               ( ( ib_supported && eth_supported ) ? " and" : "" ),
               ( eth_supported ? " Ethernet" : "" ) );

        /* Sense network, if applicable */
        if ( ib_supported && eth_supported ) {

                /* Both types are supported; try sensing network */
                start = currticks();
                do {
                        /* Try sensing port */
                        port_type = hermon_sense_port_type ( hermon, port );
                        if ( port_type < 0 ) {
                                rc = port_type;
                                return rc;
                        }
                } while ( ( port_type == HERMON_PORT_TYPE_UNKNOWN ) &&
                          ( ( elapsed = ( currticks() - start ) ) <
                            HERMON_SENSE_PORT_TIMEOUT ) );

                /* Set port type based on sensed network, defaulting
                 * to Infiniband if nothing was sensed.
                 */
                switch ( port_type ) {
                case HERMON_PORT_TYPE_ETH:
                        port->type = &hermon_port_type_eth;
                        break;
                case HERMON_PORT_TYPE_IB:
                case HERMON_PORT_TYPE_UNKNOWN:
                        port->type = &hermon_port_type_ib;
                        break;
                default:
                        return -EINVAL;
                }

        } else if ( eth_supported ) {
                port->type = &hermon_port_type_eth;
        } else {
                port->type = &hermon_port_type_ib;
        }

        assert ( port->type != NULL );
        return 0;
}
static int hermon_bofm_harvest ( struct bofm_device bofm,
unsigned int  mport,
uint8_t mac 
) [static]

Harvest Ethernet MAC for BOFM.

Parameters:
bofmBOFM device
mportMulti-port index
macMAC to fill in
Return values:
rcReturn status code

Definition at line 3640 of file hermon.c.

References bytes, container_of, DBGC, ETH_ALEN, eth_ntoa(), hermon_mod_stat_cfg(), HERMON_MOD_STAT_CFG_OFFSET, HERMON_MOD_STAT_CFG_QUERY, htonl, memcpy(), MLX_GET, rc, and strerror().

                                                {
        struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
        struct hermonprm_mod_stat_cfg stat_cfg;
        union {
                uint8_t bytes[8];
                uint32_t dwords[2];
        } buf;
        int rc;

        /* Query static configuration */
        if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
                                          HERMON_MOD_STAT_CFG_QUERY,
                                          HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
                                          &stat_cfg ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not query "
                       "configuration: %s\n", hermon, mport, strerror ( rc ) );
                return rc;
        }

        /* Retrieve MAC address */
        buf.dwords[0] = htonl ( MLX_GET ( &stat_cfg, mac_high ) );
        buf.dwords[1] = htonl ( MLX_GET ( &stat_cfg, mac_low ) );
        memcpy ( mac, &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ],
                 ETH_ALEN );

        DBGC ( hermon, "Hermon %p port %d harvested MAC address %s\n",
               hermon, mport, eth_ntoa ( mac ) );

        return 0;
}
static int hermon_bofm_update ( struct bofm_device bofm,
unsigned int  mport,
const uint8_t mac 
) [static]

Update Ethernet MAC for BOFM.

Parameters:
bofmBOFM device
mportMulti-port index
macMAC to fill in
Return values:
rcReturn status code

Definition at line 3680 of file hermon.c.

References bytes, container_of, DBGC, ETH_ALEN, eth_ntoa(), hermon_mod_stat_cfg(), HERMON_MOD_STAT_CFG_OFFSET, HERMON_MOD_STAT_CFG_SET, memcpy(), memset(), MLX_FILL_1, MLX_FILL_2, ntohl, rc, and strerror().

                                                     {
        struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
        struct hermonprm_mod_stat_cfg stat_cfg;
        union {
                uint8_t bytes[8];
                uint32_t dwords[2];
        } buf;
        int rc;

        /* Prepare MAC address */
        memset ( &buf, 0, sizeof ( buf ) );
        memcpy ( &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ], mac,
                 ETH_ALEN );

        /* Modify static configuration */
        memset ( &stat_cfg, 0, sizeof ( stat_cfg ) );
        MLX_FILL_2 ( &stat_cfg, 36,
                     mac_m, 1,
                     mac_high, ntohl ( buf.dwords[0] ) );
        MLX_FILL_1 ( &stat_cfg, 37, mac_low, ntohl ( buf.dwords[1] ) );
        if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
                                          HERMON_MOD_STAT_CFG_SET,
                                          HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
                                          &stat_cfg ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p port %d could not modify "
                       "configuration: %s\n", hermon, mport, strerror ( rc ) );
                return rc;
        }

        DBGC ( hermon, "Hermon %p port %d updated MAC address to %s\n",
               hermon, mport, eth_ntoa ( mac ) );

        return 0;
}
static struct hermon* hermon_alloc ( void  ) [static, read]

Allocate Hermon device.

Parameters:
pciPCI device
idPCI ID
Return values:
rcReturn status code

Definition at line 3736 of file hermon.c.

References free, free_dma(), HERMON_MBOX_ALIGN, HERMON_MBOX_SIZE, hermon::mailbox_in, hermon::mailbox_out, malloc_dma(), NULL, and zalloc().

Referenced by hermon_bofm_probe(), and hermon_probe().

                                             {
        struct hermon *hermon;

        /* Allocate Hermon device */
        hermon = zalloc ( sizeof ( *hermon ) );
        if ( ! hermon )
                goto err_hermon;

        /* Allocate space for mailboxes */
        hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE,
                                          HERMON_MBOX_ALIGN );
        if ( ! hermon->mailbox_in )
                goto err_mailbox_in;
        hermon->mailbox_out = malloc_dma ( HERMON_MBOX_SIZE,
                                           HERMON_MBOX_ALIGN );
        if ( ! hermon->mailbox_out )
                goto err_mailbox_out;

        return hermon;

        free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
 err_mailbox_out:
        free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
 err_mailbox_in:
        free ( hermon );
 err_hermon:
        return NULL;
}
static void hermon_free ( struct hermon hermon) [static]

Free Hermon device.

Parameters:
hermonHermon device

Definition at line 3770 of file hermon.c.

References hermon::firmware_area, free, free_dma(), HERMON_MBOX_SIZE, hermon::icm, hermon::mailbox_in, hermon::mailbox_out, and ufree().

Referenced by hermon_bofm_probe(), hermon_bofm_remove(), hermon_probe(), and hermon_remove().

                                                  {

        ufree ( hermon->icm );
        ufree ( hermon->firmware_area );
        free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
        free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
        free ( hermon );
}
static int hermon_probe ( struct pci_device pci) [static]

Probe PCI device.

Parameters:
pciPCI device
idPCI ID
Return values:
rcReturn status code

Definition at line 3786 of file hermon.c.

References adjust_pci_device(), alloc_etherdev(), alloc_ibdev(), hermon::cap, hermon::config, pci_device::dev, net_device::dev, ib_device::dev, ENOMEM, hermon_alloc(), hermon_free(), hermon_get_cap(), hermon_ib_operations, HERMON_PAGE_SIZE, HERMON_PCI_CONFIG_BAR, HERMON_PCI_CONFIG_BAR_SIZE, HERMON_PCI_UAR_BAR, HERMON_PORT_BASE, hermon_reset(), hermon_set_port_type(), hermon_start(), hermon_start_firmware(), hermon_stop(), hermon_stop_firmware(), HERMON_UAR_NON_EQ_PAGE, HERMON_VPD_FIELD, ib_set_drvdata(), hermon_port::ibdev, ibdev_put(), ioremap(), iounmap(), netdev, hermon_port::netdev, netdev_init(), netdev_nullify(), netdev_put(), NULL, hermon_dev_cap::num_ports, hermon_port::nvo, nvs_vpd_init(), nvs_vpd_nvo_init(), hermon::nvsvpd, ib_device::op, hermon::open_count, hermon::pci, pci_bar_start(), pci_set_drvdata(), ib_device::port, port, hermon::port, net_device::priv, rc, hermon_port_type::register_dev, hermon_port::type, hermon::uar, and hermon_port_type::unregister_dev.

                                                   {
        struct hermon *hermon;
        struct ib_device *ibdev;
        struct net_device *netdev;
        struct hermon_port *port;
        unsigned int i;
        int rc;

        /* Allocate Hermon device */
        hermon = hermon_alloc();
        if ( ! hermon ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        pci_set_drvdata ( pci, hermon );
        hermon->pci = pci;

        /* Fix up PCI device */
        adjust_pci_device ( pci );

        /* Map PCI BARs */
        hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR ),
                                   HERMON_PCI_CONFIG_BAR_SIZE );
        hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ),
                                HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );

        /* Reset device */
        hermon_reset ( hermon );

        /* Start firmware */
        if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
                goto err_start_firmware;

        /* Get device limits */
        if ( ( rc = hermon_get_cap ( hermon ) ) != 0 )
                goto err_get_cap;

        /* Allocate Infiniband devices */
        for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
                ibdev = alloc_ibdev ( 0 );
                if ( ! ibdev ) {
                        rc = -ENOMEM;
                        goto err_alloc_ibdev;
                }
                hermon->port[i].ibdev = ibdev;
                ibdev->op = &hermon_ib_operations;
                ibdev->dev = &pci->dev;
                ibdev->port = ( HERMON_PORT_BASE + i );
                ib_set_drvdata ( ibdev, hermon );
        }

        /* Allocate network devices */
        for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
                netdev = alloc_etherdev ( 0 );
                if ( ! netdev ) {
                        rc = -ENOMEM;
                        goto err_alloc_netdev;
                }
                hermon->port[i].netdev = netdev;
                netdev_init ( netdev, &hermon_eth_operations );
                netdev->dev = &pci->dev;
                netdev->priv = &hermon->port[i];
        }

        /* Start device */
        if ( ( rc = hermon_start ( hermon, 1 ) ) != 0 )
                goto err_start;

        /* Determine port types */
        for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
                port = &hermon->port[i];
                if ( ( rc = hermon_set_port_type ( hermon, port ) ) != 0 )
                        goto err_set_port_type;
        }

        /* Initialise non-volatile storage */
        nvs_vpd_init ( &hermon->nvsvpd, pci );
        for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
                port = &hermon->port[i];
                nvs_vpd_nvo_init ( &hermon->nvsvpd,
                                   HERMON_VPD_FIELD ( port->ibdev->port ),
                                   &port->nvo, NULL );
        }

        /* Register devices */
        for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
                port = &hermon->port[i];
                if ( ( rc = port->type->register_dev ( hermon, port ) ) != 0 )
                        goto err_register;
        }

        /* Leave device quiescent until opened */
        if ( hermon->open_count == 0 )
                hermon_stop ( hermon );

        return 0;

        i = hermon->cap.num_ports;
 err_register:
        for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
                port = &hermon->port[i];
                port->type->unregister_dev ( hermon, port );
        }
 err_set_port_type:
        hermon_stop ( hermon );
 err_start:
        i = hermon->cap.num_ports;
 err_alloc_netdev:
        for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
                netdev_nullify ( hermon->port[i].netdev );
                netdev_put ( hermon->port[i].netdev );
        }
        i = hermon->cap.num_ports;
 err_alloc_ibdev:
        for ( i-- ; ( signed int ) i >= 0 ; i-- )
                ibdev_put ( hermon->port[i].ibdev );
 err_get_cap:
        hermon_stop_firmware ( hermon );
 err_start_firmware:
        iounmap ( hermon->uar );
        iounmap ( hermon->config );
        hermon_free ( hermon );
 err_alloc:
        return rc;
}
static void hermon_remove ( struct pci_device pci) [static]

Remove PCI device.

Parameters:
pciPCI device

Definition at line 3917 of file hermon.c.

References hermon::cap, hermon::config, hermon_free(), hermon_port::ibdev, ibdev_put(), iounmap(), hermon_port::netdev, netdev_nullify(), netdev_put(), hermon_dev_cap::num_ports, pci_get_drvdata(), port, hermon::port, hermon_port::type, hermon::uar, and hermon_port_type::unregister_dev.

                                                     {
        struct hermon *hermon = pci_get_drvdata ( pci );
        struct hermon_port *port;
        int i;

        for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
                port = &hermon->port[i];
                port->type->unregister_dev ( hermon, port );
        }
        for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
                netdev_nullify ( hermon->port[i].netdev );
                netdev_put ( hermon->port[i].netdev );
        }
        for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- )
                ibdev_put ( hermon->port[i].ibdev );
        iounmap ( hermon->uar );
        iounmap ( hermon->config );
        hermon_free ( hermon );
}
static int hermon_bofm_probe ( struct pci_device pci) [static]

Probe PCI device for BOFM.

Parameters:
pciPCI device
idPCI ID
Return values:
rcReturn status code

Definition at line 3944 of file hermon.c.

References adjust_pci_device(), hermon::bofm, bofm_init(), bofm_register(), hermon::config, DBGC, ENOMEM, hermon_alloc(), hermon_free(), HERMON_PCI_CONFIG_BAR, HERMON_PCI_CONFIG_BAR_SIZE, ioremap(), iounmap(), hermon::pci, pci_bar_start(), pci_set_drvdata(), rc, and strerror().

                                                        {
        struct hermon *hermon;
        int rc;

        /* Allocate Hermon device */
        hermon = hermon_alloc();
        if ( ! hermon ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        pci_set_drvdata ( pci, hermon );
        hermon->pci = pci;

        /* Fix up PCI device */
        adjust_pci_device ( pci );

        /* Map PCI BAR */
        hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR ),
                                   HERMON_PCI_CONFIG_BAR_SIZE );

        /* Initialise BOFM device */
        bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );

        /* Register BOFM device */
        if ( ( rc = bofm_register ( &hermon->bofm ) ) != 0 ) {
                DBGC ( hermon, "Hermon %p could not register BOFM device: "
                       "%s\n", hermon, strerror ( rc ) );
                goto err_bofm_register;
        }

        return 0;

 err_bofm_register:
        iounmap ( hermon->config );
        hermon_free ( hermon );
 err_alloc:
        return rc;
}
static void hermon_bofm_remove ( struct pci_device pci) [static]

Remove PCI device for BOFM.

Parameters:
pciPCI device

Definition at line 3988 of file hermon.c.

References hermon::bofm, bofm_unregister(), hermon::config, hermon_free(), iounmap(), and pci_get_drvdata().

                                                          {
        struct hermon *hermon = pci_get_drvdata ( pci );

        bofm_unregister ( &hermon->bofm );
        iounmap ( hermon->config );
        hermon_free ( hermon );
}

Variable Documentation

uint8_t hermon_qp_st[] [static]
Initial value:

Queue pair transport service type map.

Definition at line 1070 of file hermon.c.

unsigned int( * hermon_fill_send_wqe[])(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe) [static]
Initial value:

Work queue entry constructors.

Definition at line 1566 of file hermon.c.

Referenced by hermon_post_send().

Initial value:
 {
        .create_cq      = hermon_create_cq,
        .destroy_cq     = hermon_destroy_cq,
        .create_qp      = hermon_create_qp,
        .modify_qp      = hermon_modify_qp,
        .destroy_qp     = hermon_destroy_qp,
        .post_send      = hermon_post_send,
        .post_recv      = hermon_post_recv,
        .poll_cq        = hermon_poll_cq,
        .poll_eq        = hermon_poll_eq,
        .open           = hermon_ib_open,
        .close          = hermon_ib_close,
        .mcast_attach   = hermon_mcast_attach,
        .mcast_detach   = hermon_mcast_detach,
        .set_port_info  = hermon_inform_sma,
        .set_pkey_table = hermon_inform_sma,
}

Hermon Infiniband operations.

Definition at line 3053 of file hermon.c.

Referenced by hermon_probe().

Initial value:
 {
        .register_dev = hermon_register_ibdev,
        .state_change = hermon_state_change_ibdev,
        .unregister_dev = hermon_unregister_ibdev,
}

Hermon Infiniband port type.

Definition at line 3126 of file hermon.c.

Referenced by hermon_set_port_type().

Initial value:
 {
        .alloc_iob = alloc_iob,
}

Hermon Ethernet queue pair operations.

Definition at line 3174 of file hermon.c.

Initial value:
 {
        .complete_send = hermon_eth_complete_send,
        .complete_recv = hermon_eth_complete_recv,
}

Hermon Ethernet device completion operations.

Definition at line 3230 of file hermon.c.

Initial value:
 {
        .open           = hermon_eth_open,
        .close          = hermon_eth_close,
        .transmit       = hermon_eth_transmit,
        .poll           = hermon_eth_poll,
}

Hermon Ethernet network device operations.

Definition at line 3387 of file hermon.c.

Initial value:
 {
        .register_dev = hermon_register_netdev,
        .state_change = hermon_state_change_netdev,
        .unregister_dev = hermon_unregister_netdev,
}

Hermon Ethernet port type.

Definition at line 3484 of file hermon.c.

Referenced by hermon_set_port_type().

Initial value:
 {
        .harvest = hermon_bofm_harvest,
        .update = hermon_bofm_update,
}

Hermon BOFM operations.

Definition at line 3717 of file hermon.c.

struct pci_device_id hermon_nics[] [static]
Initial value:
 {
        PCI_ROM ( 0x15b3, 0x6340, "mt25408", "MT25408 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x634a, "mt25418", "MT25418 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6732, "mt26418", "MT26418 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x673c, "mt26428", "MT26428 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6746, "mt26438", "MT26438 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6778, "mt26488", "MT26488 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6368, "mt25448", "MT25448 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6750, "mt26448", "MT26448 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6372, "mt25458", "MT25458 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x675a, "mt26458", "MT26458 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x6764, "mt26468", "MT26468 HCA driver", 0 ),
        PCI_ROM ( 0x15b3, 0x676e, "mt26478", "MT26478 HCA driver", 0 ),
}

Definition at line 3996 of file hermon.c.

struct pci_driver hermon_driver __pci_driver
Initial value:
 {
        .ids = hermon_nics,
        .id_count = ( sizeof ( hermon_nics ) / sizeof ( hermon_nics[0] ) ),
        .probe = hermon_probe,
        .remove = hermon_remove,
}

Definition at line 4011 of file hermon.c.

struct pci_driver hermon_bofm_driver __bofm_driver
Initial value:
 {
        .ids = hermon_nics,
        .id_count = ( sizeof ( hermon_nics ) / sizeof ( hermon_nics[0] ) ),
        .probe = hermon_bofm_probe,
        .remove = hermon_bofm_remove,
}

Definition at line 4018 of file hermon.c.