diff --git a/src/drivers/infiniband/linda.c b/src/drivers/infiniband/linda.c index acbbb9e0..c0d69502 100644 --- a/src/drivers/infiniband/linda.c +++ b/src/drivers/infiniband/linda.c @@ -30,7 +30,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include #include "linda.h" /** @@ -97,9 +96,6 @@ struct linda { struct i2c_bit_basher i2c; /** I2C serial EEPROM */ struct i2c_device eeprom; - - /** Subnet management agent */ - struct ib_sma sma; }; /*************************************************************************** @@ -2335,12 +2331,6 @@ static int linda_probe ( struct pci_device *pci, if ( ( rc = linda_init_ib_serdes ( linda ) ) != 0 ) goto err_init_ib_serdes; - /* Create the SMA */ - if ( ( rc = ib_create_sma ( &linda->sma, ibdev ) ) != 0 ) - goto err_create_sma; - /* If the SMA doesn't get context 0, we're screwed */ - assert ( linda_qpn_to_ctx ( linda->sma.gma.qp->qpn ) == 0 ); - /* Register Infiniband device */ if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { DBGC ( linda, "Linda %p could not register IB " @@ -2352,8 +2342,6 @@ static int linda_probe ( struct pci_device *pci, unregister_ibdev ( ibdev ); err_register_ibdev: - ib_destroy_sma ( &linda->sma ); - err_create_sma: linda_fini_recv ( linda ); err_init_recv: linda_fini_send ( linda ); @@ -2376,7 +2364,6 @@ static void linda_remove ( struct pci_device *pci ) { struct linda *linda = ib_get_drvdata ( ibdev ); unregister_ibdev ( ibdev ); - ib_destroy_sma ( &linda->sma ); linda_fini_recv ( linda ); linda_fini_send ( linda ); ibdev_put ( ibdev ); diff --git a/src/include/gpxe/ib_gma.h b/src/include/gpxe/ib_gma.h index 9ba25ddf..4764a6cc 100644 --- a/src/include/gpxe/ib_gma.h +++ b/src/include/gpxe/ib_gma.h @@ -12,13 +12,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include -struct ib_device; -struct ib_completion_queue; -struct ib_queue_pair; -union ib_mad; struct ib_gma; -enum ib_queue_pair_type; /** A GMA attribute handler */ struct ib_gma_handler { @@ -68,8 +64,8 @@ struct ib_gma { extern int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad, struct ib_address_vector *av, int retry ); -extern int ib_create_gma ( struct ib_gma *gma, struct ib_device *ibdev, - enum ib_queue_pair_type type ); +extern struct ib_gma * ib_create_gma ( struct ib_device *ibdev, + enum ib_queue_pair_type type ); extern void ib_destroy_gma ( struct ib_gma *gma ); #endif /* _GPXE_IB_GMA_H */ diff --git a/src/include/gpxe/ib_sma.h b/src/include/gpxe/ib_sma.h deleted file mode 100644 index 38cb6a2d..00000000 --- a/src/include/gpxe/ib_sma.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _GPXE_IB_SMA_H -#define _GPXE_IB_SMA_H - -/** @file - * - * Infiniband Subnet Management Agent - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include - -/** An Infiniband Subnet Management Agent */ -struct ib_sma { - /** General management agent */ - struct ib_gma gma; -}; - -extern int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev ); -extern void ib_destroy_sma ( struct ib_sma *sma ); - -#endif /* _GPXE_IB_SMA_H */ diff --git a/src/include/gpxe/infiniband.h b/src/include/gpxe/infiniband.h index 80e59bf5..9c1f57a0 100644 --- a/src/include/gpxe/infiniband.h +++ b/src/include/gpxe/infiniband.h @@ -14,7 +14,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include /** Subnet management QPN */ #define IB_QPN_SMA 0 @@ -46,6 +45,7 @@ struct ib_device; struct ib_queue_pair; struct ib_address_vector; struct ib_completion_queue; +struct ib_gma; /** An Infiniband Work Queue */ struct ib_work_queue { @@ -387,8 +387,10 @@ struct ib_device { /** Outbound packet sequence number */ uint32_t psn; + /** Subnet management agent */ + struct ib_gma *sma; /** General management agent */ - struct ib_gma gma; + struct ib_gma *gma; /** Driver private data */ void *drv_priv; diff --git a/src/net/infiniband.c b/src/net/infiniband.c index 42ffbcec..1444a12c 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -510,6 +511,22 @@ int ib_open ( struct ib_device *ibdev ) { return 0; } + /* Create subnet management agent */ + ibdev->sma = ib_create_gma ( ibdev, IB_QPT_SMA ); + if ( ! ibdev->sma ) { + DBGC ( ibdev, "IBDEV %p could not create SMA\n", ibdev ); + rc = -ENOMEM; + goto err_create_sma; + } + + /* Create general management agent */ + ibdev->gma = ib_create_gma ( ibdev, IB_QPT_GMA ); + if ( ! ibdev->gma ) { + DBGC ( ibdev, "IBDEV %p could not create GMA\n", ibdev ); + rc = -ENOMEM; + goto err_create_gma; + } + /* Open device */ if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) { DBGC ( ibdev, "IBDEV %p could not open: %s\n", @@ -517,20 +534,15 @@ int ib_open ( struct ib_device *ibdev ) { goto err_open; } - /* Create general management agent */ - if ( ( rc = ib_create_gma ( &ibdev->gma, ibdev, IB_QPT_GMA ) ) != 0 ) { - DBGC ( ibdev, "IBDEV %p could not create GMA: %s\n", - ibdev, strerror ( rc ) ); - goto err_create_gma; - } - assert ( ibdev->open_count == 1 ); return 0; - ib_destroy_gma ( &ibdev->gma ); - err_create_gma: ibdev->op->close ( ibdev ); err_open: + ib_destroy_gma ( ibdev->gma ); + err_create_gma: + ib_destroy_gma ( ibdev->sma ); + err_create_sma: assert ( ibdev->open_count == 1 ); ibdev->open_count = 0; return rc; @@ -548,7 +560,8 @@ void ib_close ( struct ib_device *ibdev ) { /* Close device if this was the last remaining requested opening */ if ( ibdev->open_count == 0 ) { - ib_destroy_gma ( &ibdev->gma ); + ib_destroy_gma ( ibdev->gma ); + ib_destroy_gma ( ibdev->sma ); ibdev->op->close ( ibdev ); } } diff --git a/src/net/infiniband/ib_gma.c b/src/net/infiniband/ib_gma.c index 1968bc27..ef725d32 100644 --- a/src/net/infiniband/ib_gma.c +++ b/src/net/infiniband/ib_gma.c @@ -68,12 +68,264 @@ struct ib_mad_request { */ #define IB_GMA_NUM_CQES 8 -/** GMA TID magic signature */ +/** TID magic signature */ #define IB_GMA_TID_MAGIC ( ( 'g' << 24 ) | ( 'P' << 16 ) | ( 'X' << 8 ) | 'E' ) /** TID to use for next MAD request */ static unsigned int next_request_tid; +/***************************************************************************** + * + * Subnet management MAD handlers + * + ***************************************************************************** + */ + +/** + * Get node information + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_get_node_info ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + struct ib_node_info *node_info = &mad->smp.smp_data.node_info; + + memset ( node_info, 0, sizeof ( *node_info ) ); + node_info->base_version = IB_MGMT_BASE_VERSION; + node_info->class_version = IB_SMP_CLASS_VERSION; + node_info->node_type = IB_NODE_TYPE_HCA; + node_info->num_ports = ib_get_hca_info ( ibdev, &node_info->sys_guid ); + memcpy ( &node_info->node_guid, &node_info->sys_guid, + sizeof ( node_info->node_guid ) ); + memcpy ( &node_info->port_guid, &ibdev->gid.u.half[1], + sizeof ( node_info->port_guid ) ); + node_info->partition_cap = htons ( 1 ); + node_info->local_port_num = ibdev->port; + + return 0; +} + +/** + * Get node description + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_get_node_desc ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc; + struct ib_gid_half *guid = &ibdev->gid.u.half[1]; + + memset ( node_desc, 0, sizeof ( *node_desc ) ); + snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ), + "gPXE %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", + guid->bytes[0], guid->bytes[1], guid->bytes[2], + guid->bytes[3], guid->bytes[4], guid->bytes[5], + guid->bytes[6], guid->bytes[7], ibdev->dev->name ); + + return 0; +} + +/** + * Get GUID information + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_get_guid_info ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info; + + memset ( guid_info, 0, sizeof ( *guid_info ) ); + memcpy ( guid_info->guid[0], &ibdev->gid.u.half[1], + sizeof ( guid_info->guid[0] ) ); + + return 0; +} + +/** + * Get port information + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_get_port_info ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + struct ib_port_info *port_info = &mad->smp.smp_data.port_info; + + memset ( port_info, 0, sizeof ( *port_info ) ); + memcpy ( port_info->gid_prefix, &ibdev->gid.u.half[0], + sizeof ( port_info->gid_prefix ) ); + port_info->lid = ntohs ( ibdev->lid ); + port_info->mastersm_lid = ntohs ( ibdev->sm_lid ); + port_info->local_port_num = ibdev->port; + port_info->link_width_enabled = ibdev->link_width; + port_info->link_width_supported = ibdev->link_width; + port_info->link_width_active = ibdev->link_width; + port_info->link_speed_supported__port_state = + ( ( ibdev->link_speed << 4 ) | ibdev->port_state ); + port_info->port_phys_state__link_down_def_state = + ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) | + IB_PORT_PHYS_STATE_POLLING ); + port_info->link_speed_active__link_speed_enabled = + ( ( ibdev->link_speed << 4 ) | ibdev->link_speed ); + port_info->neighbour_mtu__mastersm_sl = + ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl ); + port_info->vl_cap__init_type = ( IB_VL_0 << 4 ); + port_info->init_type_reply__mtu_cap = IB_MTU_2048; + port_info->operational_vls__enforcement = ( IB_VL_0 << 4 ); + port_info->guid_cap = 1; + + return 0; +} + +/** + * Set port information + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_set_port_info ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + const struct ib_port_info *port_info = &mad->smp.smp_data.port_info; + int rc; + + memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix, + sizeof ( ibdev->gid.u.half[0] ) ); + ibdev->lid = ntohs ( port_info->lid ); + ibdev->sm_lid = ntohs ( port_info->mastersm_lid ); + ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf ); + + if ( ( rc = ib_set_port_info ( ibdev, port_info ) ) != 0 ) { + DBGC ( ibdev, "IBDEV %p could not set port information: %s\n", + ibdev, strerror ( rc ) ); + mad->hdr.status = + htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); + } + + return ib_sma_get_port_info ( gma, mad ); +} + +/** + * Get partition key table + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_get_pkey_table ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table; + + memset ( pkey_table, 0, sizeof ( *pkey_table ) ); + pkey_table->pkey[0] = htons ( ibdev->pkey ); + + return 0; +} + +/** + * Set partition key table + * + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code + */ +static int ib_sma_set_pkey_table ( struct ib_gma *gma, + union ib_mad *mad ) { + struct ib_device *ibdev = gma->ibdev; + struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table; + + ibdev->pkey = ntohs ( pkey_table->pkey[0] ); + + return ib_sma_get_pkey_table ( gma, mad ); +} + +/** List of attribute handlers */ +struct ib_gma_handler ib_sma_handlers[] __ib_gma_handler = { + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_GET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_NODE_INFO ), + .handle = ib_sma_get_node_info, + }, + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_GET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_NODE_DESC ), + .handle = ib_sma_get_node_desc, + }, + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_GET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_GUID_INFO ), + .handle = ib_sma_get_guid_info, + }, + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_GET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ), + .handle = ib_sma_get_port_info, + }, + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_SET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ), + .handle = ib_sma_set_port_info, + }, + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_GET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ), + .handle = ib_sma_get_pkey_table, + }, + { + .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, + .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, + .class_version = IB_SMP_CLASS_VERSION, + .method = IB_MGMT_METHOD_SET, + .resp_method = IB_MGMT_METHOD_GET_RESP, + .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ), + .handle = ib_sma_set_pkey_table, + }, +}; + +/***************************************************************************** + * + * General management agent + * + ***************************************************************************** + */ + /** * Call attribute handler * @@ -341,18 +593,19 @@ int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad, /** * Create GMA * - * @v gma General management agent * @v ibdev Infiniband device * @v type Queue pair type - * @ret rc Return status code + * @ret gma General management agent, or NULL */ -int ib_create_gma ( struct ib_gma *gma, struct ib_device *ibdev, - enum ib_queue_pair_type type ) { +struct ib_gma * ib_create_gma ( struct ib_device *ibdev, + enum ib_queue_pair_type type ) { + struct ib_gma *gma; unsigned long qkey; - int rc; - /* Initialise fields */ - memset ( gma, 0, sizeof ( *gma ) ); + /* Allocate and initialise fields */ + gma = zalloc ( sizeof ( *gma ) ); + if ( ! gma ) + goto err_alloc; gma->ibdev = ibdev; INIT_LIST_HEAD ( &gma->requests ); @@ -362,7 +615,6 @@ int ib_create_gma ( struct ib_gma *gma, struct ib_device *ibdev, if ( ! gma->cq ) { DBGC ( gma, "GMA %p could not allocate completion queue\n", gma ); - rc = -ENOMEM; goto err_create_cq; } @@ -372,7 +624,6 @@ int ib_create_gma ( struct ib_gma *gma, struct ib_device *ibdev, IB_GMA_NUM_RECV_WQES, gma->cq, qkey ); if ( ! gma->qp ) { DBGC ( gma, "GMA %p could not allocate queue pair\n", gma ); - rc = -ENOMEM; goto err_create_qp; } ib_qp_set_ownerdata ( gma->qp, gma ); @@ -381,13 +632,15 @@ int ib_create_gma ( struct ib_gma *gma, struct ib_device *ibdev, /* Fill receive ring */ ib_refill_recv ( ibdev, gma->qp ); - return 0; + return gma; ib_destroy_qp ( ibdev, gma->qp ); err_create_qp: ib_destroy_cq ( ibdev, gma->cq ); err_create_cq: - return rc; + free ( gma ); + err_alloc: + return NULL; } /** @@ -409,4 +662,5 @@ void ib_destroy_gma ( struct ib_gma *gma ) { ib_destroy_qp ( ibdev, gma->qp ); ib_destroy_cq ( ibdev, gma->cq ); + free ( gma ); } diff --git a/src/net/infiniband/ib_mcast.c b/src/net/infiniband/ib_mcast.c index a9546771..755e0e3d 100644 --- a/src/net/infiniband/ib_mcast.c +++ b/src/net/infiniband/ib_mcast.c @@ -84,7 +84,7 @@ static int ib_mc_member_request ( struct ib_gma *gma, struct ib_gid *gid, */ int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ) { - struct ib_gma *gma = &ibdev->gma; + struct ib_gma *gma = ibdev->gma; int rc; DBGC ( gma, "GMA %p QPN %lx joining %08x:%08x:%08x:%08x\n", @@ -120,7 +120,7 @@ int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp, */ void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ) { - struct ib_gma *gma = &ibdev->gma; + struct ib_gma *gma = ibdev->gma; DBGC ( gma, "GMA %p QPN %lx leaving %08x:%08x:%08x:%08x\n", gma, qp->qpn, ntohl ( gid->u.dwords[0] ), diff --git a/src/net/infiniband/ib_pathrec.c b/src/net/infiniband/ib_pathrec.c index 316ccd47..f686b2dd 100644 --- a/src/net/infiniband/ib_pathrec.c +++ b/src/net/infiniband/ib_pathrec.c @@ -98,7 +98,7 @@ ib_find_path_cache_entry ( struct ib_device *ibdev, struct ib_gid *dgid ) { */ int ib_resolve_path ( struct ib_device *ibdev, struct ib_address_vector *av ) { - struct ib_gma *gma = &ibdev->gma; + struct ib_gma *gma = ibdev->gma; struct ib_gid *gid = &av->gid; struct ib_cached_path_record *cached; union ib_mad mad; diff --git a/src/net/infiniband/ib_sma.c b/src/net/infiniband/ib_sma.c deleted file mode 100644 index 8fb33241..00000000 --- a/src/net/infiniband/ib_sma.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * @file - * - * Infiniband Subnet Management Agent - * - */ - -/** - * Get node information - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_get_node_info ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - struct ib_node_info *node_info = &mad->smp.smp_data.node_info; - - memset ( node_info, 0, sizeof ( *node_info ) ); - node_info->base_version = IB_MGMT_BASE_VERSION; - node_info->class_version = IB_SMP_CLASS_VERSION; - node_info->node_type = IB_NODE_TYPE_HCA; - node_info->num_ports = ib_get_hca_info ( ibdev, &node_info->sys_guid ); - memcpy ( &node_info->node_guid, &node_info->sys_guid, - sizeof ( node_info->node_guid ) ); - memcpy ( &node_info->port_guid, &ibdev->gid.u.half[1], - sizeof ( node_info->port_guid ) ); - node_info->partition_cap = htons ( 1 ); - node_info->local_port_num = ibdev->port; - - return 0; -} - -/** - * Get node description - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_get_node_desc ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc; - struct ib_gid_half *guid = &ibdev->gid.u.half[1]; - - memset ( node_desc, 0, sizeof ( *node_desc ) ); - snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ), - "gPXE %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", - guid->bytes[0], guid->bytes[1], guid->bytes[2], - guid->bytes[3], guid->bytes[4], guid->bytes[5], - guid->bytes[6], guid->bytes[7], ibdev->dev->name ); - - return 0; -} - -/** - * Get GUID information - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_get_guid_info ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info; - - memset ( guid_info, 0, sizeof ( *guid_info ) ); - memcpy ( guid_info->guid[0], &ibdev->gid.u.half[1], - sizeof ( guid_info->guid[0] ) ); - - return 0; -} - -/** - * Get port information - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_get_port_info ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - struct ib_port_info *port_info = &mad->smp.smp_data.port_info; - - memset ( port_info, 0, sizeof ( *port_info ) ); - memcpy ( port_info->gid_prefix, &ibdev->gid.u.half[0], - sizeof ( port_info->gid_prefix ) ); - port_info->lid = ntohs ( ibdev->lid ); - port_info->mastersm_lid = ntohs ( ibdev->sm_lid ); - port_info->local_port_num = ibdev->port; - port_info->link_width_enabled = ibdev->link_width; - port_info->link_width_supported = ibdev->link_width; - port_info->link_width_active = ibdev->link_width; - port_info->link_speed_supported__port_state = - ( ( ibdev->link_speed << 4 ) | ibdev->port_state ); - port_info->port_phys_state__link_down_def_state = - ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) | - IB_PORT_PHYS_STATE_POLLING ); - port_info->link_speed_active__link_speed_enabled = - ( ( ibdev->link_speed << 4 ) | ibdev->link_speed ); - port_info->neighbour_mtu__mastersm_sl = - ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl ); - port_info->vl_cap__init_type = ( IB_VL_0 << 4 ); - port_info->init_type_reply__mtu_cap = IB_MTU_2048; - port_info->operational_vls__enforcement = ( IB_VL_0 << 4 ); - port_info->guid_cap = 1; - - return 0; -} - -/** - * Set port information - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_set_port_info ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - const struct ib_port_info *port_info = &mad->smp.smp_data.port_info; - int rc; - - memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix, - sizeof ( ibdev->gid.u.half[0] ) ); - ibdev->lid = ntohs ( port_info->lid ); - ibdev->sm_lid = ntohs ( port_info->mastersm_lid ); - ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf ); - - if ( ( rc = ib_set_port_info ( ibdev, port_info ) ) != 0 ) { - DBGC ( ibdev, "IBDEV %p could not set port information: %s\n", - ibdev, strerror ( rc ) ); - mad->hdr.status = - htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); - } - - return ib_sma_get_port_info ( gma, mad ); -} - -/** - * Get partition key table - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_get_pkey_table ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table; - - memset ( pkey_table, 0, sizeof ( *pkey_table ) ); - pkey_table->pkey[0] = htons ( ibdev->pkey ); - - return 0; -} - -/** - * Set partition key table - * - * @v gma General management agent - * @v mad MAD - * @ret rc Return status code - */ -static int ib_sma_set_pkey_table ( struct ib_gma *gma, - union ib_mad *mad ) { - struct ib_device *ibdev = gma->ibdev; - struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table; - - ibdev->pkey = ntohs ( pkey_table->pkey[0] ); - - return ib_sma_get_pkey_table ( gma, mad ); -} - -/** List of attribute handlers */ -struct ib_gma_handler ib_sma_handlers[] __ib_gma_handler = { - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_GET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_NODE_INFO ), - .handle = ib_sma_get_node_info, - }, - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_GET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_NODE_DESC ), - .handle = ib_sma_get_node_desc, - }, - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_GET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_GUID_INFO ), - .handle = ib_sma_get_guid_info, - }, - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_GET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ), - .handle = ib_sma_get_port_info, - }, - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_SET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ), - .handle = ib_sma_set_port_info, - }, - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_GET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ), - .handle = ib_sma_get_pkey_table, - }, - { - .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED, - .mgmt_class_ignore = IB_SMP_CLASS_IGNORE, - .class_version = IB_SMP_CLASS_VERSION, - .method = IB_MGMT_METHOD_SET, - .resp_method = IB_MGMT_METHOD_GET_RESP, - .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ), - .handle = ib_sma_set_pkey_table, - }, -}; - -/** - * Create SMA - * - * @v sma Subnet management agent - * @v ibdev Infiniband device - * @v op Subnet management operations - * @ret rc Return status code - */ -int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev ) { - int rc; - - /* Initialise GMA */ - if ( ( rc = ib_create_gma ( &sma->gma, ibdev, IB_QPT_SMA ) ) != 0 ) { - DBGC ( sma, "SMA %p could not create GMA: %s\n", - sma, strerror ( rc ) ); - goto err_create_gma; - } - - /* If we don't get QP0, we can't function */ - if ( sma->gma.qp->qpn != IB_QPN_SMA ) { - DBGC ( sma, "SMA %p on QPN %lx, needs to be on QPN 0\n", - sma, sma->gma.qp->qpn ); - rc = -ENOTSUP; - goto err_not_qp0; - } - - return 0; - - err_not_qp0: - ib_destroy_gma ( &sma->gma ); - err_create_gma: - return rc; -} - -/** - * Destroy SMA - * - * @v sma Subnet management agent - */ -void ib_destroy_sma ( struct ib_sma *sma ) { - - ib_destroy_gma ( &sma->gma ); -}