From 165074c1881e7ce86e4d6d2e3caa20231f42560b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 7 Jul 2009 18:30:15 +0100 Subject: [PATCH] [infiniband] Implement SMA as an instance of a GMA The GMA code was based upon the SMA code. We can save space by making the SMA simply an instance of the GMA. --- src/drivers/infiniband/linda.c | 11 +- src/include/gpxe/ib_gma.h | 2 + src/include/gpxe/ib_mad.h | 3 + src/include/gpxe/ib_sma.h | 43 +-- src/include/gpxe/infiniband.h | 12 + src/net/infiniband.c | 25 ++ src/net/infiniband/ib_gma.c | 3 +- src/net/infiniband/ib_sma.c | 459 ++++++++++----------------------- 8 files changed, 194 insertions(+), 364 deletions(-) diff --git a/src/drivers/infiniband/linda.c b/src/drivers/infiniband/linda.c index e7259014..acbbb9e0 100644 --- a/src/drivers/infiniband/linda.c +++ b/src/drivers/infiniband/linda.c @@ -272,11 +272,6 @@ static int linda_set_port_info ( struct ib_device *ibdev, return 0; } -/** Linda subnet management operations */ -static struct ib_sma_operations linda_sma_operations = { - .set_port_info = linda_set_port_info, -}; - /*************************************************************************** * * Context allocation @@ -1464,6 +1459,7 @@ static struct ib_device_operations linda_ib_operations = { .close = linda_close, .mcast_attach = linda_mcast_attach, .mcast_detach = linda_mcast_detach, + .set_port_info = linda_set_port_info, }; /*************************************************************************** @@ -2340,11 +2336,10 @@ static int linda_probe ( struct pci_device *pci, goto err_init_ib_serdes; /* Create the SMA */ - if ( ( rc = ib_create_sma ( &linda->sma, ibdev, - &linda_sma_operations ) ) != 0 ) + 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.qp->qpn ) == 0 ); + assert ( linda_qpn_to_ctx ( linda->sma.gma.qp->qpn ) == 0 ); /* Register Infiniband device */ if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { diff --git a/src/include/gpxe/ib_gma.h b/src/include/gpxe/ib_gma.h index 04955e5c..d24b32db 100644 --- a/src/include/gpxe/ib_gma.h +++ b/src/include/gpxe/ib_gma.h @@ -23,6 +23,8 @@ struct ib_gma; struct ib_gma_handler { /** Management class */ uint8_t mgmt_class; + /** Management class don't-care bits */ + uint8_t mgmt_class_ignore; /** Class version */ uint8_t class_version; /** Method */ diff --git a/src/include/gpxe/ib_mad.h b/src/include/gpxe/ib_mad.h index d4582c34..75bf271e 100644 --- a/src/include/gpxe/ib_mad.h +++ b/src/include/gpxe/ib_mad.h @@ -30,6 +30,9 @@ struct ib_smp_hdr { uint8_t reserved[28]; } __attribute__ (( packed )); +/** Bits to ignore in the management class for subnet management MADs */ +#define IB_SMP_CLASS_IGNORE 0x80 + /** Subnet management class version */ #define IB_SMP_CLASS_VERSION 1 diff --git a/src/include/gpxe/ib_sma.h b/src/include/gpxe/ib_sma.h index dadcdff2..38cb6a2d 100644 --- a/src/include/gpxe/ib_sma.h +++ b/src/include/gpxe/ib_sma.h @@ -10,50 +10,15 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include - -/** Infiniband Subnet Management Agent operations */ -struct ib_sma_operations { - /** Set port information - * - * @v ibdev Infiniband device - * @v port_info New port information - */ - int ( * set_port_info ) ( struct ib_device *ibdev, - const struct ib_port_info *port_info ); -}; +#include /** An Infiniband Subnet Management Agent */ struct ib_sma { - /** Infiniband device */ - struct ib_device *ibdev; - /** SMA operations */ - struct ib_sma_operations *op; - /** SMA completion queue */ - struct ib_completion_queue *cq; - /** SMA queue pair */ - struct ib_queue_pair *qp; + /** General management agent */ + struct ib_gma gma; }; -/** SMA number of send WQEs - * - * This is a policy decision. - */ -#define IB_SMA_NUM_SEND_WQES 4 - -/** SMA number of receive WQEs - * - * This is a policy decision. - */ -#define IB_SMA_NUM_RECV_WQES 2 - -/** SMA number of completion queue entries - * - * This is a policy decision - */ -#define IB_SMA_NUM_CQES 8 - -extern int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev, - struct ib_sma_operations *op ); +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 3ffd5e66..c00388e5 100644 --- a/src/include/gpxe/infiniband.h +++ b/src/include/gpxe/infiniband.h @@ -327,6 +327,16 @@ struct ib_device_operations { void ( * mcast_detach ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); + /** Set port information + * + * @v ibdev Infiniband device + * @v port_info New port information + * + * This method is required only by adapters that do not have + * an embedded SMA. + */ + int ( * set_port_info ) ( struct ib_device *ibdev, + const struct ib_port_info *port_info ); }; /** An Infiniband device */ @@ -420,6 +430,8 @@ extern void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); extern int ib_get_hca_info ( struct ib_device *ibdev, struct ib_gid_half *hca_guid ); +extern int ib_set_port_info ( struct ib_device *ibdev, + const struct ib_port_info *port_info ); extern struct ib_device * alloc_ibdev ( size_t priv_size ); extern int register_ibdev ( struct ib_device *ibdev ); extern void unregister_ibdev ( struct ib_device *ibdev ); diff --git a/src/net/infiniband.c b/src/net/infiniband.c index e71b3bcc..38aaf9fc 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -644,6 +644,31 @@ int ib_get_hca_info ( struct ib_device *ibdev, return num_ports; } +/** Set port information + * + * @v ibdev Infiniband device + * @v port_info New port information + */ +int ib_set_port_info ( struct ib_device *ibdev, + const struct ib_port_info *port_info ) { + int rc; + + /* Adapters with embedded SMAs do not need to support this method */ + if ( ! ibdev->op->set_port_info ) { + DBGC ( ibdev, "IBDEV %p does not support setting port " + "information\n", ibdev ); + return -ENOTSUP; + } + + if ( ( rc = ibdev->op->set_port_info ( ibdev, port_info ) ) != 0 ) { + DBGC ( ibdev, "IBDEV %p could not set port information: %s\n", + ibdev, strerror ( rc ) ); + return rc; + } + + return 0; +}; + /*************************************************************************** * * Event queues diff --git a/src/net/infiniband/ib_gma.c b/src/net/infiniband/ib_gma.c index 89f0eeb1..405d7861 100644 --- a/src/net/infiniband/ib_gma.c +++ b/src/net/infiniband/ib_gma.c @@ -86,7 +86,8 @@ static int ib_handle_mad ( struct ib_gma *gma, union ib_mad *mad ) { struct ib_gma_handler *handler; for_each_table_entry ( handler, IB_GMA_HANDLERS ) { - if ( ( handler->mgmt_class == hdr->mgmt_class ) && + if ( ( ( handler->mgmt_class & ~handler->mgmt_class_ignore ) == + ( hdr->mgmt_class & ~handler->mgmt_class_ignore ) ) && ( handler->class_version == hdr->class_version ) && ( handler->method == hdr->method ) && ( handler->attr_id == hdr->attr_id ) ) { diff --git a/src/net/infiniband/ib_sma.c b/src/net/infiniband/ib_sma.c index 007b4d1a..9e99703f 100644 --- a/src/net/infiniband/ib_sma.c +++ b/src/net/infiniband/ib_sma.c @@ -26,7 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include +#include #include /** @@ -39,13 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * Get node information * - * @v sma Subnet management agent - * @v get Attribute to get + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code */ -static void ib_sma_get_node_info ( struct ib_sma *sma, - union ib_smp_data *get ) { - struct ib_device *ibdev = sma->ibdev; - struct ib_node_info *node_info = &get->node_info; +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; @@ -58,18 +59,21 @@ static void ib_sma_get_node_info ( struct ib_sma *sma, sizeof ( node_info->port_guid ) ); node_info->partition_cap = htons ( 1 ); node_info->local_port_num = ibdev->port; + + return 0; } /** * Get node description * - * @v sma Subnet management agent - * @v get Attribute to get + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code */ -static void ib_sma_get_node_desc ( struct ib_sma *sma, - union ib_smp_data *get ) { - struct ib_device *ibdev = sma->ibdev; - struct ib_node_desc *node_desc = &get->node_desc; +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 ) ); @@ -78,34 +82,40 @@ static void ib_sma_get_node_desc ( struct ib_sma *sma, 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 sma Subnet management agent - * @v get Attribute to get + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code */ -static void ib_sma_get_guid_info ( struct ib_sma *sma, - union ib_smp_data *get ) { - struct ib_device *ibdev = sma->ibdev; - struct ib_guid_info *guid_info = &get->guid_info; +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 sma Subnet management agent - * @v get Attribute to get + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code */ -static void ib_sma_get_port_info ( struct ib_sma *sma, - union ib_smp_data *get ) { - struct ib_device *ibdev = sma->ibdev; - struct ib_port_info *port_info = &get->port_info; +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], @@ -129,19 +139,22 @@ static void ib_sma_get_port_info ( struct ib_sma *sma, 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 sma Subnet management agent - * @v set Attribute to set + * @v gma General management agent + * @v mad MAD * @ret rc Return status code */ -static int ib_sma_set_port_info ( struct ib_sma *sma, - const union ib_smp_data *set ) { - struct ib_device *ibdev = sma->ibdev; - const struct ib_port_info *port_info = &set->port_info; +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] ) ); @@ -149,280 +162,116 @@ static int ib_sma_set_port_info ( struct ib_sma *sma, ibdev->sm_lid = ntohs ( port_info->mastersm_lid ); ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf ); - if ( ! sma->op->set_port_info ) { - /* Not an error; we just ignore all other settings */ - return 0; + 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 sma->op->set_port_info ( ibdev, port_info ); + return ib_sma_get_port_info ( gma, mad ); } /** * Get partition key table * - * @v sma Subnet management agent - * @v get Attribute to get + * @v gma General management agent + * @v mad MAD + * @ret rc Return status code */ -static void ib_sma_get_pkey_table ( struct ib_sma *sma, - union ib_smp_data *get ) { - struct ib_device *ibdev = sma->ibdev; - struct ib_pkey_table *pkey_table = &get->pkey_table; +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 sma Subnet management agent - * @v set Attribute to set - */ -static int ib_sma_set_pkey_table ( struct ib_sma *sma, - const union ib_smp_data *get ) { - struct ib_device *ibdev = sma->ibdev; - const struct ib_pkey_table *pkey_table = &get->pkey_table; - - ibdev->pkey = ntohs ( pkey_table->pkey[0] ); - return 0; -} - -/** An attribute handler */ -struct ib_sma_handler { - /** Attribute (in network byte order) */ - uint16_t attr_id; - /** Get attribute - * - * @v sma Subnet management agent - * @v get Attribute to get - * @ret rc Return status code - */ - void ( * get ) ( struct ib_sma *sma, union ib_smp_data *get ); - /** Set attribute - * - * @v sma Subnet management agent - * @v set Attribute to set - * @ret rc Return status code - */ - int ( * set ) ( struct ib_sma *sma, const union ib_smp_data *set ); -}; - -/** List of attribute handlers */ -static struct ib_sma_handler ib_sma_handlers[] = { - { htons ( IB_SMP_ATTR_NODE_DESC ), - ib_sma_get_node_desc, NULL }, - { htons ( IB_SMP_ATTR_NODE_INFO ), - ib_sma_get_node_info, NULL }, - { htons ( IB_SMP_ATTR_GUID_INFO ), - ib_sma_get_guid_info, NULL }, - { htons ( IB_SMP_ATTR_PORT_INFO ), - ib_sma_get_port_info, ib_sma_set_port_info }, - { htons ( IB_SMP_ATTR_PKEY_TABLE ), - ib_sma_get_pkey_table, ib_sma_set_pkey_table }, -}; - -/** - * Identify attribute handler - * - * @v attr_id Attribute ID (in network byte order) - * @ret handler Attribute handler (or NULL) - */ -static struct ib_sma_handler * ib_sma_handler ( uint16_t attr_id ) { - struct ib_sma_handler *handler; - unsigned int i; - - for ( i = 0 ; i < ( sizeof ( ib_sma_handlers ) / - sizeof ( ib_sma_handlers[0] ) ) ; i++ ) { - handler = &ib_sma_handlers[i]; - if ( handler->attr_id == attr_id ) - return handler; - } - - return NULL; -} - -/** - * Respond to management datagram - * - * @v sma Subnet management agent - * @v mad Management datagram + * @v gma General management agent + * @v mad MAD * @ret rc Return status code */ -static int ib_sma_mad ( struct ib_sma *sma, union ib_mad *mad ) { - struct ib_device *ibdev = sma->ibdev; - struct ib_mad_hdr *hdr = &mad->hdr; - struct ib_mad_smp *smp = &mad->smp; - struct ib_sma_handler *handler = NULL; - unsigned int hop_pointer; - unsigned int hop_count; - int rc; +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; - DBGC ( sma, "SMA %p received SMP with bv=%02x mc=%02x cv=%02x " - "meth=%02x attr=%04x mod=%08x\n", sma, hdr->base_version, - hdr->mgmt_class, hdr->class_version, hdr->method, - ntohs ( hdr->attr_id ), ntohl ( hdr->attr_mod ) ); - DBGC2_HDA ( sma, 0, mad, sizeof ( *mad ) ); + ibdev->pkey = ntohs ( pkey_table->pkey[0] ); - /* Sanity checks */ - if ( hdr->base_version != IB_MGMT_BASE_VERSION ) { - DBGC ( sma, "SMA %p unsupported base version %x\n", - sma, hdr->base_version ); - return -ENOTSUP; - } - if ( ( hdr->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ) && - ( hdr->mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED ) ) { - DBGC ( sma, "SMA %p unsupported management class %x\n", - sma, hdr->mgmt_class ); - return -ENOTSUP; - } - if ( hdr->class_version != IB_SMP_CLASS_VERSION ) { - DBGC ( sma, "SMA %p unsupported class version %x\n", - sma, hdr->class_version ); - return -ENOTSUP; - } - if ( ( hdr->method != IB_MGMT_METHOD_GET ) && - ( hdr->method != IB_MGMT_METHOD_SET ) ) { - DBGC ( sma, "SMA %p unsupported method %x\n", - sma, hdr->method ); - return -ENOTSUP; - } - - /* Identify handler */ - if ( ! ( handler = ib_sma_handler ( hdr->attr_id ) ) ) { - DBGC ( sma, "SMA %p unsupported attribute %x\n", - sma, ntohs ( hdr->attr_id ) ); - hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); - goto respond_without_data; - } - - /* Set attribute (if applicable) */ - if ( hdr->method != IB_MGMT_METHOD_SET ) { - hdr->status = htons ( IB_MGMT_STATUS_OK ); - goto respond; - } - if ( ! handler->set ) { - DBGC ( sma, "SMA %p attribute %x is unsettable\n", - sma, ntohs ( hdr->attr_id ) ); - hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); - goto respond; - } - if ( ( rc = handler->set ( sma, &smp->smp_data ) ) != 0 ) { - DBGC ( sma, "SMA %p could not set attribute %x: %s\n", - sma, ntohs ( hdr->attr_id ), strerror ( rc ) ); - hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); - goto respond; - } - - hdr->status = htons ( IB_MGMT_STATUS_OK ); - - respond: - /* Get attribute */ - handler->get ( sma, &smp->smp_data ); - - respond_without_data: - - /* Set method to "Get Response" */ - hdr->method = IB_MGMT_METHOD_GET_RESP; - - /* Set response fields for directed route SMPs */ - if ( hdr->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ) { - hdr->status |= htons ( IB_SMP_STATUS_D_INBOUND ); - hop_pointer = smp->mad_hdr.class_specific.smp.hop_pointer; - hop_count = smp->mad_hdr.class_specific.smp.hop_count; - assert ( hop_count == hop_pointer ); - if ( hop_pointer < ( sizeof ( smp->return_path.hops ) / - sizeof ( smp->return_path.hops[0] ) ) ) { - smp->return_path.hops[hop_pointer] = ibdev->port; - } else { - DBGC ( sma, "SMA %p invalid hop pointer %d\n", - sma, hop_pointer ); - return -EINVAL; - } - } - - DBGC ( sma, "SMA %p responding with status=%04x\n", - sma, ntohs ( hdr->status ) ); - DBGC2_HDA ( sma, 0, mad, sizeof ( *mad ) ); - - return 0; + return ib_sma_get_pkey_table ( gma, mad ); } -/** - * Complete SMA send - * - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void ib_sma_complete_send ( struct ib_device *ibdev __unused, - struct ib_queue_pair *qp, - struct io_buffer *iobuf, int rc ) { - struct ib_sma *sma = ib_qp_get_ownerdata ( qp ); - - if ( rc != 0 ) { - DBGC ( sma, "SMA %p send completion error: %s\n", - sma, strerror ( rc ) ); - } - free_iob ( iobuf ); -} - -/** - * Complete SMA receive - * - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v av Address vector - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void ib_sma_complete_recv ( struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct ib_address_vector *av, - struct io_buffer *iobuf, int rc ) { - struct ib_sma *sma = ib_qp_get_ownerdata ( qp ); - union ib_mad *mad; - - /* Ignore errors */ - if ( rc != 0 ) { - DBGC ( sma, "SMA %p RX error: %s\n", sma, strerror ( rc ) ); - goto err; - } - - /* Sanity check */ - if ( iob_len ( iobuf ) != sizeof ( *mad ) ) { - DBGC ( sma, "SMA %p RX bad size (%zd bytes)\n", - sma, iob_len ( iobuf ) ); - goto err; - } - mad = iobuf->data; - - /* Construct MAD response */ - if ( ( rc = ib_sma_mad ( sma, mad ) ) != 0 ) { - DBGC ( sma, "SMA %p could not construct MAD response: %s\n", - sma, strerror ( rc ) ); - goto err; - } - - /* Send MAD response */ - if ( ( rc = ib_post_send ( ibdev, qp, av, iobuf ) ) != 0 ) { - DBGC ( sma, "SMA %p could not send MAD response: %s\n", - sma, strerror ( rc ) ); - goto err; - } - - return; - - err: - free_iob ( iobuf ); -} - -/** SMA completion operations */ -static struct ib_completion_queue_operations ib_sma_completion_ops = { - .complete_send = ib_sma_complete_send, - .complete_recv = ib_sma_complete_recv, +/** 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, + }, }; /** @@ -433,49 +282,29 @@ static struct ib_completion_queue_operations ib_sma_completion_ops = { * @v op Subnet management operations * @ret rc Return status code */ -int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev, - struct ib_sma_operations *op ) { +int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev ) { int rc; - /* Initialise fields */ - memset ( sma, 0, sizeof ( *sma ) ); - sma->ibdev = ibdev; - sma->op = op; - - /* Create completion queue */ - sma->cq = ib_create_cq ( ibdev, IB_SMA_NUM_CQES, - &ib_sma_completion_ops ); - if ( ! sma->cq ) { - rc = -ENOMEM; - goto err_create_cq; + /* Initialise GMA */ + if ( ( rc = ib_create_gma ( &sma->gma, ibdev, 0 ) ) != 0 ) { + DBGC ( sma, "SMA %p could not create GMA: %s\n", + sma, strerror ( rc ) ); + goto err_create_gma; } - /* Create queue pair */ - sma->qp = ib_create_qp ( ibdev, IB_SMA_NUM_SEND_WQES, sma->cq, - IB_SMA_NUM_RECV_WQES, sma->cq, 0 ); - if ( ! sma->qp ) { - rc = -ENOMEM; - goto err_create_qp; - } - ib_qp_set_ownerdata ( sma->qp, sma ); - /* If we don't get QP0, we can't function */ - if ( sma->qp->qpn != IB_QPN_SMA ) { + if ( sma->gma.qp->qpn != IB_QPN_SMA ) { DBGC ( sma, "SMA %p on QPN %lx, needs to be on QPN 0\n", - sma, sma->qp->qpn ); + sma, sma->gma.qp->qpn ); rc = -ENOTSUP; goto err_not_qp0; } - /* Fill receive ring */ - ib_refill_recv ( ibdev, sma->qp ); return 0; err_not_qp0: - ib_destroy_qp ( ibdev, sma->qp ); - err_create_qp: - ib_destroy_cq ( ibdev, sma->cq ); - err_create_cq: + ib_destroy_gma ( &sma->gma ); + err_create_gma: return rc; } @@ -485,8 +314,6 @@ int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev, * @v sma Subnet management agent */ void ib_destroy_sma ( struct ib_sma *sma ) { - struct ib_device *ibdev = sma->ibdev; - ib_destroy_qp ( ibdev, sma->qp ); - ib_destroy_cq ( ibdev, sma->cq ); + ib_destroy_gma ( &sma->gma ); }