iPXE
Data Structures | Defines | Functions | Variables
linda.c File Reference

QLogic Linda Infiniband HCA. More...

#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <ipxe/io.h>
#include <ipxe/pci.h>
#include <ipxe/infiniband.h>
#include <ipxe/i2c.h>
#include <ipxe/bitbash.h>
#include <ipxe/malloc.h>
#include <ipxe/iobuf.h>
#include "linda.h"

Go to the source code of this file.

Data Structures

struct  linda_send_work_queue
 A Linda send work queue. More...
struct  linda_recv_work_queue
 A Linda receive work queue. More...
struct  linda
 A Linda HCA. More...
struct  linda_serdes_param
 A Linda SerDes parameter. More...

Defines

#define linda_readq(_linda, _ptr, _offset)   linda_readq ( (_linda), (_ptr)->u.qwords, (_offset) )
#define linda_readq_array8b(_linda, _ptr, _offset, _idx)   linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )
#define linda_readq_array64k(_linda, _ptr, _offset, _idx)   linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )
#define linda_writeq(_linda, _ptr, _offset)   linda_writeq ( (_linda), (_ptr)->u.qwords, (_offset) )
#define linda_writeq_array8b(_linda, _ptr, _offset, _idx)   linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )
#define linda_writeq_array64k(_linda, _ptr, _offset, _idx)   linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )
#define LINDA_SEND_BUF_TOGGLE   0x80
 Send buffer toggle bit.
#define LINDA_EPB_ALL_CHANNELS   31
 Magic "all channels" channel number.
#define LINDA_SERDES_PARAM_END   { 0, 0, 0 }
 End of SerDes parameter list marker.
#define LINDA_DDS_VAL(amp_d, main_d, ipst_d, ipre_d,amp_s, main_s, ipst_s, ipre_s)

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static void linda_readq (struct linda *linda, uint64_t *qword, unsigned long offset)
 Read Linda qword register.
static void linda_writeq (struct linda *linda, const uint64_t *qword, unsigned long offset)
 Write Linda qword register.
static void linda_writel (struct linda *linda, uint32_t dword, unsigned long offset)
 Write Linda dword register.
static const char * linda_link_state_text (unsigned int link_state)
 Textual representation of link state.
static void linda_link_state_changed (struct ib_device *ibdev)
 Handle link state change.
static int linda_link_state_check (struct linda *linda, unsigned int new_link_state)
 Wait for link state change to take effect.
static int linda_set_port_info (struct ib_device *ibdev, union ib_mad *mad)
 Set port information.
static int linda_set_pkey_table (struct ib_device *ibdev __unused, union ib_mad *mad __unused)
 Set partition key table.
static int linda_ctx_to_qpn (unsigned int ctx)
 Map context number to QPN.
static int linda_qpn_to_ctx (unsigned int qpn)
 Map QPN to context number.
static int linda_alloc_ctx (struct linda *linda)
 Allocate a context.
static void linda_free_ctx (struct linda *linda, unsigned int ctx)
 Free a context.
static unsigned int linda_alloc_send_buf (struct linda *linda)
 Allocate a send buffer.
static void linda_free_send_buf (struct linda *linda, unsigned int send_buf)
 Free a send buffer.
static int linda_send_buf_in_use (struct linda *linda, unsigned int send_buf)
 Check to see if send buffer is in use.
static unsigned long linda_send_buffer_offset (struct linda *linda, unsigned int send_buf)
 Calculate starting offset for send buffer.
static int linda_create_send_wq (struct linda *linda, struct ib_queue_pair *qp)
 Create send work queue.
static void linda_destroy_send_wq (struct linda *linda, struct ib_queue_pair *qp)
 Destroy send work queue.
static int linda_init_send (struct linda *linda)
 Initialise send datapath.
static void linda_fini_send (struct linda *linda)
 Shut down send datapath.
static int linda_create_recv_wq (struct linda *linda, struct ib_queue_pair *qp)
 Create receive work queue.
static void linda_destroy_recv_wq (struct linda *linda, struct ib_queue_pair *qp)
 Destroy receive work queue.
static int linda_init_recv (struct linda *linda)
 Initialise receive datapath.
static void linda_fini_recv (struct linda *linda __unused)
 Shut down receive datapath.
static int linda_create_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Create completion queue.
static void linda_destroy_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Destroy completion queue.
static int linda_create_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Create queue pair.
static int linda_modify_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Modify queue pair.
static void linda_destroy_qp (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Destroy queue pair.
static int linda_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 void linda_complete_send (struct ib_device *ibdev, struct ib_queue_pair *qp, unsigned int wqe_idx)
 Complete send work queue entry.
static void linda_poll_send_wq (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Poll send work queue.
static int linda_post_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf)
 Post receive work queue entry.
static void linda_complete_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, unsigned int header_offs)
 Complete receive work queue entry.
static void linda_poll_recv_wq (struct ib_device *ibdev, struct ib_queue_pair *qp)
 Poll receive work queue.
static void linda_poll_cq (struct ib_device *ibdev, struct ib_completion_queue *cq)
 Poll completion queue.
static void linda_poll_eq (struct ib_device *ibdev)
 Poll event queue.
static int linda_open (struct ib_device *ibdev)
 Initialise Infiniband link.
static void linda_close (struct ib_device *ibdev)
 Close Infiniband link.
static int linda_mcast_attach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
 Attach to multicast group.
static void linda_mcast_detach (struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
 Detach from multicast group.
static int linda_i2c_read_bit (struct bit_basher *basher, unsigned int bit_id)
 Read Linda I2C line status.
static void linda_i2c_write_bit (struct bit_basher *basher, unsigned int bit_id, unsigned long data)
 Write Linda I2C line status.
static int linda_init_i2c (struct linda *linda)
 Initialise Linda I2C subsystem.
static int linda_read_eeprom (struct linda *linda, union ib_guid *guid)
 Read EEPROM parameters.
static int linda_ib_epb_request (struct linda *linda)
 Request ownership of the IB external parallel bus.
static int linda_ib_epb_wait (struct linda *linda, struct QIB_7220_ibsd_epb_transaction_reg *xact)
 Wait for IB external parallel bus transaction to complete.
static void linda_ib_epb_release (struct linda *linda)
 Release ownership of the IB external parallel bus.
static int linda_ib_epb_read (struct linda *linda, unsigned int location)
 Read data via IB external parallel bus.
static int linda_ib_epb_write (struct linda *linda, unsigned int location, unsigned int data)
 Write data via IB external parallel bus.
static int linda_ib_epb_mod_reg (struct linda *linda, unsigned int cs, unsigned int channel, unsigned int element, unsigned int reg, unsigned int value, unsigned int mask)
 Read/modify/write EPB register.
static int linda_ib_epb_ram_xfer (struct linda *linda, unsigned int address, const void *write, void *read, size_t len)
 Transfer data to/from microcontroller RAM.
static int linda_set_serdes_param (struct linda *linda, struct linda_serdes_param *param)
 Program IB SerDes register(s)
static int linda_set_serdes_params (struct linda *linda, struct linda_serdes_param *params)
 Program IB SerDes registers.
static int linda_program_uc_ram (struct linda *linda)
 Program the microcontroller RAM.
static int linda_verify_uc_ram (struct linda *linda)
 Verify the microcontroller RAM.
static int linda_trim_ib (struct linda *linda)
 Use the microcontroller to trim the IB link.
static int linda_init_ib_serdes (struct linda *linda)
 Initialise the IB SerDes.
static int linda_probe (struct pci_device *pci)
 Probe PCI device.
static void linda_remove (struct pci_device *pci)
 Remove PCI device.

Variables

static struct ib_device_operations linda_ib_operations
 Linda Infiniband operations.
static unsigned int linda_i2c_bits []
 Linda I2C bit to GPIO mappings.
static struct bit_basher_operations linda_i2c_basher_ops
 Linda I2C bit-bashing interface operations.
struct linda_serdes_param __packed
static struct linda_serdes_param linda_serdes_defaults1 []
 Linda SerDes default parameters.
static struct linda_serdes_param linda_serdes_defaults2 []
static struct linda_serdes_param linda_serdes_defaults3 []
static struct pci_device_id linda_nics []
struct pci_driver linda_driver __pci_driver

Detailed Description

QLogic Linda Infiniband HCA.

Definition in file linda.c.


Define Documentation

#define linda_readq (   _linda,
  _ptr,
  _offset 
)    linda_readq ( (_linda), (_ptr)->u.qwords, (_offset) )
#define linda_readq_array8b (   _linda,
  _ptr,
  _offset,
  _idx 
)    linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )

Definition at line 130 of file linda.c.

#define linda_readq_array64k (   _linda,
  _ptr,
  _offset,
  _idx 
)    linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )

Definition at line 132 of file linda.c.

#define linda_writeq (   _linda,
  _ptr,
  _offset 
)    linda_writeq ( (_linda), (_ptr)->u.qwords, (_offset) )
#define linda_writeq_array8b (   _linda,
  _ptr,
  _offset,
  _idx 
)    linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )

Definition at line 148 of file linda.c.

Referenced by linda_complete_recv(), linda_create_recv_wq(), and linda_post_recv().

#define linda_writeq_array64k (   _linda,
  _ptr,
  _offset,
  _idx 
)    linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )

Definition at line 150 of file linda.c.

Referenced by linda_create_recv_wq(), linda_poll_recv_wq(), and linda_post_recv().

#define LINDA_SEND_BUF_TOGGLE   0x80

Send buffer toggle bit.

We encode send buffers as 7 bits of send buffer index plus a single bit which should match the "check" bit in the SendBufAvail array.

Definition at line 378 of file linda.c.

Referenced by linda_alloc_send_buf(), linda_send_buf_in_use(), and linda_send_buffer_offset().

#define LINDA_EPB_ALL_CHANNELS   31

Magic "all channels" channel number.

Definition at line 1985 of file linda.c.

Referenced by linda_set_serdes_param().

#define LINDA_SERDES_PARAM_END   { 0, 0, 0 }

End of SerDes parameter list marker.

Definition at line 1988 of file linda.c.

#define LINDA_DDS_VAL (   amp_d,
  main_d,
  ipst_d,
  ipre_d,
  amp_s,
  main_s,
  ipst_s,
  ipre_s 
)
Value:
{ LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x00 ),        \
          ( ( ( amp_d & 0x1f ) << 1 ) | 1 ), 0xff },                    \
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x01 ),        \
          ( ( ( amp_s & 0x1f ) << 1 ) | 1 ), 0xff },                    \
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x09 ),        \
          ( ( main_d << 3 ) | 4 | ( ipre_d >> 2 ) ), 0xff },            \
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x0a ),        \
          ( ( main_s << 3 ) | 4 | ( ipre_s >> 2 ) ), 0xff },            \
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x06 ),        \
          ( ( ( ipst_d & 0xf ) << 1 ) |                                 \
            ( ( ipre_d & 3 ) << 6 ) | 0x21 ), 0xff },                   \
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x07 ),        \
          ( ( ( ipst_s & 0xf ) << 1 ) |                                 \
            ( ( ipre_s & 3 ) << 6) | 0x21 ), 0xff }

Definition at line 2050 of file linda.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static void linda_readq ( struct linda linda,
uint64_t qword,
unsigned long  offset 
) [static]

Read Linda qword register.

Parameters:
lindaLinda device
qwordRegister buffer to read into
offsetRegister offset

Definition at line 124 of file linda.c.

References readq(), and linda::regs.

                                                 {
        *qword = readq ( linda->regs + offset );
}
static void linda_writeq ( struct linda linda,
const uint64_t qword,
unsigned long  offset 
) [static]

Write Linda qword register.

Parameters:
lindaLinda device
qwordRegister buffer to write
offsetRegister offset

Definition at line 142 of file linda.c.

References linda::regs, and writeq().

                                                  {
        writeq ( *qword, ( linda->regs + offset ) );
}
static void linda_writel ( struct linda linda,
uint32_t  dword,
unsigned long  offset 
) [static]

Write Linda dword register.

Parameters:
lindaLinda device
dwordValue to write
offsetRegister offset

Definition at line 160 of file linda.c.

References linda::regs, and writel().

Referenced by linda_post_send().

                                                  {
        writel ( dword, ( linda->regs + offset ) );
}
static const char* linda_link_state_text ( unsigned int  link_state) [static]

Textual representation of link state.

Parameters:
link_stateLink state
Return values:
link_textLink state text

Definition at line 178 of file linda.c.

References LINDA_LINK_STATE_ACT_DEFER, LINDA_LINK_STATE_ACTIVE, LINDA_LINK_STATE_ARM, LINDA_LINK_STATE_DOWN, and LINDA_LINK_STATE_INIT.

Referenced by linda_link_state_changed(), linda_link_state_check(), and linda_set_port_info().

                                                                      {
        switch ( link_state ) {
        case LINDA_LINK_STATE_DOWN:     return "DOWN";
        case LINDA_LINK_STATE_INIT:     return "INIT";
        case LINDA_LINK_STATE_ARM:      return "ARM";
        case LINDA_LINK_STATE_ACTIVE:   return "ACTIVE";
        case LINDA_LINK_STATE_ACT_DEFER:return "ACT_DEFER";
        default:                        return "UNKNOWN";
        }
}
static void linda_link_state_changed ( struct ib_device ibdev) [static]

Handle link state change.

Parameters:
lindaLinda device

Definition at line 194 of file linda.c.

References BIT_GET, BIT_SET, DBGC, ib_get_drvdata(), IB_LINK_SPEED_DDR, IB_LINK_SPEED_SDR, ib_link_state_changed(), IB_LINK_WIDTH_1X, IB_LINK_WIDTH_4X, LINDA_LINK_STATE_ACTIVE, LINDA_LINK_STATE_INIT, linda_link_state_text(), linda_readq, linda_writeq, ib_device::link_speed_active, ib_device::link_width_active, ib_device::port_state, QIB_7220_EXTCtrl_offset, and QIB_7220_IBCStatus_offset.

Referenced by linda_poll_eq(), and linda_set_port_info().

                                                                 {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct QIB_7220_IBCStatus ibcstatus;
        struct QIB_7220_EXTCtrl extctrl;
        unsigned int link_state;
        unsigned int link_width;
        unsigned int link_speed;

        /* Read link state */
        linda_readq ( linda, &ibcstatus, QIB_7220_IBCStatus_offset );
        link_state = BIT_GET ( &ibcstatus, LinkState );
        link_width = BIT_GET ( &ibcstatus, LinkWidthActive );
        link_speed = BIT_GET ( &ibcstatus, LinkSpeedActive );
        DBGC ( linda, "Linda %p link state %s (%s %s)\n", linda,
               linda_link_state_text ( link_state ),
               ( link_speed ? "DDR" : "SDR" ), ( link_width ? "x4" : "x1" ) );

        /* Set LEDs according to link state */
        linda_readq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
        BIT_SET ( &extctrl, LEDPriPortGreenOn,
                  ( ( link_state >= LINDA_LINK_STATE_INIT ) ? 1 : 0 ) );
        BIT_SET ( &extctrl, LEDPriPortYellowOn,
                  ( ( link_state >= LINDA_LINK_STATE_ACTIVE ) ? 1 : 0 ) );
        linda_writeq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );

        /* Notify Infiniband core of link state change */
        ibdev->port_state = ( link_state + 1 );
        ibdev->link_width_active =
                ( link_width ? IB_LINK_WIDTH_4X : IB_LINK_WIDTH_1X );
        ibdev->link_speed_active =
                ( link_speed ? IB_LINK_SPEED_DDR : IB_LINK_SPEED_SDR );
        ib_link_state_changed ( ibdev );
}
static int linda_link_state_check ( struct linda linda,
unsigned int  new_link_state 
) [static]

Wait for link state change to take effect.

Parameters:
lindaLinda device
new_link_stateExpected link state
Return values:
rcReturn status code

Definition at line 235 of file linda.c.

References BIT_GET, DBGC, ETIMEDOUT, LINDA_LINK_STATE_MAX_WAIT_US, linda_link_state_text(), linda_readq, QIB_7220_IBCStatus_offset, and udelay().

Referenced by linda_set_port_info().

                                                                  {
        struct QIB_7220_IBCStatus ibcstatus;
        unsigned int link_state;
        unsigned int i;

        for ( i = 0 ; i < LINDA_LINK_STATE_MAX_WAIT_US ; i++ ) {
                linda_readq ( linda, &ibcstatus, QIB_7220_IBCStatus_offset );
                link_state = BIT_GET ( &ibcstatus, LinkState );
                if ( link_state == new_link_state )
                        return 0;
                udelay ( 1 );
        }

        DBGC ( linda, "Linda %p timed out waiting for link state %s\n",
               linda, linda_link_state_text ( link_state ) );
        return -ETIMEDOUT;
}
static int linda_set_port_info ( struct ib_device ibdev,
union ib_mad mad 
) [static]

Set port information.

Parameters:
ibdevInfiniband device
madSet port information MAD

Definition at line 260 of file linda.c.

References BIT_SET, DBGC, ib_get_drvdata(), linda_link_state_changed(), linda_link_state_check(), linda_link_state_text(), linda_readq, linda_writeq, ib_port_info::link_speed_supported__port_state, ib_smp_data::port_info, port_info, port_state, QIB_7220_IBCCtrl_offset, ib_mad::smp, and ib_mad_smp::smp_data.

                                                                              {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
        struct QIB_7220_IBCCtrl ibcctrl;
        unsigned int port_state;
        unsigned int link_state;

        /* Set new link state */
        port_state = ( port_info->link_speed_supported__port_state & 0xf );
        if ( port_state ) {
                link_state = ( port_state - 1 );
                DBGC ( linda, "Linda %p set link state to %s (%x)\n", linda,
                       linda_link_state_text ( link_state ), link_state );
                linda_readq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
                BIT_SET ( &ibcctrl, LinkCmd, link_state );
                linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );

                /* Wait for link state change to take effect.  Ignore
                 * errors; the current link state will be returned via
                 * the GetResponse MAD.
                 */
                linda_link_state_check ( linda, link_state );
        }

        /* Detect and report link state change */
        linda_link_state_changed ( ibdev );

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

Set partition key table.

Parameters:
ibdevInfiniband device
madSet partition key table MAD

Definition at line 296 of file linda.c.

                                                               {
        /* Nothing to do */
        return 0;
}
static int linda_ctx_to_qpn ( unsigned int  ctx) [static]

Map context number to QPN.

Parameters:
ctxContext index
Return values:
qpnQueue pair number

Definition at line 315 of file linda.c.

Referenced by linda_create_qp().

                                                 {
        /* This mapping is fixed by hardware */
        return ( ctx * 2 );
}
static int linda_qpn_to_ctx ( unsigned int  qpn) [static]

Map QPN to context number.

Parameters:
qpnQueue pair number
Return values:
ctxContext index

Definition at line 326 of file linda.c.

Referenced by linda_create_recv_wq(), linda_destroy_recv_wq(), linda_poll_recv_wq(), and linda_post_recv().

                                                 {
        /* This mapping is fixed by hardware */
        return ( qpn / 2 );
}
static int linda_alloc_ctx ( struct linda linda) [static]

Allocate a context.

Parameters:
lindaLinda device
Return values:
ctxContext index, or negative error

Definition at line 337 of file linda.c.

References ctx, DBGC, DBGC2, ENOENT, LINDA_NUM_CONTEXTS, and linda::used_ctx.

Referenced by linda_create_qp().

                                                   {
        unsigned int ctx;

        for ( ctx = 0 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) {

                if ( ! linda->used_ctx[ctx] ) {
                        linda->used_ctx[ctx ] = 1;
                        DBGC2 ( linda, "Linda %p CTX %d allocated\n",
                                linda, ctx );
                        return ctx;
                }
        }

        DBGC ( linda, "Linda %p out of available contexts\n", linda );
        return -ENOENT;
}
static void linda_free_ctx ( struct linda linda,
unsigned int  ctx 
) [static]

Free a context.

Parameters:
lindaLinda device
ctxContext index

Definition at line 360 of file linda.c.

References ctx, DBGC2, and linda::used_ctx.

Referenced by linda_create_qp(), and linda_destroy_recv_wq().

                                                                     {

        linda->used_ctx[ctx] = 0;
        DBGC2 ( linda, "Linda %p CTX %d freed\n", linda, ctx );
}
static unsigned int linda_alloc_send_buf ( struct linda linda) [static]

Allocate a send buffer.

Parameters:
lindaLinda device
Return values:
send_bufSend buffer

You must guarantee that a send buffer is available. This is done by refusing to allocate more TX WQEs in total than the number of available send buffers.

Definition at line 390 of file linda.c.

References LINDA_MAX_SEND_BUFS, LINDA_SEND_BUF_TOGGLE, linda::send_buf, and linda::send_buf_cons.

Referenced by linda_post_send().

                                                                 {
        unsigned int send_buf;

        send_buf = linda->send_buf[linda->send_buf_cons];
        send_buf ^= LINDA_SEND_BUF_TOGGLE;
        linda->send_buf_cons = ( ( linda->send_buf_cons + 1 ) %
                                 LINDA_MAX_SEND_BUFS );
        return send_buf;
}
static void linda_free_send_buf ( struct linda linda,
unsigned int  send_buf 
) [static]

Free a send buffer.

Parameters:
lindaLinda device
send_bufSend buffer

Definition at line 406 of file linda.c.

References LINDA_MAX_SEND_BUFS, linda::send_buf, and linda::send_buf_prod.

Referenced by linda_complete_send().

                                                          {
        linda->send_buf[linda->send_buf_prod] = send_buf;
        linda->send_buf_prod = ( ( linda->send_buf_prod + 1 ) %
                                 LINDA_MAX_SEND_BUFS );
}
static int linda_send_buf_in_use ( struct linda linda,
unsigned int  send_buf 
) [static]

Check to see if send buffer is in use.

Parameters:
lindaLinda device
send_bufSend buffer
Return values:
in_useSend buffer is in use

Definition at line 420 of file linda.c.

References BIT_GET, LINDA_SEND_BUF_TOGGLE, and linda::sendbufavail.

Referenced by linda_poll_send_wq().

                                                           {
        unsigned int send_idx;
        unsigned int send_check;
        unsigned int inusecheck;
        unsigned int inuse;
        unsigned int check;

        send_idx = ( send_buf & ~LINDA_SEND_BUF_TOGGLE );
        send_check = ( !! ( send_buf & LINDA_SEND_BUF_TOGGLE ) );
        inusecheck = BIT_GET ( linda->sendbufavail, InUseCheck[send_idx] );
        inuse = ( !! ( inusecheck & 0x02 ) );
        check = ( !! ( inusecheck & 0x01 ) );
        return ( inuse || ( check != send_check ) );
}
static unsigned long linda_send_buffer_offset ( struct linda linda,
unsigned int  send_buf 
) [static]

Calculate starting offset for send buffer.

Parameters:
lindaLinda device
send_bufSend buffer
Return values:
offsetStarting offset

Definition at line 443 of file linda.c.

References LINDA_SEND_BUF_SIZE, LINDA_SEND_BUF_TOGGLE, and linda::send_buffer_base.

Referenced by linda_post_send().

                                                                        {
        return ( linda->send_buffer_base +
                 ( ( send_buf & ~LINDA_SEND_BUF_TOGGLE ) *
                   LINDA_SEND_BUF_SIZE ) );
}
static int linda_create_send_wq ( struct linda linda,
struct ib_queue_pair qp 
) [static]

Create send work queue.

Parameters:
lindaLinda device
qpQueue pair

Definition at line 456 of file linda.c.

References linda_send_work_queue::cons, DBGC, ENOBUFS, free, ib_wq_get_drvdata(), LINDA_MAX_SEND_BUFS, ib_work_queue::num_wqes, linda_send_work_queue::prod, rc, linda::reserved_send_bufs, ib_queue_pair::send, linda_send_work_queue::send_buf, and zalloc().

Referenced by linda_create_qp().

                                                             {
        struct ib_work_queue *wq = &qp->send;
        struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        int rc;

        /* Reserve send buffers */
        if ( ( linda->reserved_send_bufs + qp->send.num_wqes ) >
             LINDA_MAX_SEND_BUFS ) {
                DBGC ( linda, "Linda %p out of send buffers (have %d, used "
                       "%d, need %d)\n", linda, LINDA_MAX_SEND_BUFS,
                       linda->reserved_send_bufs, qp->send.num_wqes );
                rc = -ENOBUFS;
                goto err_reserve_bufs;
        }
        linda->reserved_send_bufs += qp->send.num_wqes;

        /* Reset work queue */
        linda_wq->prod = 0;
        linda_wq->cons = 0;

        /* Allocate space for send buffer uasge list */
        linda_wq->send_buf = zalloc ( qp->send.num_wqes *
                                      sizeof ( linda_wq->send_buf[0] ) );
        if ( ! linda_wq->send_buf ) {
                rc = -ENOBUFS;
                goto err_alloc_send_buf;
        }

        return 0;

        free ( linda_wq->send_buf );
 err_alloc_send_buf:
        linda->reserved_send_bufs -= qp->send.num_wqes;
 err_reserve_bufs:
        return rc;
}
static void linda_destroy_send_wq ( struct linda linda,
struct ib_queue_pair qp 
) [static]

Destroy send work queue.

Parameters:
lindaLinda device
qpQueue pair

Definition at line 500 of file linda.c.

References free, ib_wq_get_drvdata(), ib_work_queue::num_wqes, linda::reserved_send_bufs, ib_queue_pair::send, and linda_send_work_queue::send_buf.

Referenced by linda_create_qp(), and linda_destroy_qp().

                                                               {
        struct ib_work_queue *wq = &qp->send;
        struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );

        free ( linda_wq->send_buf );
        linda->reserved_send_bufs -= qp->send.num_wqes;
}
static int linda_init_send ( struct linda linda) [static]

Initialise send datapath.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 515 of file linda.c.

References BIT_FILL_1, BIT_FILL_2, BIT_GET, DBGC, ENOMEM, free_dma(), LINDA_MAX_SEND_BUFS, linda_readq, LINDA_SENDBUFAVAIL_ALIGN, linda_writeq, malloc_dma(), memset(), QIB_7220_SendBufAvailAddr_offset, QIB_7220_SendBufBase_offset, QIB_7220_SendCtrl_offset, rc, linda::send_buf, linda::send_buffer_base, linda::sendbufavail, and virt_to_bus().

Referenced by linda_probe().

                                                   {
        struct QIB_7220_SendBufBase sendbufbase;
        struct QIB_7220_SendBufAvailAddr sendbufavailaddr;
        struct QIB_7220_SendCtrl sendctrl;
        unsigned int i;
        int rc;

        /* Retrieve SendBufBase */
        linda_readq ( linda, &sendbufbase, QIB_7220_SendBufBase_offset );
        linda->send_buffer_base = BIT_GET ( &sendbufbase,
                                            BaseAddr_SmallPIO );
        DBGC ( linda, "Linda %p send buffers at %lx\n",
               linda, linda->send_buffer_base );

        /* Initialise the send_buf[] array */
        for ( i = 0 ; i < LINDA_MAX_SEND_BUFS ; i++ )
                linda->send_buf[i] = i;

        /* Allocate space for the SendBufAvail array */
        linda->sendbufavail = malloc_dma ( sizeof ( *linda->sendbufavail ),
                                           LINDA_SENDBUFAVAIL_ALIGN );
        if ( ! linda->sendbufavail ) {
                rc = -ENOMEM;
                goto err_alloc_sendbufavail;
        }
        memset ( linda->sendbufavail, 0, sizeof ( *linda->sendbufavail ) );

        /* Program SendBufAvailAddr into the hardware */
        memset ( &sendbufavailaddr, 0, sizeof ( sendbufavailaddr ) );
        BIT_FILL_1 ( &sendbufavailaddr, SendBufAvailAddr,
                     ( virt_to_bus ( linda->sendbufavail ) >> 6 ) );
        linda_writeq ( linda, &sendbufavailaddr,
                       QIB_7220_SendBufAvailAddr_offset );

        /* Enable sending and DMA of SendBufAvail */
        memset ( &sendctrl, 0, sizeof ( sendctrl ) );
        BIT_FILL_2 ( &sendctrl,
                     SendBufAvailUpd, 1,
                     SPioEnable, 1 );
        linda_writeq ( linda, &sendctrl, QIB_7220_SendCtrl_offset );

        return 0;

        free_dma ( linda->sendbufavail, sizeof ( *linda->sendbufavail ) );
 err_alloc_sendbufavail:
        return rc;
}
static void linda_fini_send ( struct linda linda) [static]

Shut down send datapath.

Parameters:
lindaLinda device

Definition at line 568 of file linda.c.

References free_dma(), linda_readq, linda_writeq, mb(), memset(), QIB_7220_SendCtrl_offset, and linda::sendbufavail.

Referenced by linda_probe(), and linda_remove().

                                                    {
        struct QIB_7220_SendCtrl sendctrl;

        /* Disable sending and DMA of SendBufAvail */
        memset ( &sendctrl, 0, sizeof ( sendctrl ) );
        linda_writeq ( linda, &sendctrl, QIB_7220_SendCtrl_offset );
        mb();

        /* Ensure hardware has seen this disable */
        linda_readq ( linda, &sendctrl, QIB_7220_SendCtrl_offset );

        free_dma ( linda->sendbufavail, sizeof ( *linda->sendbufavail ) );
}
static int linda_create_recv_wq ( struct linda linda,
struct ib_queue_pair qp 
) [static]

Create receive work queue.

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

Definition at line 596 of file linda.c.

References BIT_FILL_1, BIT_SET, ctx, DBGC, linda_recv_work_queue::eager_cons, linda_recv_work_queue::eager_prod, ENOMEM, free_dma(), linda_recv_work_queue::header, linda_recv_work_queue::header_cons, linda_recv_work_queue::header_prod, ib_wq_get_drvdata(), linda_qpn_to_ctx(), linda_readq, LINDA_RECV_HEADERS_ALIGN, LINDA_RECV_HEADERS_SIZE, linda_writeq, linda_writeq_array64k, linda_writeq_array8b, malloc_dma(), memset(), QIB_7220_RcvCtrl_offset, QIB_7220_RcvEgrIndexHead0_offset, QIB_7220_RcvHdrAddr0_offset, QIB_7220_RcvHdrHead0_offset, QIB_7220_RcvHdrTailAddr0_offset, ib_queue_pair::qpn, rc, ib_queue_pair::recv, and virt_to_bus().

Referenced by linda_create_qp().

                                                             {
        struct ib_work_queue *wq = &qp->recv;
        struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct QIB_7220_RcvHdrAddr0 rcvhdraddr;
        struct QIB_7220_RcvHdrTailAddr0 rcvhdrtailaddr;
        struct QIB_7220_RcvHdrHead0 rcvhdrhead;
        struct QIB_7220_scalar rcvegrindexhead;
        struct QIB_7220_RcvCtrl rcvctrl;
        unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
        int rc;

        /* Reset context information */
        memset ( &linda_wq->header_prod, 0,
                 sizeof ( linda_wq->header_prod ) );
        linda_wq->header_cons = 0;
        linda_wq->eager_prod = 0;
        linda_wq->eager_cons = 0;

        /* Allocate receive header buffer */
        linda_wq->header = malloc_dma ( LINDA_RECV_HEADERS_SIZE,
                                        LINDA_RECV_HEADERS_ALIGN );
        if ( ! linda_wq->header ) {
                rc = -ENOMEM;
                goto err_alloc_header;
        }

        /* Enable context in hardware */
        memset ( &rcvhdraddr, 0, sizeof ( rcvhdraddr ) );
        BIT_FILL_1 ( &rcvhdraddr, RcvHdrAddr0,
                     ( virt_to_bus ( linda_wq->header ) >> 2 ) );
        linda_writeq_array8b ( linda, &rcvhdraddr,
                               QIB_7220_RcvHdrAddr0_offset, ctx );
        memset ( &rcvhdrtailaddr, 0, sizeof ( rcvhdrtailaddr ) );
        BIT_FILL_1 ( &rcvhdrtailaddr, RcvHdrTailAddr0,
                     ( virt_to_bus ( &linda_wq->header_prod ) >> 2 ) );
        linda_writeq_array8b ( linda, &rcvhdrtailaddr,
                               QIB_7220_RcvHdrTailAddr0_offset, ctx );
        memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) );
        BIT_FILL_1 ( &rcvhdrhead, counter, 1 );
        linda_writeq_array64k ( linda, &rcvhdrhead,
                                QIB_7220_RcvHdrHead0_offset, ctx );
        memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) );
        BIT_FILL_1 ( &rcvegrindexhead, Value, 1 );
        linda_writeq_array64k ( linda, &rcvegrindexhead,
                                QIB_7220_RcvEgrIndexHead0_offset, ctx );
        linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
        BIT_SET ( &rcvctrl, PortEnable[ctx], 1 );
        BIT_SET ( &rcvctrl, IntrAvail[ctx], 1 );
        linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );

        DBGC ( linda, "Linda %p QPN %ld CTX %d hdrs [%lx,%lx) prod %lx\n",
               linda, qp->qpn, ctx, virt_to_bus ( linda_wq->header ),
               ( virt_to_bus ( linda_wq->header ) + LINDA_RECV_HEADERS_SIZE ),
               virt_to_bus ( &linda_wq->header_prod ) );
        return 0;

        free_dma ( linda_wq->header, LINDA_RECV_HEADERS_SIZE );
 err_alloc_header:
        return rc;
}
static void linda_destroy_recv_wq ( struct linda linda,
struct ib_queue_pair qp 
) [static]

Destroy receive work queue.

Parameters:
lindaLinda device
qpQueue pair

Definition at line 664 of file linda.c.

References BIT_SET, ctx, free_dma(), linda_recv_work_queue::header, ib_wq_get_drvdata(), linda_free_ctx(), linda_qpn_to_ctx(), linda_readq, LINDA_RECV_HEADERS_SIZE, linda_writeq, mb(), QIB_7220_RcvCtrl_offset, ib_queue_pair::qpn, and ib_queue_pair::recv.

Referenced by linda_create_qp(), and linda_destroy_qp().

                                                               {
        struct ib_work_queue *wq = &qp->recv;
        struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct QIB_7220_RcvCtrl rcvctrl;
        unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );

        /* Disable context in hardware */
        linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
        BIT_SET ( &rcvctrl, PortEnable[ctx], 0 );
        BIT_SET ( &rcvctrl, IntrAvail[ctx], 0 );
        linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );

        /* Make sure the hardware has seen that the context is disabled */
        linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
        mb();

        /* Free headers ring */
        free_dma ( linda_wq->header, LINDA_RECV_HEADERS_SIZE );

        /* Free context */
        linda_free_ctx ( linda, ctx );
}
static int linda_init_recv ( struct linda linda) [static]

Initialise receive datapath.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 694 of file linda.c.

References BIT_FILL_1, BIT_FILL_3, BIT_GET, ctx, DBGC, linda_recv_work_queue::eager_array, linda_recv_work_queue::eager_entries, EINVAL, LINDA_EAGER_ARRAY_SIZE_17CTX_0, LINDA_EAGER_ARRAY_SIZE_17CTX_OTHER, LINDA_EAGER_ARRAY_SIZE_5CTX_0, LINDA_EAGER_ARRAY_SIZE_5CTX_OTHER, LINDA_EAGER_ARRAY_SIZE_9CTX_0, LINDA_EAGER_ARRAY_SIZE_9CTX_OTHER, LINDA_NUM_CONTEXTS, LINDA_PORTCFG_17CTX, LINDA_PORTCFG_5CTX, LINDA_PORTCFG_9CTX, LINDA_QP_IDETH, linda_readq, LINDA_RECV_HEADER_COUNT, LINDA_RECV_HEADER_SIZE, linda_writeq, linker_assert, memset(), QIB_7220_RcvBTHQP_offset, QIB_7220_RcvCtrl_offset, QIB_7220_RcvEgrBase_offset, QIB_7220_RcvHdrCnt_offset, QIB_7220_RcvHdrEntSize_offset, and linda::recv_wq.

Referenced by linda_probe().

                                                   {
        struct QIB_7220_RcvCtrl rcvctrl;
        struct QIB_7220_scalar rcvegrbase;
        struct QIB_7220_scalar rcvhdrentsize;
        struct QIB_7220_scalar rcvhdrcnt;
        struct QIB_7220_RcvBTHQP rcvbthqp;
        unsigned int portcfg;
        unsigned long egrbase;
        unsigned int eager_array_size_0;
        unsigned int eager_array_size_other;
        unsigned int ctx;

        /* Select configuration based on number of contexts */
        switch ( LINDA_NUM_CONTEXTS ) {
        case 5:
                portcfg = LINDA_PORTCFG_5CTX;
                eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_5CTX_0;
                eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_5CTX_OTHER;
                break;
        case 9:
                portcfg = LINDA_PORTCFG_9CTX;
                eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_9CTX_0;
                eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_9CTX_OTHER;
                break;
        case 17:
                portcfg = LINDA_PORTCFG_17CTX;
                eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_17CTX_0;
                eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_17CTX_OTHER;
                break;
        default:
                linker_assert ( 0, invalid_LINDA_NUM_CONTEXTS );
                return -EINVAL;
        }

        /* Configure number of contexts */
        memset ( &rcvctrl, 0, sizeof ( rcvctrl ) );
        BIT_FILL_3 ( &rcvctrl,
                     TailUpd, 1,
                     PortCfg, portcfg,
                     RcvQPMapEnable, 1 );
        linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );

        /* Configure receive header buffer sizes */
        memset ( &rcvhdrcnt, 0, sizeof ( rcvhdrcnt ) );
        BIT_FILL_1 ( &rcvhdrcnt, Value, LINDA_RECV_HEADER_COUNT );
        linda_writeq ( linda, &rcvhdrcnt, QIB_7220_RcvHdrCnt_offset );
        memset ( &rcvhdrentsize, 0, sizeof ( rcvhdrentsize ) );
        BIT_FILL_1 ( &rcvhdrentsize, Value, ( LINDA_RECV_HEADER_SIZE >> 2 ) );
        linda_writeq ( linda, &rcvhdrentsize, QIB_7220_RcvHdrEntSize_offset );

        /* Calculate eager array start addresses for each context */
        linda_readq ( linda, &rcvegrbase, QIB_7220_RcvEgrBase_offset );
        egrbase = BIT_GET ( &rcvegrbase, Value );
        linda->recv_wq[0].eager_array = egrbase;
        linda->recv_wq[0].eager_entries = eager_array_size_0;
        egrbase += ( eager_array_size_0 * sizeof ( struct QIB_7220_RcvEgr ) );
        for ( ctx = 1 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) {
                linda->recv_wq[ctx].eager_array = egrbase;
                linda->recv_wq[ctx].eager_entries = eager_array_size_other;
                egrbase += ( eager_array_size_other *
                             sizeof ( struct QIB_7220_RcvEgr ) );
        }
        for ( ctx = 0 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) {
                DBGC ( linda, "Linda %p CTX %d eager array at %lx (%d "
                       "entries)\n", linda, ctx,
                       linda->recv_wq[ctx].eager_array,
                       linda->recv_wq[ctx].eager_entries );
        }

        /* Set the BTH QP for Infinipath packets to an unused value */
        memset ( &rcvbthqp, 0, sizeof ( rcvbthqp ) );
        BIT_FILL_1 ( &rcvbthqp, RcvBTHQP, LINDA_QP_IDETH );
        linda_writeq ( linda, &rcvbthqp, QIB_7220_RcvBTHQP_offset );

        return 0;
}
static void linda_fini_recv ( struct linda *linda  __unused) [static]

Shut down receive datapath.

Parameters:
lindaLinda device

Definition at line 776 of file linda.c.

Referenced by linda_probe(), and linda_remove().

                                                             {
        /* Nothing to do; all contexts were already disabled when the
         * queue pairs were destroyed
         */
}
static int linda_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 796 of file linda.c.

References ib_completion_queue::cqn, cqn, DBGC, and ib_get_drvdata().

                                                              {
        struct linda *linda = ib_get_drvdata ( ibdev );
        static int cqn;

        /* The hardware has no concept of completion queues.  We
         * simply use the association between CQs and WQs (already
         * handled by the IB core) to decide which WQs to poll.
         *
         * We do set a CQN, just to avoid confusing debug messages
         * from the IB core.
         */
        cq->cqn = ++cqn;
        DBGC ( linda, "Linda %p CQN %ld created\n", linda, cq->cqn );

        return 0;
}
static void linda_destroy_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
) [static]

Destroy completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 820 of file linda.c.

References ib_completion_queue::cqn, DBGC, and ib_get_drvdata().

                                                                {
        struct linda *linda = ib_get_drvdata ( ibdev );

        /* Nothing to do */
        DBGC ( linda, "Linda %p CQN %ld destroyed\n", linda, cq->cqn );
}
static int linda_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 842 of file linda.c.

References ctx, ib_get_drvdata(), ib_wq_set_drvdata(), linda_alloc_ctx(), linda_create_recv_wq(), linda_create_send_wq(), linda_ctx_to_qpn(), linda_destroy_recv_wq(), linda_destroy_send_wq(), linda_free_ctx(), ib_queue_pair::qpn, rc, ib_queue_pair::recv, linda::recv_wq, ib_queue_pair::send, and linda::send_wq.

                                                        {
        struct linda *linda = ib_get_drvdata ( ibdev );
        int ctx;
        int rc;

        /* Locate an available context */
        ctx = linda_alloc_ctx ( linda );
        if ( ctx < 0 ) {
                rc = ctx;
                goto err_alloc_ctx;
        }

        /* Set queue pair number based on context index */
        qp->qpn = linda_ctx_to_qpn ( ctx );

        /* Set work-queue private data pointers */
        ib_wq_set_drvdata ( &qp->send, &linda->send_wq[ctx] );
        ib_wq_set_drvdata ( &qp->recv, &linda->recv_wq[ctx] );

        /* Create receive work queue */
        if ( ( rc = linda_create_recv_wq ( linda, qp ) ) != 0 )
                goto err_create_recv_wq;

        /* Create send work queue */
        if ( ( rc = linda_create_send_wq ( linda, qp ) ) != 0 )
                goto err_create_send_wq;

        return 0;

        linda_destroy_send_wq ( linda, qp );
 err_create_send_wq:
        linda_destroy_recv_wq ( linda, qp );
 err_create_recv_wq:
        linda_free_ctx ( linda, ctx );
 err_alloc_ctx:
        return rc;
}
static int linda_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 888 of file linda.c.

References DBGC, ib_get_drvdata(), and ib_queue_pair::qpn.

                                                        {
        struct linda *linda = ib_get_drvdata ( ibdev );

        /* Nothing to do; the hardware doesn't have a notion of queue
         * keys
         */
        DBGC ( linda, "Linda %p QPN %ld modified\n", linda, qp->qpn );
        return 0;
}
static void linda_destroy_qp ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Destroy queue pair.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 905 of file linda.c.

References ib_get_drvdata(), linda_destroy_recv_wq(), and linda_destroy_send_wq().

                                                          {
        struct linda *linda = ib_get_drvdata ( ibdev );

        linda_destroy_send_wq ( linda, qp );
        linda_destroy_recv_wq ( linda, qp );
}
static int linda_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 929 of file linda.c.

References assert, BIT_FILL_2, io_buffer::data, data, DBG_DISABLE, DBG_ENABLE, DBGC2, DBGLVL_IO, ib_get_drvdata(), IB_MAX_HEADER_SIZE, ib_push(), ib_wq_get_drvdata(), iob_len(), iob_populate(), iob_reserve, ib_work_queue::iobufs, len, linda_alloc_send_buf(), linda_send_buffer_offset(), linda_writel(), linda_writeq, memset(), NULL, ib_work_queue::num_wqes, offset, linda_send_work_queue::prod, ib_queue_pair::qpn, ib_queue_pair::send, and linda_send_work_queue::send_buf.

                                                       {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq = &qp->send;
        struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct QIB_7220_SendPbc sendpbc;
        uint8_t header_buf[IB_MAX_HEADER_SIZE];
        struct io_buffer headers;
        unsigned int send_buf;
        unsigned long start_offset;
        unsigned long offset;
        size_t len;
        ssize_t frag_len;
        uint32_t *data;

        /* Allocate send buffer and calculate offset */
        send_buf = linda_alloc_send_buf ( linda );
        start_offset = offset = linda_send_buffer_offset ( linda, send_buf );

        /* Store I/O buffer and send buffer index */
        assert ( wq->iobufs[linda_wq->prod] == NULL );
        wq->iobufs[linda_wq->prod] = iobuf;
        linda_wq->send_buf[linda_wq->prod] = send_buf;

        /* Construct headers */
        iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) );
        iob_reserve ( &headers, sizeof ( header_buf ) );
        ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest );

        /* Calculate packet length */
        len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) +
                  iob_len ( iobuf ) + 3 ) & ~3 );

        /* Construct send per-buffer control word */
        memset ( &sendpbc, 0, sizeof ( sendpbc ) );
        BIT_FILL_2 ( &sendpbc,
                     LengthP1_toibc, ( ( len >> 2 ) - 1 ),
                     VL15, 1 );

        /* Write SendPbc */
        DBG_DISABLE ( DBGLVL_IO );
        linda_writeq ( linda, &sendpbc, offset );
        offset += sizeof ( sendpbc );

        /* Write headers */
        for ( data = headers.data, frag_len = iob_len ( &headers ) ;
              frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) {
                linda_writel ( linda, *data, offset );
        }

        /* Write data */
        for ( data = iobuf->data, frag_len = iob_len ( iobuf ) ;
              frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) {
                linda_writel ( linda, *data, offset );
        }
        DBG_ENABLE ( DBGLVL_IO );

        assert ( ( start_offset + len ) == offset );
        DBGC2 ( linda, "Linda %p QPN %ld TX %d(%d) posted [%lx,%lx)\n",
                linda, qp->qpn, send_buf, linda_wq->prod,
                start_offset, offset );

        /* Increment producer counter */
        linda_wq->prod = ( ( linda_wq->prod + 1 ) & ( wq->num_wqes - 1 ) );

        return 0;
}
static void linda_complete_send ( struct ib_device ibdev,
struct ib_queue_pair qp,
unsigned int  wqe_idx 
) [static]

Complete send work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
wqe_idxWork queue entry index

Definition at line 1006 of file linda.c.

References assert, DBGC2, ib_complete_send(), ib_get_drvdata(), ib_wq_get_drvdata(), ib_work_queue::iobufs, linda_free_send_buf(), NULL, ib_queue_pair::qpn, ib_queue_pair::send, and linda_send_work_queue::send_buf.

Referenced by linda_poll_send_wq().

                                                         {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq = &qp->send;
        struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct io_buffer *iobuf;
        unsigned int send_buf;

        /* Parse completion */
        send_buf = linda_wq->send_buf[wqe_idx];
        DBGC2 ( linda, "Linda %p QPN %ld TX %d(%d) complete\n",
                linda, qp->qpn, send_buf, wqe_idx );

        /* Complete work queue entry */
        iobuf = wq->iobufs[wqe_idx];
        assert ( iobuf != NULL );
        ib_complete_send ( ibdev, qp, iobuf, 0 );
        wq->iobufs[wqe_idx] = NULL;

        /* Free send buffer */
        linda_free_send_buf ( linda, send_buf );
}
static void linda_poll_send_wq ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Poll send work queue.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 1036 of file linda.c.

References linda_send_work_queue::cons, ib_work_queue::fill, ib_get_drvdata(), ib_wq_get_drvdata(), linda_complete_send(), linda_send_buf_in_use(), ib_work_queue::num_wqes, ib_queue_pair::send, and linda_send_work_queue::send_buf.

Referenced by linda_poll_cq().

                                                            {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq = &qp->send;
        struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        unsigned int send_buf;

        /* Look for completions */
        while ( wq->fill ) {

                /* Check to see if send buffer has completed */
                send_buf = linda_wq->send_buf[linda_wq->cons];
                if ( linda_send_buf_in_use ( linda, send_buf ) )
                        break;

                /* Complete this buffer */
                linda_complete_send ( ibdev, qp, linda_wq->cons );

                /* Increment consumer counter */
                linda_wq->cons = ( ( linda_wq->cons + 1 ) &
                                   ( wq->num_wqes - 1 ) );
        }
}
static int linda_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 1068 of file linda.c.

References addr, assert, BIT_FILL_1, BIT_FILL_2, bufsize, ctx, io_buffer::data, DBGC, DBGC2, linda_recv_work_queue::eager_array, linda_recv_work_queue::eager_entries, linda_recv_work_queue::eager_prod, EINVAL, ib_get_drvdata(), ib_wq_get_drvdata(), iob_tailroom(), ib_work_queue::iobufs, len, LINDA_EAGER_BUFFER_16K, LINDA_EAGER_BUFFER_2K, LINDA_EAGER_BUFFER_32K, LINDA_EAGER_BUFFER_4K, LINDA_EAGER_BUFFER_64K, LINDA_EAGER_BUFFER_8K, LINDA_EAGER_BUFFER_ALIGN, LINDA_EAGER_BUFFER_NONE, linda_qpn_to_ctx(), LINDA_RECV_PAYLOAD_SIZE, linda_writeq_array64k, linda_writeq_array8b, linker_assert, memset(), NULL, ib_work_queue::num_wqes, QIB_7220_RcvEgrIndexHead0_offset, ib_queue_pair::qpn, ib_queue_pair::recv, and virt_to_bus().

                                                       {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq = &qp->recv;
        struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct QIB_7220_RcvEgr rcvegr;
        struct QIB_7220_scalar rcvegrindexhead;
        unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
        physaddr_t addr;
        size_t len;
        unsigned int wqe_idx;
        unsigned int bufsize;

        /* Sanity checks */
        addr = virt_to_bus ( iobuf->data );
        len = iob_tailroom ( iobuf );
        if ( addr & ( LINDA_EAGER_BUFFER_ALIGN - 1 ) ) {
                DBGC ( linda, "Linda %p QPN %ld misaligned RX buffer "
                       "(%08lx)\n", linda, qp->qpn, addr );
                return -EINVAL;
        }
        if ( len != LINDA_RECV_PAYLOAD_SIZE ) {
                DBGC ( linda, "Linda %p QPN %ld wrong RX buffer size (%zd)\n",
                       linda, qp->qpn, len );
                return -EINVAL;
        }

        /* Calculate eager producer index and WQE index */
        wqe_idx = ( linda_wq->eager_prod & ( wq->num_wqes - 1 ) );
        assert ( wq->iobufs[wqe_idx] == NULL );

        /* Store I/O buffer */
        wq->iobufs[wqe_idx] = iobuf;

        /* Calculate buffer size */
        switch ( LINDA_RECV_PAYLOAD_SIZE ) {
        case 2048:  bufsize = LINDA_EAGER_BUFFER_2K;  break;
        case 4096:  bufsize = LINDA_EAGER_BUFFER_4K;  break;
        case 8192:  bufsize = LINDA_EAGER_BUFFER_8K;  break;
        case 16384: bufsize = LINDA_EAGER_BUFFER_16K; break;
        case 32768: bufsize = LINDA_EAGER_BUFFER_32K; break;
        case 65536: bufsize = LINDA_EAGER_BUFFER_64K; break;
        default:    linker_assert ( 0, invalid_rx_payload_size );
                    bufsize = LINDA_EAGER_BUFFER_NONE;
        }

        /* Post eager buffer */
        memset ( &rcvegr, 0, sizeof ( rcvegr ) );
        BIT_FILL_2 ( &rcvegr,
                     Addr, ( addr >> 11 ),
                     BufSize, bufsize );
        linda_writeq_array8b ( linda, &rcvegr,
                               linda_wq->eager_array, linda_wq->eager_prod );
        DBGC2 ( linda, "Linda %p QPN %ld RX egr %d(%d) posted [%lx,%lx)\n",
                linda, qp->qpn, linda_wq->eager_prod, wqe_idx,
                addr, ( addr + len ) );

        /* Increment producer index */
        linda_wq->eager_prod = ( ( linda_wq->eager_prod + 1 ) &
                                 ( linda_wq->eager_entries - 1 ) );

        /* Update head index */
        memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) );
        BIT_FILL_1 ( &rcvegrindexhead,
                     Value, ( ( linda_wq->eager_prod + 1 ) &
                              ( linda_wq->eager_entries - 1 ) ) );
        linda_writeq_array64k ( linda, &rcvegrindexhead,
                                QIB_7220_RcvEgrIndexHead0_offset, ctx );

        return 0;
}
static void linda_complete_recv ( struct ib_device ibdev,
struct ib_queue_pair qp,
unsigned int  header_offs 
) [static]

Complete receive work queue entry.

Parameters:
ibdevInfiniband device
qpQueue pair
header_offsHeader offset

Definition at line 1148 of file linda.c.

References assert, BIT_GET, io_buffer::data, DBGC, DBGC2, DBGCP_HDA, linda_recv_work_queue::eager_array, linda_recv_work_queue::eager_cons, linda_recv_work_queue::eager_entries, linda_recv_work_queue::eager_prod, ECANCELED, EIO, EPROTO, ib_work_queue::fill, linda_recv_work_queue::header, ib_complete_recv(), ib_get_drvdata(), ib_pull(), ib_wq_get_drvdata(), iob_populate(), iob_put, iob_tailroom(), ib_work_queue::iobufs, LINDA_RECV_HEADER_SIZE, linda_writeq_array8b, memset(), NULL, ib_work_queue::num_wqes, qp, ib_queue_pair::qpn, rc, ib_queue_pair::recv, and strerror().

Referenced by linda_poll_recv_wq().

                                                             {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq = &qp->recv;
        struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct QIB_7220_RcvHdrFlags *rcvhdrflags;
        struct QIB_7220_RcvEgr rcvegr;
        struct io_buffer headers;
        struct io_buffer *iobuf;
        struct ib_queue_pair *intended_qp;
        struct ib_address_vector dest;
        struct ib_address_vector source;
        unsigned int rcvtype;
        unsigned int pktlen;
        unsigned int egrindex;
        unsigned int useegrbfr;
        unsigned int iberr, mkerr, tiderr, khdrerr, mtuerr;
        unsigned int lenerr, parityerr, vcrcerr, icrcerr;
        unsigned int err;
        unsigned int hdrqoffset;
        unsigned int header_len;
        unsigned int padded_payload_len;
        unsigned int wqe_idx;
        size_t payload_len;
        int qp0;
        int rc;

        /* RcvHdrFlags are at the end of the header entry */
        rcvhdrflags = ( linda_wq->header + header_offs +
                        LINDA_RECV_HEADER_SIZE - sizeof ( *rcvhdrflags ) );
        rcvtype = BIT_GET ( rcvhdrflags, RcvType );
        pktlen = ( BIT_GET ( rcvhdrflags, PktLen ) << 2 );
        egrindex = BIT_GET ( rcvhdrflags, EgrIndex );
        useegrbfr = BIT_GET ( rcvhdrflags, UseEgrBfr );
        hdrqoffset = ( BIT_GET ( rcvhdrflags, HdrqOffset ) << 2 );
        iberr = BIT_GET ( rcvhdrflags, IBErr );
        mkerr = BIT_GET ( rcvhdrflags, MKErr );
        tiderr = BIT_GET ( rcvhdrflags, TIDErr );
        khdrerr = BIT_GET ( rcvhdrflags, KHdrErr );
        mtuerr = BIT_GET ( rcvhdrflags, MTUErr );
        lenerr = BIT_GET ( rcvhdrflags, LenErr );
        parityerr = BIT_GET ( rcvhdrflags, ParityErr );
        vcrcerr = BIT_GET ( rcvhdrflags, VCRCErr );
        icrcerr = BIT_GET ( rcvhdrflags, ICRCErr );
        header_len = ( LINDA_RECV_HEADER_SIZE - hdrqoffset -
                       sizeof ( *rcvhdrflags ) );
        padded_payload_len = ( pktlen - header_len - 4 /* ICRC */ );
        err = ( iberr | mkerr | tiderr | khdrerr | mtuerr |
                lenerr | parityerr | vcrcerr | icrcerr );
        /* IB header is placed immediately before RcvHdrFlags */
        iob_populate ( &headers, ( ( ( void * ) rcvhdrflags ) - header_len ),
                       header_len, header_len );

        /* Dump diagnostic information */
        if ( err || ( ! useegrbfr ) ) {
                DBGC ( linda, "Linda %p QPN %ld RX egr %d%s hdr %d type %d "
                       "len %d(%d+%d+4)%s%s%s%s%s%s%s%s%s%s%s\n", linda,
                       qp->qpn, egrindex, ( useegrbfr ? "" : "(unused)" ),
                       ( header_offs / LINDA_RECV_HEADER_SIZE ), rcvtype,
                       pktlen, header_len, padded_payload_len,
                       ( err ? " [Err" : "" ), ( iberr ? " IB" : "" ),
                       ( mkerr ? " MK" : "" ), ( tiderr ? " TID" : "" ),
                       ( khdrerr ? " KHdr" : "" ), ( mtuerr ? " MTU" : "" ),
                       ( lenerr ? " Len" : "" ), ( parityerr ? " Parity" : ""),
                       ( vcrcerr ? " VCRC" : "" ), ( icrcerr ? " ICRC" : "" ),
                       ( err ? "]" : "" ) );
        } else {
                DBGC2 ( linda, "Linda %p QPN %ld RX egr %d hdr %d type %d "
                        "len %d(%d+%d+4)\n", linda, qp->qpn, egrindex,
                        ( header_offs / LINDA_RECV_HEADER_SIZE ), rcvtype,
                        pktlen, header_len, padded_payload_len );
        }
        DBGCP_HDA ( linda, hdrqoffset, headers.data,
                    ( header_len + sizeof ( *rcvhdrflags ) ) );

        /* Parse header to generate address vector */
        qp0 = ( qp->qpn == 0 );
        intended_qp = NULL;
        if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ),
                              &payload_len, &dest, &source ) ) != 0 ) {
                DBGC ( linda, "Linda %p could not parse headers: %s\n",
                       linda, strerror ( rc ) );
                err = 1;
        }
        if ( ! intended_qp )
                intended_qp = qp;

        /* Complete this buffer and any skipped buffers.  Note that
         * when the hardware runs out of buffers, it will repeatedly
         * report the same buffer (the tail) as a TID error, and that
         * it also has a habit of sometimes skipping over several
         * buffers at once.
         */
        while ( 1 ) {

                /* If we have caught up to the producer counter, stop.
                 * This will happen when the hardware first runs out
                 * of buffers and starts reporting TID errors against
                 * the eager buffer it wants to use next.
                 */
                if ( linda_wq->eager_cons == linda_wq->eager_prod )
                        break;

                /* If we have caught up to where we should be after
                 * completing this egrindex, stop.  We phrase the test
                 * this way to avoid completing the entire ring when
                 * we receive the same egrindex twice in a row.
                 */
                if ( ( linda_wq->eager_cons ==
                       ( ( egrindex + 1 ) & ( linda_wq->eager_entries - 1 ) )))
                        break;

                /* Identify work queue entry and corresponding I/O
                 * buffer.
                 */
                wqe_idx = ( linda_wq->eager_cons & ( wq->num_wqes - 1 ) );
                iobuf = wq->iobufs[wqe_idx];
                assert ( iobuf != NULL );
                wq->iobufs[wqe_idx] = NULL;

                /* Complete the eager buffer */
                if ( linda_wq->eager_cons == egrindex ) {
                        /* Completing the eager buffer described in
                         * this header entry.
                         */
                        if ( payload_len <= iob_tailroom ( iobuf ) ) {
                                iob_put ( iobuf, payload_len );
                                rc = ( err ?
                                       -EIO : ( useegrbfr ? 0 : -ECANCELED ) );
                        } else {
                                DBGC ( linda, "Linda %p bad payload len %zd\n",
                                       linda, payload_len );
                                rc = -EPROTO;
                        }
                        /* Redirect to target QP if necessary */
                        if ( qp != intended_qp ) {
                                DBGC ( linda, "Linda %p redirecting QPN %ld "
                                       "=> %ld\n",
                                       linda, qp->qpn, intended_qp->qpn );
                                /* Compensate for incorrect fill levels */
                                qp->recv.fill--;
                                intended_qp->recv.fill++;
                        }
                        ib_complete_recv ( ibdev, intended_qp, &dest, &source,
                                           iobuf, rc );
                } else {
                        /* Completing on a skipped-over eager buffer */
                        ib_complete_recv ( ibdev, qp, &dest, &source, iobuf,
                                           -ECANCELED );
                }

                /* Clear eager buffer */
                memset ( &rcvegr, 0, sizeof ( rcvegr ) );
                linda_writeq_array8b ( linda, &rcvegr, linda_wq->eager_array,
                                       linda_wq->eager_cons );

                /* Increment consumer index */
                linda_wq->eager_cons = ( ( linda_wq->eager_cons + 1 ) &
                                         ( linda_wq->eager_entries - 1 ) );
        }
}
static void linda_poll_recv_wq ( struct ib_device ibdev,
struct ib_queue_pair qp 
) [static]

Poll receive work queue.

Parameters:
ibdevInfiniband device
qpQueue pair

Definition at line 1317 of file linda.c.

References BIT_FILL_2, BIT_GET, ctx, linda_recv_work_queue::header_cons, linda_recv_work_queue::header_prod, ib_get_drvdata(), ib_wq_get_drvdata(), linda_complete_recv(), linda_qpn_to_ctx(), LINDA_RECV_HEADER_SIZE, LINDA_RECV_HEADERS_SIZE, linda_writeq_array64k, memset(), QIB_7220_RcvHdrHead0_offset, ib_queue_pair::qpn, and ib_queue_pair::recv.

Referenced by linda_poll_cq().

                                                            {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct ib_work_queue *wq = &qp->recv;
        struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
        struct QIB_7220_RcvHdrHead0 rcvhdrhead;
        unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
        unsigned int header_prod;

        /* Check for received packets */
        header_prod = ( BIT_GET ( &linda_wq->header_prod, Value ) << 2 );
        if ( header_prod == linda_wq->header_cons )
                return;

        /* Process all received packets */
        while ( linda_wq->header_cons != header_prod ) {

                /* Complete the receive */
                linda_complete_recv ( ibdev, qp, linda_wq->header_cons );

                /* Increment the consumer offset */
                linda_wq->header_cons += LINDA_RECV_HEADER_SIZE;
                linda_wq->header_cons %= LINDA_RECV_HEADERS_SIZE;
        }

        /* Update consumer offset */
        memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) );
        BIT_FILL_2 ( &rcvhdrhead,
                     RcvHeadPointer, ( linda_wq->header_cons >> 2 ),
                     counter, 1 );
        linda_writeq_array64k ( linda, &rcvhdrhead,
                                QIB_7220_RcvHdrHead0_offset, ctx );
}
static void linda_poll_cq ( struct ib_device ibdev,
struct ib_completion_queue cq 
) [static]

Poll completion queue.

Parameters:
ibdevInfiniband device
cqCompletion queue

Definition at line 1357 of file linda.c.

References ib_work_queue::is_send, linda_poll_recv_wq(), linda_poll_send_wq(), ib_work_queue::list, list_for_each_entry, ib_work_queue::qp, and ib_completion_queue::work_queues.

                                                             {
        struct ib_work_queue *wq;

        /* Poll associated send and receive queues */
        list_for_each_entry ( wq, &cq->work_queues, list ) {
                if ( wq->is_send ) {
                        linda_poll_send_wq ( ibdev, wq->qp );
                } else {
                        linda_poll_recv_wq ( ibdev, wq->qp );
                }
        }
}
static void linda_poll_eq ( struct ib_device ibdev) [static]

Poll event queue.

Parameters:
ibdevInfiniband device

Definition at line 1383 of file linda.c.

References BIT_FILL_1, BIT_GET, DBG_DISABLE, DBG_ENABLE, DBGLVL_IO, ib_get_drvdata(), linda_link_state_changed(), linda_readq, linda_writeq, memset(), QIB_7220_ErrClear_offset, and QIB_7220_ErrStatus_offset.

                                                      {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct QIB_7220_ErrStatus errstatus;
        struct QIB_7220_ErrClear errclear;

        /* Check for link status changes */
        DBG_DISABLE ( DBGLVL_IO );
        linda_readq ( linda, &errstatus, QIB_7220_ErrStatus_offset );
        DBG_ENABLE ( DBGLVL_IO );
        if ( BIT_GET ( &errstatus, IBStatusChanged ) ) {
                linda_link_state_changed ( ibdev );
                memset ( &errclear, 0, sizeof ( errclear ) );
                BIT_FILL_1 ( &errclear, IBStatusChangedClear, 1 );
                linda_writeq ( linda, &errclear, QIB_7220_ErrClear_offset );
        }
}
static int linda_open ( struct ib_device ibdev) [static]

Initialise Infiniband link.

Parameters:
ibdevInfiniband device
Return values:
rcReturn status code

Definition at line 1413 of file linda.c.

References BIT_SET, ib_get_drvdata(), linda_readq, linda_writeq, and QIB_7220_Control_offset.

                                                  {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct QIB_7220_Control control;

        /* Disable link */
        linda_readq ( linda, &control, QIB_7220_Control_offset );
        BIT_SET ( &control, LinkEn, 1 );
        linda_writeq ( linda, &control, QIB_7220_Control_offset );
        return 0;
}
static void linda_close ( struct ib_device ibdev) [static]

Close Infiniband link.

Parameters:
ibdevInfiniband device

Definition at line 1429 of file linda.c.

References BIT_SET, ib_get_drvdata(), linda_readq, linda_writeq, and QIB_7220_Control_offset.

                                                    {
        struct linda *linda = ib_get_drvdata ( ibdev );
        struct QIB_7220_Control control;

        /* Disable link */
        linda_readq ( linda, &control, QIB_7220_Control_offset );
        BIT_SET ( &control, LinkEn, 0 );
        linda_writeq ( linda, &control, QIB_7220_Control_offset );
}
static int linda_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 1454 of file linda.c.

References ib_get_drvdata().

                                                    {
        struct linda *linda = ib_get_drvdata ( ibdev );

        ( void ) linda;
        ( void ) qp;
        ( void ) gid;
        return 0;
}
static void linda_mcast_detach ( struct ib_device ibdev,
struct ib_queue_pair qp,
union ib_gid gid 
) [static]

Detach from multicast group.

Parameters:
ibdevInfiniband device
qpQueue pair
gidMulticast GID

Definition at line 1472 of file linda.c.

References ib_get_drvdata().

                                                     {
        struct linda *linda = ib_get_drvdata ( ibdev );

        ( void ) linda;
        ( void ) qp;
        ( void ) gid;
}
static int linda_i2c_read_bit ( struct bit_basher basher,
unsigned int  bit_id 
) [static]

Read Linda I2C line status.

Parameters:
basherBit-bashing interface
bit_idBit number
Return values:
zeroInput is a logic 0
non-zeroInput is a logic 1

Definition at line 1522 of file linda.c.

References i2c_bit_basher::basher, BIT_GET, container_of, DBG_DISABLE, DBG_ENABLE, DBGLVL_IO, linda::i2c, linda_i2c_bits, linda_readq, QIB_7220_EXTStatus_offset, and status.

                                                      {
        struct linda *linda =
                container_of ( basher, struct linda, i2c.basher );
        struct QIB_7220_EXTStatus extstatus;
        unsigned int status;

        DBG_DISABLE ( DBGLVL_IO );

        linda_readq ( linda, &extstatus, QIB_7220_EXTStatus_offset );
        status = ( BIT_GET ( &extstatus, GPIOIn ) & linda_i2c_bits[bit_id] );

        DBG_ENABLE ( DBGLVL_IO );

        return status;
}
static void linda_i2c_write_bit ( struct bit_basher basher,
unsigned int  bit_id,
unsigned long  data 
) [static]

Write Linda I2C line status.

Parameters:
basherBit-bashing interface
bit_idBit number
dataValue to write

Definition at line 1546 of file linda.c.

References i2c_bit_basher::basher, BIT_GET, BIT_SET, container_of, DBG_DISABLE, DBG_ENABLE, DBGLVL_IO, linda::i2c, linda_i2c_bits, linda_readq, linda_writeq, mb(), QIB_7220_EXTCtrl_offset, and QIB_7220_GPIOOut_offset.

                                                                            {
        struct linda *linda =
                container_of ( basher, struct linda, i2c.basher );
        struct QIB_7220_EXTCtrl extctrl;
        struct QIB_7220_GPIO gpioout;
        unsigned int bit = linda_i2c_bits[bit_id];
        unsigned int outputs = 0;
        unsigned int output_enables = 0;

        DBG_DISABLE ( DBGLVL_IO );

        /* Read current GPIO mask and outputs */
        linda_readq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
        linda_readq ( linda, &gpioout, QIB_7220_GPIOOut_offset );

        /* Update outputs and output enables.  I2C lines are tied
         * high, so we always set the output to 0 and use the output
         * enable to control the line.
         */
        output_enables = BIT_GET ( &extctrl, GPIOOe );
        output_enables = ( ( output_enables & ~bit ) | ( ~data & bit ) );
        outputs = BIT_GET ( &gpioout, GPIO );
        outputs = ( outputs & ~bit );
        BIT_SET ( &extctrl, GPIOOe, output_enables );
        BIT_SET ( &gpioout, GPIO, outputs );

        /* Write the output enable first; that way we avoid logic
         * hazards.
         */
        linda_writeq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
        linda_writeq ( linda, &gpioout, QIB_7220_GPIOOut_offset );
        mb();

        DBG_ENABLE ( DBGLVL_IO );
}
static int linda_init_i2c ( struct linda linda) [static]

Initialise Linda I2C subsystem.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 1595 of file linda.c.

References DBGC, DBGC2, linda::eeprom, ENODEV, i2c_bit_basher::i2c, linda::i2c, i2c_check_presence(), init_i2c_bit_basher(), init_i2c_eeprom(), rc, and strerror().

Referenced by linda_probe().

                                                  {
        static int try_eeprom_address[] = { 0x51, 0x50 };
        unsigned int i;
        int rc;

        /* Initialise bus */
        if ( ( rc = init_i2c_bit_basher ( &linda->i2c,
                                          &linda_i2c_basher_ops ) ) != 0 ) {
                DBGC ( linda, "Linda %p could not initialise I2C bus: %s\n",
                       linda, strerror ( rc ) );
                return rc;
        }

        /* Probe for devices */
        for ( i = 0 ; i < ( sizeof ( try_eeprom_address ) /
                            sizeof ( try_eeprom_address[0] ) ) ; i++ ) {
                init_i2c_eeprom ( &linda->eeprom, try_eeprom_address[i] );
                if ( ( rc = i2c_check_presence ( &linda->i2c.i2c,
                                                 &linda->eeprom ) ) == 0 ) {
                        DBGC2 ( linda, "Linda %p found EEPROM at %02x\n",
                                linda, try_eeprom_address[i] );
                        return 0;
                }
        }

        DBGC ( linda, "Linda %p could not find EEPROM\n", linda );
        return -ENODEV;
}
static int linda_read_eeprom ( struct linda linda,
union ib_guid guid 
) [static]

Read EEPROM parameters.

Parameters:
lindaLinda device
guidGUID to fill in
Return values:
rcReturn status code

Definition at line 1631 of file linda.c.

References ib_guid::bytes, DBG_LOG, DBGC, DBGC2, linda::eeprom, i2c_bit_basher::i2c, linda::i2c, IB_GUID_ARGS, IB_GUID_FMT, LINDA_EEPROM_GUID_OFFSET, LINDA_EEPROM_SERIAL_OFFSET, LINDA_EEPROM_SERIAL_SIZE, rc, i2c_interface::read, serial, and strerror().

Referenced by linda_probe().

                                                                          {
        struct i2c_interface *i2c = &linda->i2c.i2c;
        int rc;

        /* Read GUID */
        if ( ( rc = i2c->read ( i2c, &linda->eeprom, LINDA_EEPROM_GUID_OFFSET,
                                guid->bytes, sizeof ( *guid ) ) ) != 0 ) {
                DBGC ( linda, "Linda %p could not read GUID: %s\n",
                       linda, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( linda, "Linda %p has GUID " IB_GUID_FMT "\n",
                linda, IB_GUID_ARGS ( guid ) );

        /* Read serial number (debug only) */
        if ( DBG_LOG ) {
                uint8_t serial[LINDA_EEPROM_SERIAL_SIZE + 1];

                serial[ sizeof ( serial ) - 1 ] = '\0';
                if ( ( rc = i2c->read ( i2c, &linda->eeprom,
                                        LINDA_EEPROM_SERIAL_OFFSET, serial,
                                        ( sizeof ( serial ) - 1 ) ) ) != 0 ) {
                        DBGC ( linda, "Linda %p could not read serial: %s\n",
                               linda, strerror ( rc ) );
                        return rc;
                }
                DBGC2 ( linda, "Linda %p has serial number \"%s\"\n",
                        linda, serial );
        }

        return 0;
}
static int linda_ib_epb_request ( struct linda linda) [static]

Request ownership of the IB external parallel bus.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 1677 of file linda.c.

References BIT_FILL_1, BIT_GET, DBGC, ETIMEDOUT, LINDA_EPB_REQUEST_MAX_WAIT_US, linda_readq, linda_writeq, memset(), QIB_7220_ibsd_epb_access_ctrl_offset, and udelay().

Referenced by linda_ib_epb_mod_reg(), and linda_ib_epb_ram_xfer().

                                                        {
        struct QIB_7220_ibsd_epb_access_ctrl access;
        unsigned int i;

        /* Request ownership */
        memset ( &access, 0, sizeof ( access ) );
        BIT_FILL_1 ( &access, sw_ib_epb_req, 1 );
        linda_writeq ( linda, &access, QIB_7220_ibsd_epb_access_ctrl_offset );

        /* Wait for ownership to be granted */
        for ( i = 0 ; i < LINDA_EPB_REQUEST_MAX_WAIT_US ; i++ ) {
                linda_readq ( linda, &access,
                              QIB_7220_ibsd_epb_access_ctrl_offset );
                if ( BIT_GET ( &access, sw_ib_epb_req_granted ) )
                        return 0;
                udelay ( 1 );
        }

        DBGC ( linda, "Linda %p timed out waiting for IB EPB request\n",
               linda );
        return -ETIMEDOUT;
}
static int linda_ib_epb_wait ( struct linda linda,
struct QIB_7220_ibsd_epb_transaction_reg xact 
) [static]

Wait for IB external parallel bus transaction to complete.

Parameters:
lindaLinda device
xactBuffer to hold transaction result
Return values:
rcReturn status code

Definition at line 1707 of file linda.c.

References BIT_GET, DBGC, EIO, ETIMEDOUT, LINDA_EPB_XACT_MAX_WAIT_US, linda_readq, QIB_7220_ibsd_epb_transaction_reg_offset, and udelay().

Referenced by linda_ib_epb_read(), and linda_ib_epb_write().

                                                                             {
        unsigned int i;

        /* Discard first read to allow for signals crossing clock domains */
        linda_readq ( linda, xact, QIB_7220_ibsd_epb_transaction_reg_offset );

        for ( i = 0 ; i < LINDA_EPB_XACT_MAX_WAIT_US ; i++ ) {
                linda_readq ( linda, xact,
                              QIB_7220_ibsd_epb_transaction_reg_offset );
                if ( BIT_GET ( xact, ib_epb_rdy ) ) {
                        if ( BIT_GET ( xact, ib_epb_req_error ) ) {
                                DBGC ( linda, "Linda %p EPB transaction "
                                       "failed\n", linda );
                                return -EIO;
                        } else {
                                return 0;
                        }
                }
                udelay ( 1 );
        }

        DBGC ( linda, "Linda %p timed out waiting for IB EPB transaction\n",
               linda );
        return -ETIMEDOUT;
}
static void linda_ib_epb_release ( struct linda linda) [static]

Release ownership of the IB external parallel bus.

Parameters:
lindaLinda device

Definition at line 1739 of file linda.c.

References BIT_FILL_1, linda_writeq, memset(), and QIB_7220_ibsd_epb_access_ctrl_offset.

Referenced by linda_ib_epb_mod_reg(), and linda_ib_epb_ram_xfer().

                                                         {
        struct QIB_7220_ibsd_epb_access_ctrl access;

        memset ( &access, 0, sizeof ( access ) );
        BIT_FILL_1 ( &access, sw_ib_epb_req, 0 );
        linda_writeq ( linda, &access, QIB_7220_ibsd_epb_access_ctrl_offset );
}
static int linda_ib_epb_read ( struct linda linda,
unsigned int  location 
) [static]

Read data via IB external parallel bus.

Parameters:
lindaLinda device
locationEPB location
Return values:
dataData read, or negative error

You must have already acquired ownership of the IB external parallel bus.

Definition at line 1757 of file linda.c.

References BIT_FILL_3, BIT_GET, data, LINDA_EPB_LOC_ADDRESS, LINDA_EPB_LOC_CS, LINDA_EPB_READ, linda_ib_epb_wait(), linda_writeq, memset(), QIB_7220_ibsd_epb_transaction_reg_offset, and rc.

Referenced by linda_ib_epb_mod_reg(), and linda_ib_epb_ram_xfer().

                                                                            {
        struct QIB_7220_ibsd_epb_transaction_reg xact;
        unsigned int data;
        int rc;

        /* Ensure no transaction is currently in progress */
        if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
                return rc;

        /* Process data */
        memset ( &xact, 0, sizeof ( xact ) );
        BIT_FILL_3 ( &xact,
                     ib_epb_address, LINDA_EPB_LOC_ADDRESS ( location ),
                     ib_epb_read_write, LINDA_EPB_READ,
                     ib_epb_cs, LINDA_EPB_LOC_CS ( location ) );
        linda_writeq ( linda, &xact,
                       QIB_7220_ibsd_epb_transaction_reg_offset );

        /* Wait for transaction to complete */
        if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
                return rc;

        data = BIT_GET ( &xact, ib_epb_data );
        return data;
}
static int linda_ib_epb_write ( struct linda linda,
unsigned int  location,
unsigned int  data 
) [static]

Write data via IB external parallel bus.

Parameters:
lindaLinda device
locationEPB location
dataData to write
Return values:
rcReturn status code

You must have already acquired ownership of the IB external parallel bus.

Definition at line 1794 of file linda.c.

References BIT_FILL_4, LINDA_EPB_LOC_ADDRESS, LINDA_EPB_LOC_CS, LINDA_EPB_WRITE, linda_ib_epb_wait(), linda_writeq, memset(), QIB_7220_ibsd_epb_transaction_reg_offset, and rc.

Referenced by linda_ib_epb_mod_reg(), and linda_ib_epb_ram_xfer().

                                                    {
        struct QIB_7220_ibsd_epb_transaction_reg xact;
        int rc;

        /* Ensure no transaction is currently in progress */
        if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
                return rc;

        /* Process data */
        memset ( &xact, 0, sizeof ( xact ) );
        BIT_FILL_4 ( &xact,
                     ib_epb_data, data,
                     ib_epb_address, LINDA_EPB_LOC_ADDRESS ( location ),
                     ib_epb_read_write, LINDA_EPB_WRITE,
                     ib_epb_cs, LINDA_EPB_LOC_CS ( location ) );
        linda_writeq ( linda, &xact,
                       QIB_7220_ibsd_epb_transaction_reg_offset );

        /* Wait for transaction to complete */
        if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
                return rc;

        return 0;
}
static int linda_ib_epb_mod_reg ( struct linda linda,
unsigned int  cs,
unsigned int  channel,
unsigned int  element,
unsigned int  reg,
unsigned int  value,
unsigned int  mask 
) [static]

Read/modify/write EPB register.

Parameters:
lindaLinda device
csChip select
channelChannel
elementElement
regRegister
valueValue to set
maskMask to apply to old value
Return values:
rcReturn status code

Definition at line 1832 of file linda.c.

References assert, DBG_DISABLE, DBG_ENABLE, DBGCP, DBGLVL_IO, LINDA_EPB_LOC, linda_ib_epb_read(), linda_ib_epb_release(), linda_ib_epb_request(), linda_ib_epb_write(), out, and rc.

Referenced by linda_set_serdes_param().

                                                      {
        unsigned int location;
        int old_value;
        int rc;

        DBG_DISABLE ( DBGLVL_IO );

        /* Sanity check */
        assert ( ( value & mask ) == value );

        /* Acquire bus ownership */
        if ( ( rc = linda_ib_epb_request ( linda ) ) != 0 )
                goto out;

        /* Read existing value, if necessary */
        location = LINDA_EPB_LOC ( cs, channel, element, reg );
        if ( (~mask) & 0xff ) {
                old_value = linda_ib_epb_read ( linda, location );
                if ( old_value < 0 ) {
                        rc = old_value;
                        goto out_release;
                }
        } else {
                old_value = 0;
        }

        /* Update value */
        value = ( ( old_value & ~mask ) | value );
        DBGCP ( linda, "Linda %p CS %d EPB(%d,%d,%#02x) %#02x => %#02x\n",
                linda, cs, channel, element, reg, old_value, value );
        if ( ( rc = linda_ib_epb_write ( linda, location, value ) ) != 0 )
                goto out_release;

 out_release:
        /* Release bus */
        linda_ib_epb_release ( linda );
 out:
        DBG_ENABLE ( DBGLVL_IO );
        return rc;
}
static int linda_ib_epb_ram_xfer ( struct linda linda,
unsigned int  address,
const void *  write,
void *  read,
size_t  len 
) [static]

Transfer data to/from microcontroller RAM.

Parameters:
lindaLinda device
addressStarting address
writeData to write, or NULL
readData to read, or NULL
lenLength of data
Return values:
rcReturn status code

Definition at line 1886 of file linda.c.

References assert, control, data, DBG_DISABLE, DBG_ENABLE, DBGLVL_IO, LINDA_EPB_UC_ADDR_HI, LINDA_EPB_UC_ADDR_LO, LINDA_EPB_UC_CHUNK_SIZE, LINDA_EPB_UC_CTL, LINDA_EPB_UC_CTL_READ, LINDA_EPB_UC_CTL_WRITE, LINDA_EPB_UC_DATA, linda_ib_epb_read(), linda_ib_epb_release(), linda_ib_epb_request(), linda_ib_epb_write(), out, and rc.

Referenced by linda_program_uc_ram(), and linda_verify_uc_ram().

                                                {
        unsigned int control;
        unsigned int address_hi;
        unsigned int address_lo;
        int data;
        int rc;

        DBG_DISABLE ( DBGLVL_IO );

        assert ( ! ( write && read ) );
        assert ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 );
        assert ( ( len % LINDA_EPB_UC_CHUNK_SIZE ) == 0 );

        /* Acquire bus ownership */
        if ( ( rc = linda_ib_epb_request ( linda ) ) != 0 )
                goto out;

        /* Process data */
        while ( len ) {

                /* Reset the address for each new chunk */
                if ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ) {

                        /* Write the control register */
                        control = ( read ? LINDA_EPB_UC_CTL_READ :
                                    LINDA_EPB_UC_CTL_WRITE );
                        if ( ( rc = linda_ib_epb_write ( linda,
                                                         LINDA_EPB_UC_CTL,
                                                         control ) ) != 0 )
                                break;

                        /* Write the address registers */
                        address_hi = ( address >> 8 );
                        if ( ( rc = linda_ib_epb_write ( linda,
                                                         LINDA_EPB_UC_ADDR_HI,
                                                         address_hi ) ) != 0 )
                                break;
                        address_lo = ( address & 0xff );
                        if ( ( rc = linda_ib_epb_write ( linda,
                                                         LINDA_EPB_UC_ADDR_LO,
                                                         address_lo ) ) != 0 )
                                break;
                }

                /* Read or write the data */
                if ( read ) {
                        data = linda_ib_epb_read ( linda, LINDA_EPB_UC_DATA );
                        if ( data < 0 ) {
                                rc = data;
                                break;
                        }
                        *( ( uint8_t * ) read++ ) = data;
                } else {
                        data = *( ( uint8_t * ) write++ );
                        if ( ( rc = linda_ib_epb_write ( linda,
                                                         LINDA_EPB_UC_DATA,
                                                         data ) ) != 0 )
                                break;
                }
                address++;
                len--;

                /* Reset the control byte after each chunk */
                if ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ) {
                        if ( ( rc = linda_ib_epb_write ( linda,
                                                         LINDA_EPB_UC_CTL,
                                                         0 ) ) != 0 )
                                break;
                }
        }

        /* Release bus */
        linda_ib_epb_release ( linda );

 out:
        DBG_ENABLE ( DBGLVL_IO );
        return rc;
}
static int linda_set_serdes_param ( struct linda linda,
struct linda_serdes_param param 
) [static]

Program IB SerDes register(s)

Parameters:
lindaLinda device
paramSerDes parameter
Return values:
rcReturn status code

Definition at line 1997 of file linda.c.

References linda_serdes_param::address, channel, LINDA_EPB_ADDRESS_CHANNEL, LINDA_EPB_ADDRESS_ELEMENT, LINDA_EPB_ADDRESS_REG, LINDA_EPB_ALL_CHANNELS, LINDA_EPB_CS_SERDES, linda_ib_epb_mod_reg(), linda_serdes_param::mask, rc, reg, and linda_serdes_param::value.

Referenced by linda_set_serdes_params().

                                                                       {
        unsigned int channel;
        unsigned int channel_start;
        unsigned int channel_end;
        unsigned int element;
        unsigned int reg;
        int rc;

        /* Break down the EPB address and determine channels */
        channel = LINDA_EPB_ADDRESS_CHANNEL ( param->address );
        element = LINDA_EPB_ADDRESS_ELEMENT ( param->address );
        reg = LINDA_EPB_ADDRESS_REG ( param->address );
        if ( channel == LINDA_EPB_ALL_CHANNELS ) {
                channel_start = 0;
                channel_end = 3;
        } else {
                channel_start = channel_end = channel;
        }

        /* Modify register for each specified channel */
        for ( channel = channel_start ; channel <= channel_end ; channel++ ) {
                if ( ( rc = linda_ib_epb_mod_reg ( linda, LINDA_EPB_CS_SERDES,
                                                   channel, element, reg,
                                                   param->value,
                                                   param->mask ) ) != 0 )
                        return rc;
        }

        return 0;
}
static int linda_set_serdes_params ( struct linda linda,
struct linda_serdes_param params 
) [static]

Program IB SerDes registers.

Parameters:
lindaLinda device
paramSerDes parameters
countNumber of parameters
Return values:
rcReturn status code

Definition at line 2037 of file linda.c.

References linda_set_serdes_param(), linda_serdes_param::mask, and rc.

Referenced by linda_init_ib_serdes().

                                                                         {
        int rc;

        for ( ; params->mask != 0 ; params++ ){
                if ( ( rc = linda_set_serdes_param ( linda,
                                                         params ) ) != 0 )
                        return rc;
        }

        return 0;
}
static int linda_program_uc_ram ( struct linda linda) [static]

Program the microcontroller RAM.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 2136 of file linda.c.

References DBGC, linda_ib_epb_ram_xfer(), linda_ib_fw, NULL, rc, and strerror().

Referenced by linda_init_ib_serdes().

                                                        {
        int rc;

        if ( ( rc = linda_ib_epb_ram_xfer ( linda, 0, linda_ib_fw, NULL,
                                            sizeof ( linda_ib_fw ) ) ) != 0 ){
                DBGC ( linda, "Linda %p could not load IB firmware: %s\n",
                       linda, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int linda_verify_uc_ram ( struct linda linda) [static]

Verify the microcontroller RAM.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 2155 of file linda.c.

References DBGC, DBGC2, DBGC_HDA, EIO, LINDA_EPB_UC_CHUNK_SIZE, linda_ib_epb_ram_xfer(), linda_ib_fw, memcmp(), NULL, offset, rc, and strerror().

Referenced by linda_init_ib_serdes().

                                                       {
        uint8_t verify[LINDA_EPB_UC_CHUNK_SIZE];
        unsigned int offset;
        int rc;

        for ( offset = 0 ; offset < sizeof ( linda_ib_fw );
              offset += sizeof ( verify ) ) {
                if ( ( rc = linda_ib_epb_ram_xfer ( linda, offset,
                                                    NULL, verify,
                                                    sizeof (verify) )) != 0 ){
                        DBGC ( linda, "Linda %p could not read back IB "
                               "firmware: %s\n", linda, strerror ( rc ) );
                        return rc;
                }
                if ( memcmp ( ( linda_ib_fw + offset ), verify,
                              sizeof ( verify ) ) != 0 ) {
                        DBGC ( linda, "Linda %p firmware verification failed "
                               "at offset %#x\n", linda, offset );
                        DBGC_HDA ( linda, offset, ( linda_ib_fw + offset ),
                                   sizeof ( verify ) );
                        DBGC_HDA ( linda, offset, verify, sizeof ( verify ) );
                        return -EIO;
                }
        }

        DBGC2 ( linda, "Linda %p firmware verified ok\n", linda );
        return 0;
}
static int linda_trim_ib ( struct linda linda) [static]

Use the microcontroller to trim the IB link.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 2190 of file linda.c.

References BIT_GET, BIT_SET, DBGC, ETIMEDOUT, linda_readq, LINDA_TRIM_DONE_MAX_WAIT_MS, linda_writeq, mdelay(), QIB_7220_IBSerDesCtrl_offset, QIB_7220_IntStatus_offset, and rc.

Referenced by linda_init_ib_serdes().

                                                 {
        struct QIB_7220_IBSerDesCtrl ctrl;
        struct QIB_7220_IntStatus intstatus;
        unsigned int i;
        int rc;

        /* Bring the microcontroller out of reset */
        linda_readq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset );
        BIT_SET ( &ctrl, ResetIB_uC_Core, 0 );
        linda_writeq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset );

        /* Wait for the "trim done" signal */
        for ( i = 0 ; i < LINDA_TRIM_DONE_MAX_WAIT_MS ; i++ ) {
                linda_readq ( linda, &intstatus, QIB_7220_IntStatus_offset );
                if ( BIT_GET ( &intstatus, IBSerdesTrimDone ) ) {
                        rc = 0;
                        goto out_reset;
                }
                mdelay ( 1 );
        }

        DBGC ( linda, "Linda %p timed out waiting for trim done\n", linda );
        rc = -ETIMEDOUT;
 out_reset:
        /* Put the microcontroller back into reset */
        BIT_SET ( &ctrl, ResetIB_uC_Core, 1 );
        linda_writeq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset );

        return rc;
}
static int linda_init_ib_serdes ( struct linda linda) [static]

Initialise the IB SerDes.

Parameters:
lindaLinda device
Return values:
rcReturn status code

Definition at line 2227 of file linda.c.

References BIT_FILL_6, BIT_SET, DBGLVL_LOG, linda_program_uc_ram(), linda_readq, LINDA_RECV_HEADER_SIZE, LINDA_RECV_PAYLOAD_SIZE, linda_set_serdes_params(), linda_trim_ib(), linda_verify_uc_ram(), linda_writeq, memset(), QIB_7220_Control_offset, QIB_7220_IBCCtrl_offset, QIB_7220_IBCDDRCtrl_offset, QIB_7220_XGXSCfg_offset, rc, and udelay().

Referenced by linda_probe().

                                                        {
        struct QIB_7220_Control control;
        struct QIB_7220_IBCCtrl ibcctrl;
        struct QIB_7220_IBCDDRCtrl ibcddrctrl;
        struct QIB_7220_XGXSCfg xgxscfg;
        int rc;

        /* Disable link */
        linda_readq ( linda, &control, QIB_7220_Control_offset );
        BIT_SET ( &control, LinkEn, 0 );
        linda_writeq ( linda, &control, QIB_7220_Control_offset );

        /* Configure sensible defaults for IBC */
        memset ( &ibcctrl, 0, sizeof ( ibcctrl ) );
        BIT_FILL_6 ( &ibcctrl, /* Tuning values taken from Linux driver */
                     FlowCtrlPeriod, 0x03,
                     FlowCtrlWaterMark, 0x05,
                     MaxPktLen, ( ( LINDA_RECV_HEADER_SIZE +
                                    LINDA_RECV_PAYLOAD_SIZE +
                                    4 /* ICRC */ ) >> 2 ),
                     PhyerrThreshold, 0xf,
                     OverrunThreshold, 0xf,
                     CreditScale, 0x4 );
        linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );

        /* Force SDR only to avoid needing all the DDR tuning,
         * Mellanox compatibility hacks etc.  SDR is plenty for
         * boot-time operation.
         */
        linda_readq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset );
        BIT_SET ( &ibcddrctrl, IB_ENHANCED_MODE, 0 );
        BIT_SET ( &ibcddrctrl, SD_SPEED_SDR, 1 );
        BIT_SET ( &ibcddrctrl, SD_SPEED_DDR, 0 );
        BIT_SET ( &ibcddrctrl, SD_SPEED_QDR, 0 );
        BIT_SET ( &ibcddrctrl, HRTBT_ENB, 0 );
        BIT_SET ( &ibcddrctrl, HRTBT_AUTO, 0 );
        linda_writeq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset );

        /* Set default SerDes parameters */
        if ( ( rc = linda_set_serdes_params ( linda,
                                              linda_serdes_defaults1 ) ) != 0 )
                return rc;
        udelay ( 415 ); /* Magic delay while SerDes sorts itself out */
        if ( ( rc = linda_set_serdes_params ( linda,
                                              linda_serdes_defaults2 ) ) != 0 )
                return rc;

        /* Program the microcontroller RAM */
        if ( ( rc = linda_program_uc_ram ( linda ) ) != 0 )
                return rc;

        /* Verify the microcontroller RAM contents */
        if ( DBGLVL_LOG ) {
                if ( ( rc = linda_verify_uc_ram ( linda ) ) != 0 )
                        return rc;
        }

        /* More SerDes tuning */
        if ( ( rc = linda_set_serdes_params ( linda,
                                              linda_serdes_defaults3 ) ) != 0 )
                return rc;

        /* Use the microcontroller to trim the IB link */
        if ( ( rc = linda_trim_ib ( linda ) ) != 0 )
                return rc;

        /* Bring XGXS out of reset */
        linda_readq ( linda, &xgxscfg, QIB_7220_XGXSCfg_offset );
        BIT_SET ( &xgxscfg, tx_rx_reset, 0 );
        BIT_SET ( &xgxscfg, xcv_reset, 0 );
        linda_writeq ( linda, &xgxscfg, QIB_7220_XGXSCfg_offset );

        return rc;
}
static int linda_probe ( struct pci_device pci) [static]

Probe PCI device.

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

Definition at line 2316 of file linda.c.

References adjust_pci_device(), alloc_ibdev(), BIT_GET, DBGC, DBGC2, pci_device::dev, ib_device::dev, ENOMEM, ib_device::gid, ib_gid::guid, ib_get_drvdata(), IB_LINK_SPEED_SDR, IB_LINK_WIDTH_1X, IB_LINK_WIDTH_4X, ibdev_put(), ioremap(), iounmap(), LINDA_BAR0_SIZE, linda_fini_recv(), linda_fini_send(), linda_ib_operations, linda_init_i2c(), linda_init_ib_serdes(), linda_init_recv(), linda_init_send(), linda_read_eeprom(), linda_readq, ib_device::link_speed_enabled, ib_device::link_speed_supported, ib_device::link_width_enabled, ib_device::link_width_supported, pci_device::membase, memcpy(), ib_device::node_guid, ib_device::op, pci_set_drvdata(), ib_device::port, QIB_7220_Revision_offset, rc, register_ibdev(), linda::regs, ib_gid::s, strerror(), and unregister_ibdev().

                                                  {
        struct ib_device *ibdev;
        struct linda *linda;
        struct QIB_7220_Revision revision;
        int rc;

        /* Allocate Infiniband device */
        ibdev = alloc_ibdev ( sizeof ( *linda ) );
        if ( ! ibdev ) {
                rc = -ENOMEM;
                goto err_alloc_ibdev;
        }
        pci_set_drvdata ( pci, ibdev );
        linda = ib_get_drvdata ( ibdev );
        ibdev->op = &linda_ib_operations;
        ibdev->dev = &pci->dev;
        ibdev->port = 1;

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

        /* Map PCI BARs */
        linda->regs = ioremap ( pci->membase, LINDA_BAR0_SIZE );
        DBGC2 ( linda, "Linda %p has BAR at %08lx\n", linda, pci->membase );

        /* Print some general data */
        linda_readq ( linda, &revision, QIB_7220_Revision_offset );
        DBGC2 ( linda, "Linda %p board %02lx v%ld.%ld.%ld.%ld\n", linda,
                BIT_GET ( &revision, BoardID ),
                BIT_GET ( &revision, R_SW ),
                BIT_GET ( &revision, R_Arch ),
                BIT_GET ( &revision, R_ChipRevMajor ),
                BIT_GET ( &revision, R_ChipRevMinor ) );

        /* Record link capabilities.  Note that we force SDR only to
         * avoid having to carry extra code for DDR tuning etc.
         */
        ibdev->link_width_enabled = ibdev->link_width_supported =
                ( IB_LINK_WIDTH_4X | IB_LINK_WIDTH_1X );
        ibdev->link_speed_enabled = ibdev->link_speed_supported =
                IB_LINK_SPEED_SDR;

        /* Initialise I2C subsystem */
        if ( ( rc = linda_init_i2c ( linda ) ) != 0 )
                goto err_init_i2c;

        /* Read EEPROM parameters */
        if ( ( rc = linda_read_eeprom ( linda, &ibdev->node_guid ) ) != 0 )
                goto err_read_eeprom;
        memcpy ( &ibdev->gid.s.guid, &ibdev->node_guid,
                 sizeof ( ibdev->gid.s.guid ) );

        /* Initialise send datapath */
        if ( ( rc = linda_init_send ( linda ) ) != 0 )
                goto err_init_send;

        /* Initialise receive datapath */
        if ( ( rc = linda_init_recv ( linda ) ) != 0 )
                goto err_init_recv;

        /* Initialise the IB SerDes */
        if ( ( rc = linda_init_ib_serdes ( linda ) ) != 0 )
                goto err_init_ib_serdes;

        /* Register Infiniband device */
        if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
                DBGC ( linda, "Linda %p could not register IB "
                       "device: %s\n", linda, strerror ( rc ) );
                goto err_register_ibdev;
        }

        return 0;

        unregister_ibdev ( ibdev );
 err_register_ibdev:
        linda_fini_recv ( linda );
 err_init_recv:
        linda_fini_send ( linda );
 err_init_send:
 err_init_ib_serdes:
 err_read_eeprom:
 err_init_i2c:
        iounmap ( linda->regs );
        ibdev_put ( ibdev );
 err_alloc_ibdev:
        return rc;
}
static void linda_remove ( struct pci_device pci) [static]

Remove PCI device.

Parameters:
pciPCI device

Definition at line 2409 of file linda.c.

References ib_get_drvdata(), ibdev_put(), iounmap(), linda_fini_recv(), linda_fini_send(), pci_get_drvdata(), linda::regs, and unregister_ibdev().

                                                    {
        struct ib_device *ibdev = pci_get_drvdata ( pci );
        struct linda *linda = ib_get_drvdata ( ibdev );

        unregister_ibdev ( ibdev );
        linda_fini_recv ( linda );
        linda_fini_send ( linda );
        iounmap ( linda->regs );
        ibdev_put ( ibdev );
}

Variable Documentation

Initial value:
 {
        .create_cq      = linda_create_cq,
        .destroy_cq     = linda_destroy_cq,
        .create_qp      = linda_create_qp,
        .modify_qp      = linda_modify_qp,
        .destroy_qp     = linda_destroy_qp,
        .post_send      = linda_post_send,
        .post_recv      = linda_post_recv,
        .poll_cq        = linda_poll_cq,
        .poll_eq        = linda_poll_eq,
        .open           = linda_open,
        .close          = linda_close,
        .mcast_attach   = linda_mcast_attach,
        .mcast_detach   = linda_mcast_detach,
        .set_port_info  = linda_set_port_info,
        .set_pkey_table = linda_set_pkey_table,
}

Linda Infiniband operations.

Definition at line 1483 of file linda.c.

Referenced by linda_probe().

unsigned int linda_i2c_bits[] [static]
Initial value:
 {
        [I2C_BIT_SCL] = ( 1 << LINDA_GPIO_SCL ),
        [I2C_BIT_SDA] = ( 1 << LINDA_GPIO_SDA ),
}

Linda I2C bit to GPIO mappings.

Definition at line 1509 of file linda.c.

Referenced by linda_i2c_read_bit(), and linda_i2c_write_bit().

Initial value:
 {
        .read   = linda_i2c_read_bit,
        .write  = linda_i2c_write_bit,
}

Linda I2C bit-bashing interface operations.

Definition at line 1584 of file linda.c.

Initial value:
 {
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x00 ), 0xd4, 0xff },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x05 ), 0x2d, 0xff },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x08 ), 0x03, 0x0f },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x10, 0xff },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x28 ), 0x30, 0xff },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x0e ), 0x40, 0xff },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x06 ), 0x04, 0xff },
        
        { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x0f ), 0x04, 0xff },
        
        LINDA_SERDES_PARAM_END
}

Linda SerDes default parameters.

These magic start-of-day values are taken from the Linux driver.

Definition at line 2072 of file linda.c.

Definition at line 2092 of file linda.c.

Initial value:

Definition at line 2123 of file linda.c.

struct pci_device_id linda_nics[] [static]
Initial value:
 {
        PCI_ROM ( 0x1077, 0x7220, "iba7220", "QLE7240/7280 HCA driver", 0 ),
}

Definition at line 2420 of file linda.c.

struct pci_driver linda_driver __pci_driver
Initial value:
 {
        .ids = linda_nics,
        .id_count = ( sizeof ( linda_nics ) / sizeof ( linda_nics[0] ) ),
        .probe = linda_probe,
        .remove = linda_remove,
}

Definition at line 2424 of file linda.c.