david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[hermon] Add BOFM support

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2011-02-10 16:40:56 +00:00
parent d157e249f3
commit e809985ca9
3 changed files with 415 additions and 58 deletions

View File

@ -1335,7 +1335,11 @@ struct hermonprm_virtual_physical_mapping_st { /* Little Endian */
/* MOD_STAT_CFG #### michal - gdror fix */
struct hermonprm_mod_stat_cfg_st { /* Little Endian */
pseudo_bit_t reserved0[0x00010];
pseudo_bit_t log_pg_sz[0x00008];
pseudo_bit_t log_pg_sz_m[0x00001];
pseudo_bit_t reserved0[0x00005];
pseudo_bit_t dife[0x00001];
pseudo_bit_t dife_m[0x00001];
pseudo_bit_t rx_options[0x00004]; /* number of RX options to sweep when doing SerDes parameters AutoNegotiation. */
pseudo_bit_t reserved1[0x00003];
pseudo_bit_t rx_options_m[0x00001]; /* Modify rx_options */
@ -1343,46 +1347,129 @@ struct hermonprm_mod_stat_cfg_st { /* Little Endian */
pseudo_bit_t reserved2[0x00003];
pseudo_bit_t tx_options_m[0x00001]; /* Modify tx_options */
/* -------------- */
pseudo_bit_t reserved3[0x00020];
pseudo_bit_t reserved3[0x00010];
pseudo_bit_t qdr_rx_options[0x00004];
pseudo_bit_t reserved4[0x00003];
pseudo_bit_t qdr_rx_options_m[0x00001];
pseudo_bit_t qdr_tx_options[0x00004];
pseudo_bit_t reserved5[0x00003];
pseudo_bit_t qdr_tx_options_m[0x00001];
/* -------------- */
pseudo_bit_t pre_amp[0x00004]; /* Pre Amplitude */
pseudo_bit_t pre_emp_pre_amp[0x00004];
pseudo_bit_t pre_emp_out[0x00004]; /* Pre Emphasis Out */
pseudo_bit_t voltage[0x00004];
pseudo_bit_t equ[0x00004]; /* Equalization */
pseudo_bit_t reserved4[0x0000b];
pseudo_bit_t serdes_m[0x00001]; /* Modify serdes parameters */
pseudo_bit_t reserved6[0x00020];
/* -------------- */
pseudo_bit_t lid[0x00010]; /* default LID */
pseudo_bit_t lid_m[0x00001]; /* Modify default LID */
pseudo_bit_t reserved5[0x00003];
pseudo_bit_t reserved7[0x00003];
pseudo_bit_t port_en[0x00001]; /* enable port (E_Key) */
pseudo_bit_t port_en_m[0x00001]; /* Modify port_en */
pseudo_bit_t reserved6[0x0000a];
pseudo_bit_t reserved8[0x00002];
pseudo_bit_t port_pause_mode[0x00002];
pseudo_bit_t reserved9[0x00001];
pseudo_bit_t port_pause_mode_m[0x00001];
pseudo_bit_t reserved10[0x00004];
/* -------------- */
pseudo_bit_t reserved7[0x0001f];
pseudo_bit_t reserved11[0x0001f];
pseudo_bit_t guid_hi_m[0x00001]; /* Modify guid_hi */
/* -------------- */
pseudo_bit_t guid_hi[0x00020];
/* -------------- */
pseudo_bit_t reserved8[0x0001f];
pseudo_bit_t reserved12[0x0001f];
pseudo_bit_t guid_lo_m[0x00001]; /* Modify guid_lo */
/* -------------- */
pseudo_bit_t guid_lo[0x00020];
/* -------------- */
pseudo_bit_t reserved9[0x0001f];
pseudo_bit_t reserved13[0x0001f];
pseudo_bit_t nodeguid_hi_m[0x00001];
/* -------------- */
pseudo_bit_t nodeguid_hi[0x00020];
/* -------------- */
pseudo_bit_t reserved10[0x0001f];
pseudo_bit_t reserved14[0x0001f];
pseudo_bit_t nodeguid_lo_m[0x00001];
/* -------------- */
pseudo_bit_t nodeguid_lo[0x00020];
/* -------------- */
pseudo_bit_t reserved11[0x00680];
pseudo_bit_t ob_preemp_pre[0x00005];
pseudo_bit_t reserved15[0x00003];
pseudo_bit_t ob_preemp_post[0x00005];
pseudo_bit_t reserved16[0x00003];
pseudo_bit_t ob_preemp_main[0x00005];
pseudo_bit_t reserved17[0x00003];
pseudo_bit_t ob_preemp[0x00005];
pseudo_bit_t reserved18[0x00002];
pseudo_bit_t serdes_m[0x00001];
/* -------------- */
};
pseudo_bit_t inbuf_ind_en[0x00003];
pseudo_bit_t reserved19[0x00001];
pseudo_bit_t sd_main[0x00004];
pseudo_bit_t reserved20[0x00004];
pseudo_bit_t sd_equal[0x00004];
pseudo_bit_t reserved21[0x00004];
pseudo_bit_t sd_mux_main[0x00002];
pseudo_bit_t reserved22[0x00002];
pseudo_bit_t mux_eq[0x00002];
pseudo_bit_t reserved23[0x00002];
pseudo_bit_t sigdet_th[0x00003];
pseudo_bit_t reserved24[0x00001];
/* -------------- */
pseudo_bit_t reserved25[0x00040];
/* -------------- */
pseudo_bit_t port_protocol[0x00008];
pseudo_bit_t port_dual[0x00001];
pseudo_bit_t reserved26[0x00006];
pseudo_bit_t port_protocol_m[0x00001];
pseudo_bit_t num_port[0x00008];
pseudo_bit_t reserved27[0x00008];
/* -------------- */
pseudo_bit_t port_protocol_vpi[0x00008];
pseudo_bit_t reserved28[0x00018];
/* -------------- */
pseudo_bit_t reserved29[0x00180];
/* -------------- */
pseudo_bit_t fw_rev_major[0x00010];
pseudo_bit_t reserved30[0x0000f];
pseudo_bit_t fw_rev_support[0x00001];
/* -------------- */
pseudo_bit_t fw_rev_minor[0x00010];
pseudo_bit_t fw_rev_subminor[0x00010];
/* -------------- */
pseudo_bit_t cmd_interface_rev[0x00010];
pseudo_bit_t reserved31[0x00010];
/* -------------- */
pseudo_bit_t reserved32[0x00060];
/* -------------- */
pseudo_bit_t mac_high[0x00010];
pseudo_bit_t reserved33[0x0000f];
pseudo_bit_t mac_m[0x00001];
/* -------------- */
pseudo_bit_t mac_low[0x00020];
/* -------------- */
pseudo_bit_t reserved34[0x00010];
pseudo_bit_t num_veps[0x00008];
pseudo_bit_t num_vep_groups[0x00008];
/* -------------- */
pseudo_bit_t reserved35[0x00020];
/* -------------- */
pseudo_bit_t reserved36[0x00018];
pseudo_bit_t outer_vlan_en[0x00001];
pseudo_bit_t reserved37[0x00002];
pseudo_bit_t outer_vlan_en_m[0x00001];
pseudo_bit_t port_net_boot[0x00001];
pseudo_bit_t reserved38[0x00002];
pseudo_bit_t port_net_boot_m[0x00001];
/* -------------- */
pseudo_bit_t reserved39[0x00060];
/* -------------- */
pseudo_bit_t port_eth_mode_capability[0x0001f];
pseudo_bit_t reserved40[0x00001];
/* -------------- */
pseudo_bit_t port_eth_mode_enabled[0x0001f];
pseudo_bit_t port_eth_mod_m[0x00001];
/* -------------- */
pseudo_bit_t port_eth_mode_current[0x0001f];
pseudo_bit_t reserved41[0x00001];
/* -------------- */
pseudo_bit_t reserved42[0x00220];
};
/* SRQ Context */

View File

@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/ethernet.h>
#include <ipxe/fcoe.h>
#include <ipxe/vlan.h>
#include <ipxe/bofm.h>
#include "hermon.h"
/**
@ -496,6 +497,17 @@ hermon_cmd_mgid_hash ( struct hermon *hermon, const union ib_gid *gid,
0, gid, 0, hash );
}
static inline int
hermon_cmd_mod_stat_cfg ( struct hermon *hermon, unsigned int mode,
unsigned int input_mod,
struct hermonprm_scalar_parameter *portion ) {
return hermon_cmd ( hermon,
HERMON_HCR_INOUT_CMD ( HERMON_HCR_MOD_STAT_CFG,
0, sizeof ( *portion ),
0, sizeof ( *portion ) ),
mode, portion, input_mod, portion );
}
static inline int
hermon_cmd_query_port ( struct hermon *hermon, unsigned int port,
struct hermonprm_query_port_cap *query_port ) {
@ -682,6 +694,59 @@ static void hermon_free_mtt ( struct hermon *hermon,
mtt->num_pages );
}
/***************************************************************************
*
* Static configuration operations
*
***************************************************************************
*/
/**
* Calculate offset within static configuration
*
* @v field Field
* @ret offset Offset
*/
#define HERMON_MOD_STAT_CFG_OFFSET( field ) \
( ( MLX_BIT_OFFSET ( struct hermonprm_mod_stat_cfg_st, field ) / 8 ) \
& ~( sizeof ( struct hermonprm_scalar_parameter ) - 1 ) )
/**
* Query or modify static configuration
*
* @v hermon Hermon device
* @v port Port
* @v mode Command mode
* @v offset Offset within static configuration
* @v stat_cfg Static configuration
* @ret rc Return status code
*/
static int hermon_mod_stat_cfg ( struct hermon *hermon, unsigned int port,
unsigned int mode, unsigned int offset,
struct hermonprm_mod_stat_cfg *stat_cfg ) {
struct hermonprm_scalar_parameter *portion =
( ( void * ) &stat_cfg->u.bytes[offset] );
struct hermonprm_mod_stat_cfg_input_mod mod;
int rc;
/* Sanity check */
assert ( ( offset % sizeof ( *portion ) ) == 0 );
/* Construct input modifier */
memset ( &mod, 0, sizeof ( mod ) );
MLX_FILL_2 ( &mod, 0,
portnum, port,
offset, offset );
/* Issue command */
if ( ( rc = hermon_cmd_mod_stat_cfg ( hermon, mode,
be32_to_cpu ( mod.u.dwords[0] ),
portion ) ) != 0 )
return rc;
return 0;
}
/***************************************************************************
*
* MAD operations
@ -3230,6 +3295,103 @@ static void hermon_free_icm ( struct hermon *hermon ) {
hermon->icm = UNULL;
}
/***************************************************************************
*
* BOFM interface
*
***************************************************************************
*/
/**
* Harvest Ethernet MAC for BOFM
*
* @v bofm BOFM device
* @v mport Multi-port index
* @v mac MAC to fill in
* @ret rc Return status code
*/
static int hermon_bofm_harvest ( struct bofm_device *bofm, unsigned int mport,
uint8_t *mac ) {
struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
struct hermonprm_mod_stat_cfg stat_cfg;
union {
uint8_t bytes[8];
uint32_t dwords[2];
} buf;
int rc;
/* Query static configuration */
if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
HERMON_MOD_STAT_CFG_QUERY,
HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
&stat_cfg ) ) != 0 ) {
DBGC ( hermon, "Hermon %p port %d could not query "
"configuration: %s\n", hermon, mport, strerror ( rc ) );
return rc;
}
/* Retrieve MAC address */
buf.dwords[0] = htonl ( MLX_GET ( &stat_cfg, mac_high ) );
buf.dwords[1] = htonl ( MLX_GET ( &stat_cfg, mac_low ) );
memcpy ( mac, &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ],
ETH_ALEN );
DBGC ( hermon, "Hermon %p port %d harvested MAC address %s\n",
hermon, mport, eth_ntoa ( mac ) );
return 0;
}
/**
* Update Ethernet MAC for BOFM
*
* @v bofm BOFM device
* @v mport Multi-port index
* @v mac MAC to fill in
* @ret rc Return status code
*/
static int hermon_bofm_update ( struct bofm_device *bofm, unsigned int mport,
const uint8_t *mac ) {
struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
struct hermonprm_mod_stat_cfg stat_cfg;
union {
uint8_t bytes[8];
uint32_t dwords[2];
} buf;
int rc;
/* Prepare MAC address */
memset ( &buf, 0, sizeof ( buf ) );
memcpy ( &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ], mac,
ETH_ALEN );
/* Modify static configuration */
memset ( &stat_cfg, 0, sizeof ( stat_cfg ) );
MLX_FILL_2 ( &stat_cfg, 36,
mac_m, 1,
mac_high, ntohl ( buf.dwords[0] ) );
MLX_FILL_1 ( &stat_cfg, 37, mac_low, ntohl ( buf.dwords[1] ) );
if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
HERMON_MOD_STAT_CFG_SET,
HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
&stat_cfg ) ) != 0 ) {
DBGC ( hermon, "Hermon %p port %d could not modify "
"configuration: %s\n", hermon, mport, strerror ( rc ) );
return rc;
}
DBGC ( hermon, "Hermon %p port %d updated MAC address to %s\n",
hermon, mport, eth_ntoa ( mac ) );
return 0;
}
/** Hermon BOFM operations */
static struct bofm_operations hermon_bofm_operations = {
.harvest = hermon_bofm_harvest,
.update = hermon_bofm_update,
};
/***************************************************************************
*
* PCI interface
@ -3325,6 +3487,72 @@ static void hermon_reset ( struct hermon *hermon,
pci_restore ( pci, &backup, backup_exclude );
}
/**
* Allocate Hermon device
*
* @v pci PCI device
* @v id PCI ID
* @ret rc Return status code
*/
static struct hermon * hermon_alloc ( void ) {
struct hermon *hermon;
/* Allocate Hermon device */
hermon = zalloc ( sizeof ( *hermon ) );
if ( ! hermon )
goto err_hermon;
/* Allocate space for mailboxes */
hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE,
HERMON_MBOX_ALIGN );
if ( ! hermon->mailbox_in )
goto err_mailbox_in;
hermon->mailbox_out = malloc_dma ( HERMON_MBOX_SIZE,
HERMON_MBOX_ALIGN );
if ( ! hermon->mailbox_out )
goto err_mailbox_out;
return hermon;
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
err_mailbox_out:
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
err_mailbox_in:
free ( hermon );
err_hermon:
return NULL;
}
/**
* Free Hermon device
*
* @v hermon Hermon device
*/
static void hermon_free ( struct hermon *hermon ) {
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
free ( hermon );
}
/**
* Initialise Hermon PCI parameters
*
* @v hermon Hermon device
* @v pci PCI device
*/
static void hermon_pci_init ( struct hermon *hermon, struct pci_device *pci ) {
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Get PCI BARs */
hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR),
HERMON_PCI_CONFIG_BAR_SIZE );
hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ),
HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );
}
/**
* Probe PCI device
*
@ -3342,39 +3570,19 @@ static int hermon_probe ( struct pci_device *pci ) {
int rc;
/* Allocate Hermon device */
hermon = zalloc ( sizeof ( *hermon ) );
hermon = hermon_alloc();
if ( ! hermon ) {
rc = -ENOMEM;
goto err_alloc_hermon;
goto err_alloc;
}
pci_set_drvdata ( pci, hermon );
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Get PCI BARs */
hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR),
HERMON_PCI_CONFIG_BAR_SIZE );
hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ),
HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );
/* Initialise PCI parameters */
hermon_pci_init ( hermon, pci );
/* Reset device */
hermon_reset ( hermon, pci );
/* Allocate space for mailboxes */
hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE,
HERMON_MBOX_ALIGN );
if ( ! hermon->mailbox_in ) {
rc = -ENOMEM;
goto err_mailbox_in;
}
hermon->mailbox_out = malloc_dma ( HERMON_MBOX_SIZE,
HERMON_MBOX_ALIGN );
if ( ! hermon->mailbox_out ) {
rc = -ENOMEM;
goto err_mailbox_out;
}
/* Start firmware */
if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
goto err_start_firmware;
@ -3483,12 +3691,8 @@ static int hermon_probe ( struct pci_device *pci ) {
err_get_cap:
hermon_stop_firmware ( hermon );
err_start_firmware:
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
err_mailbox_out:
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
err_mailbox_in:
free ( hermon );
err_alloc_hermon:
hermon_free ( hermon );
err_alloc:
return rc;
}
@ -3511,15 +3715,65 @@ static void hermon_remove ( struct pci_device *pci ) {
hermon_free_icm ( hermon );
hermon_stop_firmware ( hermon );
hermon_stop_firmware ( hermon );
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
netdev_nullify ( hermon->port[i].netdev );
netdev_put ( hermon->port[i].netdev );
}
for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- )
ibdev_put ( hermon->port[i].ibdev );
free ( hermon );
hermon_free ( hermon );
}
/**
* Probe PCI device for BOFM
*
* @v pci PCI device
* @v id PCI ID
* @ret rc Return status code
*/
static int hermon_bofm_probe ( struct pci_device *pci ) {
struct hermon *hermon;
int rc;
/* Allocate Hermon device */
hermon = hermon_alloc();
if ( ! hermon ) {
rc = -ENOMEM;
goto err_alloc;
}
pci_set_drvdata ( pci, hermon );
/* Initialise PCI parameters */
hermon_pci_init ( hermon, pci );
/* Initialise BOFM device */
bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );
/* Register BOFM device */
if ( ( rc = bofm_register ( &hermon->bofm ) ) != 0 ) {
DBGC ( hermon, "Hermon %p could not register BOFM device: "
"%s\n", hermon, strerror ( rc ) );
goto err_bofm_register;
}
return 0;
err_bofm_register:
hermon_free ( hermon );
err_alloc:
return rc;
}
/**
* Remove PCI device for BOFM
*
* @v pci PCI device
*/
static void hermon_bofm_remove ( struct pci_device *pci ) {
struct hermon *hermon = pci_get_drvdata ( pci );
bofm_unregister ( &hermon->bofm );
hermon_free ( hermon );
}
static struct pci_device_id hermon_nics[] = {
@ -3543,3 +3797,10 @@ struct pci_driver hermon_driver __pci_driver = {
.probe = hermon_probe,
.remove = hermon_remove,
};
struct pci_driver hermon_bofm_driver __bofm_driver = {
.ids = hermon_nics,
.id_count = ( sizeof ( hermon_nics ) / sizeof ( hermon_nics[0] ) ),
.probe = hermon_bofm_probe,
.remove = hermon_bofm_remove,
};

View File

@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
#include <ipxe/uaccess.h>
#include <ipxe/ib_packet.h>
#include <ipxe/bofm.h>
#include "mlx_bitops.h"
#include "MT25408_PRM.h"
@ -131,6 +132,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define HERMON_RETRY_MAX 0x07
#define HERMON_MOD_STAT_CFG_SET 0x01
#define HERMON_MOD_STAT_CFG_QUERY 0x03
/*
* Datatypes that seem to be missing from the autogenerated documentation
*
@ -417,13 +421,14 @@ struct hermonprm_set_port_vlan_st {
/* -------------- */
} __attribute__ (( packed ));
struct hermonprm_mod_stat_cfg_pf_net_boot_st {
pseudo_bit_t reserved1[0x0001c];
pseudo_bit_t pf_net_boot[0x00001];
pseudo_bit_t reserved2[0x00002];
pseudo_bit_t pf_net_boot_m[0x00001];
/* -------------- */
pseudo_bit_t reserved0[0x00020];
struct hermonprm_mod_stat_cfg_input_mod_st {
pseudo_bit_t offset[0x00008];
pseudo_bit_t portnum[0x00008];
pseudo_bit_t xnum[0x00004];
pseudo_bit_t linkspeed[0x00003];
pseudo_bit_t autoneg[0x00001];
pseudo_bit_t reserved[0x00004];
pseudo_bit_t setup_mode[0x00004];
} __attribute__ (( packed ));
/*
@ -444,7 +449,8 @@ struct MLX_DECLARE_STRUCT ( hermonprm_init_hca );
struct MLX_DECLARE_STRUCT ( hermonprm_mad_ifc );
struct MLX_DECLARE_STRUCT ( hermonprm_mcg_entry );
struct MLX_DECLARE_STRUCT ( hermonprm_mgm_hash );
struct MLX_DECLARE_STRUCT ( hermonprm_mod_stat_cfg_pf_net_boot );
struct MLX_DECLARE_STRUCT ( hermonprm_mod_stat_cfg );
struct MLX_DECLARE_STRUCT ( hermonprm_mod_stat_cfg_input_mod );
struct MLX_DECLARE_STRUCT ( hermonprm_mpt );
struct MLX_DECLARE_STRUCT ( hermonprm_mtt );
struct MLX_DECLARE_STRUCT ( hermonprm_port_state_change_event );
@ -866,6 +872,9 @@ struct hermon {
/** Ports */
struct hermon_port port[HERMON_MAX_PORTS];
/** BOFM device */
struct bofm_device bofm;
};
/** Global protection domain */