First (working) draft of command interface.
This commit is contained in:
parent
baa885ee8e
commit
bf9bd93856
@ -16,14 +16,34 @@
|
|||||||
#define ARBEL_OPCODE_RECV_ERROR 0xfe
|
#define ARBEL_OPCODE_RECV_ERROR 0xfe
|
||||||
#define ARBEL_OPCODE_SEND_ERROR 0xff
|
#define ARBEL_OPCODE_SEND_ERROR 0xff
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HCA commands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ARBEL_HCR_BASE 0x80680
|
||||||
|
#define ARBEL_HCR_REG(x) ( ARBEL_HCR_BASE + 4 * (x) )
|
||||||
|
#define ARBEL_HCR_MAX_WAIT_MS 2000
|
||||||
|
|
||||||
|
#define ARBEL_HCR_OPCODE_MASK 0x0000ffffUL
|
||||||
|
#define ARBEL_HCR_IN_IMMEDIATE 0x00010000UL
|
||||||
|
#define ARBEL_HCR_IN_MAILBOX 0x00020000UL
|
||||||
|
#define ARBEL_HCR_OUT_IMMEDIATE 0x00040000UL
|
||||||
|
#define ARBEL_HCR_OUT_MAILBOX 0x00080000UL
|
||||||
|
|
||||||
|
#define ARBEL_HCR_OP_SW2HW_CQ ( 0x0016 | ARBEL_HCR_IN_MAILBOX )
|
||||||
|
#define ARBEL_HCR_OP_NOP ( 0x0031 )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper structures for hardware datatypes
|
* Wrapper structures for hardware datatypes
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_context );
|
||||||
struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
|
struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
|
||||||
struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
|
struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
|
||||||
struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
|
struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
|
||||||
|
struct MLX_DECLARE_STRUCT ( arbelprm_hca_command_register );
|
||||||
struct MLX_DECLARE_STRUCT ( arbelprm_qp_db_record );
|
struct MLX_DECLARE_STRUCT ( arbelprm_qp_db_record );
|
||||||
struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
|
struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
|
||||||
struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
|
struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
|
||||||
@ -126,6 +146,13 @@ struct arbel_completion_queue {
|
|||||||
|
|
||||||
/** An Arbel device */
|
/** An Arbel device */
|
||||||
struct arbel {
|
struct arbel {
|
||||||
|
/** Configuration registers */
|
||||||
|
void *config;
|
||||||
|
/** Command input mailbox */
|
||||||
|
void *mailbox_in;
|
||||||
|
/** Command output mailbox */
|
||||||
|
void *mailbox_out;
|
||||||
|
|
||||||
/** User Access Region */
|
/** User Access Region */
|
||||||
void *uar;
|
void *uar;
|
||||||
/** Doorbell records */
|
/** Doorbell records */
|
||||||
|
@ -26,6 +26,11 @@ Skeleton NIC driver for Etherboot
|
|||||||
#include "arbel.h"
|
#include "arbel.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const struct ib_gid arbel_no_gid = {
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define MLX_RX_MAX_FILL NUM_IPOIB_RCV_WQES
|
#define MLX_RX_MAX_FILL NUM_IPOIB_RCV_WQES
|
||||||
|
|
||||||
struct mlx_nic {
|
struct mlx_nic {
|
||||||
@ -263,11 +268,121 @@ static struct net_device_operations mlx_operations = {
|
|||||||
.irq = mlx_irq,
|
.irq = mlx_irq,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for Arbel command completion
|
||||||
|
*
|
||||||
|
* @v arbel Arbel device
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int arbel_command_wait ( struct arbel *arbel,
|
||||||
|
struct arbelprm_hca_command_register *hcr ) {
|
||||||
|
unsigned int wait;
|
||||||
|
|
||||||
|
for ( wait = ARBEL_HCR_MAX_WAIT_MS ; wait ; wait-- ) {
|
||||||
|
hcr->u.dwords[6] =
|
||||||
|
readl ( arbel->config + ARBEL_HCR_REG ( 6 ) );
|
||||||
|
if ( MLX_GET ( hcr, go ) == 0 )
|
||||||
|
return 0;
|
||||||
|
mdelay ( 1 );
|
||||||
|
}
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue HCA command
|
||||||
|
*
|
||||||
|
* @v arbel Arbel device
|
||||||
|
* @v op_fl Opcode (plus implied flags)
|
||||||
|
* @v op_mod Opcode modifier (0 if no modifier applicable)
|
||||||
|
* @v in_param Input parameter
|
||||||
|
* @v in_param_len Input parameter length
|
||||||
|
* @v in_mod Input modifier (0 if no modifier applicable)
|
||||||
|
* @v out_param Output parameter
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int arbel_command ( struct arbel *arbel, unsigned int op_fl,
|
||||||
|
unsigned int op_mod, const void *in_param,
|
||||||
|
size_t in_param_len, unsigned int in_mod,
|
||||||
|
void *out_param, size_t out_param_len ) {
|
||||||
|
struct arbelprm_hca_command_register hcr;
|
||||||
|
unsigned int status;
|
||||||
|
unsigned int i;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Check that HCR is free */
|
||||||
|
if ( ( rc = arbel_command_wait ( arbel, &hcr ) ) != 0 ) {
|
||||||
|
DBGC ( arbel, "Arbel %p command interface locked\n", arbel );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare HCR */
|
||||||
|
memset ( &hcr, 0, sizeof ( hcr ) );
|
||||||
|
if ( op_fl & ARBEL_HCR_IN_IMMEDIATE ) {
|
||||||
|
memcpy ( &hcr.u.dwords[0], in_param, 8 );
|
||||||
|
} else if ( op_fl & ARBEL_HCR_IN_MAILBOX ) {
|
||||||
|
memcpy ( arbel->mailbox_in, in_param, in_param_len );
|
||||||
|
MLX_FILL_1 ( &hcr, 1, in_param_l,
|
||||||
|
virt_to_bus ( arbel->mailbox_in ) );
|
||||||
|
}
|
||||||
|
MLX_FILL_1 ( &hcr, 2, input_modifier, in_mod );
|
||||||
|
if ( op_fl & ARBEL_HCR_OUT_MAILBOX ) {
|
||||||
|
MLX_FILL_1 ( &hcr, 4, out_param_l,
|
||||||
|
virt_to_bus ( arbel->mailbox_out ) );
|
||||||
|
}
|
||||||
|
MLX_FILL_3 ( &hcr, 6,
|
||||||
|
opcode, ( op_fl & ARBEL_HCR_OPCODE_MASK ),
|
||||||
|
opcode_modifier, op_mod,
|
||||||
|
go, 1 );
|
||||||
|
|
||||||
|
/* Issue command */
|
||||||
|
for ( i = 0 ; i < ( sizeof ( hcr ) / sizeof ( hcr.u.dwords[0] ) ) ;
|
||||||
|
i++ ) {
|
||||||
|
writel ( hcr.u.dwords[i],
|
||||||
|
arbel->config + ARBEL_HCR_REG ( i ) );
|
||||||
|
barrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for command completion */
|
||||||
|
if ( ( rc = arbel_command_wait ( arbel, &hcr ) ) != 0 ) {
|
||||||
|
DBGC ( arbel, "Arbel %p timed out waiting for command:\n",
|
||||||
|
arbel );
|
||||||
|
DBGC_HD ( arbel, &hcr, sizeof ( hcr ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check command status */
|
||||||
|
status = MLX_GET ( &hcr, status );
|
||||||
|
if ( status != 0 ) {
|
||||||
|
DBGC ( arbel, "Arbel %p command failed with status %02x:\n",
|
||||||
|
arbel, status );
|
||||||
|
DBGC_HD ( arbel, &hcr, sizeof ( hcr ) );
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read output parameters, if any */
|
||||||
|
hcr.u.dwords[3] = readl ( arbel->config + ARBEL_HCR_REG ( 3 ) );
|
||||||
|
hcr.u.dwords[4] = readl ( arbel->config + ARBEL_HCR_REG ( 4 ) );
|
||||||
|
if ( op_fl & ARBEL_HCR_OUT_IMMEDIATE ) {
|
||||||
|
memcpy ( out_param, &hcr.u.dwords[3], 8 );
|
||||||
|
} else if ( op_fl & ARBEL_HCR_OUT_MAILBOX ) {
|
||||||
|
memcpy ( out_param, arbel->mailbox_out, out_param_len );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create completion queue
|
||||||
|
*
|
||||||
|
* @v ibdev Infiniband device
|
||||||
|
* @v
|
||||||
|
*/
|
||||||
|
static int arbel_create_cq ( struct ib_device *ibdev ) {
|
||||||
|
struct arbelprm_completion_queue_context *cqctx;
|
||||||
|
|
||||||
|
|
||||||
static struct ib_gid arbel_no_gid = {
|
}
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ring doorbell register in UAR
|
* Ring doorbell register in UAR
|
||||||
@ -310,7 +425,7 @@ static int arbel_post_send ( struct ib_device *ibdev,
|
|||||||
struct arbelprm_ud_send_wqe *wqe;
|
struct arbelprm_ud_send_wqe *wqe;
|
||||||
union arbelprm_doorbell_record *db_rec;
|
union arbelprm_doorbell_record *db_rec;
|
||||||
union arbelprm_doorbell_register db_reg;
|
union arbelprm_doorbell_register db_reg;
|
||||||
struct ib_gid *gid;
|
const struct ib_gid *gid;
|
||||||
unsigned int wqe_idx_mask;
|
unsigned int wqe_idx_mask;
|
||||||
size_t nds;
|
size_t nds;
|
||||||
|
|
||||||
@ -616,6 +731,9 @@ static int arbel_probe ( struct pci_device *pci,
|
|||||||
memcpy ( &mac->gid, ib_data.port_gid.raw, sizeof ( mac->gid ) );
|
memcpy ( &mac->gid, ib_data.port_gid.raw, sizeof ( mac->gid ) );
|
||||||
|
|
||||||
/* Hack up IB structures */
|
/* Hack up IB structures */
|
||||||
|
static_arbel.config = memfree_pci_dev.cr_space;
|
||||||
|
static_arbel.mailbox_in = dev_buffers_p->inprm_buf;
|
||||||
|
static_arbel.mailbox_out = dev_buffers_p->outprm_buf;
|
||||||
static_arbel.uar = memfree_pci_dev.uar;
|
static_arbel.uar = memfree_pci_dev.uar;
|
||||||
static_arbel.db_rec = dev_ib_data.uar_context_base;
|
static_arbel.db_rec = dev_ib_data.uar_context_base;
|
||||||
static_arbel.reserved_lkey = dev_ib_data.mkey;
|
static_arbel.reserved_lkey = dev_ib_data.mkey;
|
||||||
@ -634,6 +752,16 @@ static int arbel_probe ( struct pci_device *pci,
|
|||||||
list_add ( &static_ipoib_qp.recv.list,
|
list_add ( &static_ipoib_qp.recv.list,
|
||||||
&static_ipoib_recv_cq.work_queues );
|
&static_ipoib_recv_cq.work_queues );
|
||||||
|
|
||||||
|
uint8_t buf[512];
|
||||||
|
memset ( buf, 0xaa, sizeof ( buf ) );
|
||||||
|
if ( ( rc = arbel_command ( &static_arbel,
|
||||||
|
( 0x03 | ARBEL_HCR_OUT_MAILBOX ), 0,
|
||||||
|
NULL, 0, 0, buf, 256 ) ) != 0 ) {
|
||||||
|
DBG ( "QUERY_DEV_LIM failed: %s\n", strerror ( rc ) );
|
||||||
|
}
|
||||||
|
DBG ( "Device limits:\n ");
|
||||||
|
DBG_HD ( &buf[0], sizeof ( buf ) );
|
||||||
|
|
||||||
/* Register network device */
|
/* Register network device */
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
goto err_register_netdev;
|
goto err_register_netdev;
|
||||||
|
Reference in New Issue
Block a user