From 791f992657d662f4e9645fcdcc9a39dc6d2a2359 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Sep 2007 03:13:25 +0100 Subject: [PATCH] Command interface now reasonably friendly. --- src/drivers/net/mlx_ipoib/arbel.h | 61 ++++++++++++++------- src/drivers/net/mlx_ipoib/mt25218.c | 83 ++++++++++++++++++----------- 2 files changed, 94 insertions(+), 50 deletions(-) diff --git a/src/drivers/net/mlx_ipoib/arbel.h b/src/drivers/net/mlx_ipoib/arbel.h index 79d01b2b..1cf92bde 100644 --- a/src/drivers/net/mlx_ipoib/arbel.h +++ b/src/drivers/net/mlx_ipoib/arbel.h @@ -16,24 +16,6 @@ #define ARBEL_OPCODE_RECV_ERROR 0xfe #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 * @@ -45,6 +27,7 @@ struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error ); 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_query_dev_lim ); struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next ); struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell ); struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector ); @@ -165,4 +148,46 @@ struct arbel { }; +/* + * HCA commands + * + */ + +#define ARBEL_HCR_QUERY_DEV_LIM 0x0003 + +#define ARBEL_HCR_BASE 0x80680 +#define ARBEL_HCR_REG(x) ( ARBEL_HCR_BASE + 4 * (x) ) +#define ARBEL_HCR_MAX_WAIT_MS 2000 + +/* HCA command is split into + * + * bits 11:0 Opcode + * bit 12 Input uses mailbox + * bit 13 Output uses mailbox + * bits 22:14 Input parameter length (in dwords) + * bits 31:23 Output parameter length (in dwords) + * + * Encoding the information in this way allows us to cut out several + * parameters to the arbel_command() call. + */ +#define ARBEL_HCR_IN_MBOX 0x00001000UL +#define ARBEL_HCR_OUT_MBOX 0x00002000UL +#define ARBEL_HCR_OPCODE( _command ) ( (_command) & 0xfff ) +#define ARBEL_HCR_IN_LEN( _command ) ( ( (_command) >> 12 ) & 0x7fc ) +#define ARBEL_HCR_OUT_LEN( _command ) ( ( (_command) >> 21 ) & 0x7fc ) + +/** Build HCR command from component parts */ +#define ARBEL_HCR_CMD( _opcode, _in_mbox, _in_len, _out_mbox, _out_len ) \ + ( (_opcode) | \ + ( (_in_mbox) ? ARBEL_HCR_IN_MBOX : 0 ) | \ + ( ( (_in_len) / 4 ) << 14 ) | \ + ( (_out_mbox) ? ARBEL_HCR_OUT_MBOX : 0 ) | \ + ( ( (_out_len) / 4 ) << 23 ) ) + +#define ARBEL_HCR_IN_CMD( _opcode, _in_mbox, _in_len ) \ + ARBEL_HCR_CMD ( _opcode, _in_mbox, _in_len, 0, 0 ) + +#define ARBEL_HCR_OUT_CMD( _opcode, _out_mbox, _out_len ) \ + ARBEL_HCR_CMD ( _opcode, 0, 0, _out_mbox, _out_len ) + #endif /* _ARBEL_H */ diff --git a/src/drivers/net/mlx_ipoib/mt25218.c b/src/drivers/net/mlx_ipoib/mt25218.c index 3625991c..180ec6da 100644 --- a/src/drivers/net/mlx_ipoib/mt25218.c +++ b/src/drivers/net/mlx_ipoib/mt25218.c @@ -268,14 +268,21 @@ static struct net_device_operations mlx_operations = { .irq = mlx_irq, }; +/*************************************************************************** + * + * HCA commands + * + *************************************************************************** + */ + /** * 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 ) { +static int arbel_cmd_wait ( struct arbel *arbel, + struct arbelprm_hca_command_register *hcr ) { unsigned int wait; for ( wait = ARBEL_HCR_MAX_WAIT_MS ; wait ; wait-- ) { @@ -292,45 +299,54 @@ static int arbel_command_wait ( struct arbel *arbel, * Issue HCA command * * @v arbel Arbel device - * @v op_fl Opcode (plus implied flags) + * @v command Command opcode, flags and input/output lengths * @v op_mod Opcode modifier (0 if no modifier applicable) - * @v in_param Input parameter - * @v in_param_len Input parameter length + * @v in Input parameters * @v in_mod Input modifier (0 if no modifier applicable) - * @v out_param Output parameter + * @v out Output parameters * @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 ) { +static int arbel_cmd ( struct arbel *arbel, unsigned long command, + unsigned int op_mod, const void *in, + unsigned int in_mod, void *out ) { struct arbelprm_hca_command_register hcr; + unsigned int opcode = ARBEL_HCR_OPCODE ( command ); + size_t in_len = ARBEL_HCR_IN_LEN ( command ); + size_t out_len = ARBEL_HCR_OUT_LEN ( command ); + void *in_buffer; + void *out_buffer; unsigned int status; unsigned int i; int rc; + DBGC ( arbel, "Arbel %p command %02x in %zx%s out %zx%s\n", + arbel, opcode, in_len, + ( ( command & ARBEL_HCR_IN_MBOX ) ? "(mbox)" : "" ), out_len, + ( ( command & ARBEL_HCR_OUT_MBOX ) ? "(mbox)" : "" ) ); + /* Check that HCR is free */ - if ( ( rc = arbel_command_wait ( arbel, &hcr ) ) != 0 ) { + if ( ( rc = arbel_cmd_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 ) ); + in_buffer = &hcr.u.dwords[0]; + if ( in_len && ( command & ARBEL_HCR_IN_MBOX ) ) { + in_buffer = arbel->mailbox_in; + MLX_FILL_1 ( &hcr, 1, in_param_l, virt_to_bus ( in_buffer ) ); } + memcpy ( in_buffer, in, in_len ); MLX_FILL_1 ( &hcr, 2, input_modifier, in_mod ); - if ( op_fl & ARBEL_HCR_OUT_MAILBOX ) { + out_buffer = &hcr.u.dwords[3]; + if ( out_len && ( command & ARBEL_HCR_OUT_MBOX ) ) { + out_buffer = arbel->mailbox_out; MLX_FILL_1 ( &hcr, 4, out_param_l, - virt_to_bus ( arbel->mailbox_out ) ); + virt_to_bus ( out_buffer ) ); } MLX_FILL_3 ( &hcr, 6, - opcode, ( op_fl & ARBEL_HCR_OPCODE_MASK ), + opcode, opcode, opcode_modifier, op_mod, go, 1 ); @@ -343,7 +359,7 @@ static int arbel_command ( struct arbel *arbel, unsigned int op_fl, } /* Wait for command completion */ - if ( ( rc = arbel_command_wait ( arbel, &hcr ) ) != 0 ) { + if ( ( rc = arbel_cmd_wait ( arbel, &hcr ) ) != 0 ) { DBGC ( arbel, "Arbel %p timed out waiting for command:\n", arbel ); DBGC_HD ( arbel, &hcr, sizeof ( hcr ) ); @@ -362,15 +378,19 @@ static int arbel_command ( struct arbel *arbel, unsigned int op_fl, /* 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 ); - } + memcpy ( out, out_buffer, out_len ); return 0; } +static int arbel_cmd_query_dev_lim ( struct arbel *arbel, + struct arbelprm_query_dev_lim *out ) { + return arbel_cmd ( arbel, + ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_DEV_LIM, + 1, sizeof ( *out ) ), + 0, NULL, 0, out ); +} + /** * Create completion queue * @@ -752,15 +772,14 @@ static int arbel_probe ( struct pci_device *pci, list_add ( &static_ipoib_qp.recv.list, &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 ) { + struct arbelprm_query_dev_lim dev_lim; + memset ( &dev_lim, 0xaa, sizeof ( dev_lim ) ); + if ( ( rc = arbel_cmd_query_dev_lim ( &static_arbel, + &dev_lim ) ) != 0 ) { DBG ( "QUERY_DEV_LIM failed: %s\n", strerror ( rc ) ); } DBG ( "Device limits:\n "); - DBG_HD ( &buf[0], sizeof ( buf ) ); + DBG_HD ( &dev_lim, sizeof ( dev_lim ) ); /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 )