/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * Based in part upon the original driver by Mellanox Technologies
- * Ltd. Portions may be Copyright (c) Mellanox Technologies Ltd.
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2008 Mellanox Technologies Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/infiniband.h>
-#include <gpxe/ipoib.h>
#include "hermon.h"
/**
*
*/
-/* Port to use */
-#define PXE_IB_PORT 1
-
/***************************************************************************
*
* Queue number allocation
}
static inline int
-hermon_cmd_mad_ifc ( struct hermon *hermon, union hermonprm_mad *mad ) {
+hermon_cmd_mad_ifc ( struct hermon *hermon, unsigned int port,
+ union hermonprm_mad *mad ) {
return hermon_cmd ( hermon,
HERMON_HCR_INOUT_CMD ( HERMON_HCR_MAD_IFC,
1, sizeof ( *mad ),
1, sizeof ( *mad ) ),
- 0x03, mad, PXE_IB_PORT, mad );
+ 0x03, mad, port, mad );
}
static inline int
*/
static int hermon_create_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) {
- struct hermon *hermon = ibdev->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_completion_queue *hermon_cq;
struct hermonprm_completion_queue_context cqctx;
int cqn_offset;
DBGC ( hermon, "Hermon %p CQN %#lx ring at [%p,%p)\n",
hermon, cq->cqn, hermon_cq->cqe,
( ( ( void * ) hermon_cq->cqe ) + hermon_cq->cqe_size ) );
- cq->dev_priv = hermon_cq;
+ ib_cq_set_drvdata ( cq, hermon_cq );
return 0;
err_sw2hw_cq:
*/
static void hermon_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) {
- struct hermon *hermon = ibdev->dev_priv;
- struct hermon_completion_queue *hermon_cq = cq->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
struct hermonprm_completion_queue_context cqctx;
int cqn_offset;
int rc;
cqn_offset = ( cq->cqn - hermon->cap.reserved_cqs );
hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 );
- cq->dev_priv = NULL;
+ ib_cq_set_drvdata ( cq, NULL );
}
/***************************************************************************
*/
static int hermon_create_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp ) {
- struct hermon *hermon = ibdev->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_queue_pair *hermon_qp;
struct hermonprm_qp_ee_state_transitions qpctx;
int qpn_offset;
goto err_alloc_mtt;
}
- /* Hand queue over to hardware */
+ /* Transition queue to INIT state */
memset ( &qpctx, 0, sizeof ( qpctx ) );
MLX_FILL_2 ( &qpctx, 2,
qpc_eec_data.pm_state, 0x03 /* Always 0x03 for UD */,
goto err_rst2init_qp;
}
+ /* Transition queue to RTR state */
memset ( &qpctx, 0, sizeof ( qpctx ) );
MLX_FILL_2 ( &qpctx, 4,
qpc_eec_data.mtu, HERMON_MTU_2048,
MLX_FILL_1 ( &qpctx, 16,
qpc_eec_data.primary_address_path.sched_queue,
( 0x83 /* default policy */ |
- ( ( PXE_IB_PORT - 1 ) << 6 ) ) );
+ ( ( ibdev->port - 1 ) << 6 ) ) );
if ( ( rc = hermon_cmd_init2rtr_qp ( hermon, qp->qpn,
&qpctx ) ) != 0 ) {
DBGC ( hermon, "Hermon %p INIT2RTR_QP failed: %s\n",
DBGC ( hermon, "Hermon %p QPN %#lx receive ring at [%p,%p)\n",
hermon, qp->qpn, hermon_qp->recv.wqe,
( ((void *)hermon_qp->recv.wqe ) + hermon_qp->recv.wqe_size ) );
- qp->dev_priv = hermon_qp;
+ ib_qp_set_drvdata ( qp, hermon_qp );
return 0;
err_rtr2rts_qp:
*/
static void hermon_destroy_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp ) {
- struct hermon *hermon = ibdev->dev_priv;
- struct hermon_queue_pair *hermon_qp = qp->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
int qpn_offset;
int rc;
hermon->cap.reserved_qps );
hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 );
- qp->dev_priv = NULL;
+ ib_qp_set_drvdata ( qp, NULL );
}
/***************************************************************************
struct ib_queue_pair *qp,
struct ib_address_vector *av,
struct io_buffer *iobuf ) {
- struct hermon *hermon = ibdev->dev_priv;
- struct hermon_queue_pair *hermon_qp = qp->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
struct ib_work_queue *wq = &qp->send;
struct hermon_send_work_queue *hermon_send_wq = &hermon_qp->send;
struct hermonprm_ud_send_wqe *wqe;
MLX_FILL_1 ( &wqe->ctrl, 2, c, 0x03 /* generate completion */ );
MLX_FILL_2 ( &wqe->ud, 0,
ud_address_vector.pd, HERMON_GLOBAL_PD,
- ud_address_vector.port_number, PXE_IB_PORT );
+ ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud, 1,
ud_address_vector.rlid, av->dlid,
ud_address_vector.g, av->gid_present );
static int hermon_post_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
struct io_buffer *iobuf ) {
- struct hermon *hermon = ibdev->dev_priv;
- struct hermon_queue_pair *hermon_qp = qp->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
struct ib_work_queue *wq = &qp->recv;
struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv;
struct hermonprm_recv_wqe *wqe;
union hermonprm_completion_entry *cqe,
ib_completer_t complete_send,
ib_completer_t complete_recv ) {
- struct hermon *hermon = ibdev->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
struct ib_completion completion;
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
return -EIO;
}
qp = wq->qp;
- hermon_qp = qp->dev_priv;
+ hermon_qp = ib_qp_get_drvdata ( qp );
/* Identify I/O buffer */
wqe_idx = ( MLX_GET ( &cqe->normal, wqe_counter ) &
struct ib_completion_queue *cq,
ib_completer_t complete_send,
ib_completer_t complete_recv ) {
- struct hermon *hermon = ibdev->dev_priv;
- struct hermon_completion_queue *hermon_cq = cq->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
union hermonprm_completion_entry *cqe;
unsigned int cqe_idx_mask;
int rc;
}
}
+/***************************************************************************
+ *
+ * Infiniband link-layer operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Initialise Infiniband link
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int hermon_open ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermonprm_init_port init_port;
+ int rc;
+
+ memset ( &init_port, 0, sizeof ( init_port ) );
+ MLX_FILL_2 ( &init_port, 0,
+ port_width_cap, 3,
+ vl_cap, 1 );
+ MLX_FILL_2 ( &init_port, 1,
+ mtu, HERMON_MTU_2048,
+ max_gid, 1 );
+ MLX_FILL_1 ( &init_port, 2, max_pkey, 64 );
+ if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port,
+ &init_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not intialise port: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Close Infiniband link
+ *
+ * @v ibdev Infiniband device
+ */
+static void hermon_close ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ int rc;
+
+ if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not close port: %s\n",
+ hermon, strerror ( rc ) );
+ /* Nothing we can do about this */
+ }
+}
+
/***************************************************************************
*
* Multicast group operations
static int hermon_mcast_attach ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
struct ib_gid *gid ) {
- struct hermon *hermon = ibdev->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermonprm_mgm_hash hash;
struct hermonprm_mcg_entry mcg;
unsigned int index;
static void hermon_mcast_detach ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused,
struct ib_gid *gid ) {
- struct hermon *hermon = ibdev->dev_priv;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermonprm_mgm_hash hash;
struct hermonprm_mcg_entry mcg;
unsigned int index;
}
}
-/** Hermon Infiniband operations */
-static struct ib_device_operations hermon_ib_operations = {
- .create_cq = hermon_create_cq,
- .destroy_cq = hermon_destroy_cq,
- .create_qp = hermon_create_qp,
- .destroy_qp = hermon_destroy_qp,
- .post_send = hermon_post_send,
- .post_recv = hermon_post_recv,
- .poll_cq = hermon_poll_cq,
- .mcast_attach = hermon_mcast_attach,
- .mcast_detach = hermon_mcast_detach,
-};
-
/***************************************************************************
*
- * MAD IFC operations
+ * MAD operations
*
***************************************************************************
*/
-static int hermon_mad_ifc ( struct hermon *hermon,
- union hermonprm_mad *mad ) {
- struct ib_mad_hdr *hdr = &mad->mad.mad_hdr;
- int rc;
-
- hdr->base_version = IB_MGMT_BASE_VERSION;
- if ( ( rc = hermon_cmd_mad_ifc ( hermon, mad ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
- if ( hdr->status != 0 ) {
- DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
- hermon, ntohs ( hdr->status ) );
- return -EIO;
- }
- return 0;
-}
-
-static int hermon_get_port_info ( struct hermon *hermon,
- struct ib_mad_port_info *port_info ) {
- union hermonprm_mad mad;
- struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
- int rc;
-
- memset ( &mad, 0, sizeof ( mad ) );
- hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- hdr->class_version = 1;
- hdr->method = IB_MGMT_METHOD_GET;
- hdr->attr_id = htons ( IB_SMP_ATTR_PORT_INFO );
- hdr->attr_mod = htonl ( PXE_IB_PORT );
- if ( ( rc = hermon_mad_ifc ( hermon, &mad ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not get port info: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
- memcpy ( port_info, &mad.mad.port_info, sizeof ( *port_info ) );
- return 0;
-}
-
-static int hermon_get_guid_info ( struct hermon *hermon,
- struct ib_mad_guid_info *guid_info ) {
- union hermonprm_mad mad;
- struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
- int rc;
-
- memset ( &mad, 0, sizeof ( mad ) );
- hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- hdr->class_version = 1;
- hdr->method = IB_MGMT_METHOD_GET;
- hdr->attr_id = htons ( IB_SMP_ATTR_GUID_INFO );
- if ( ( rc = hermon_mad_ifc ( hermon, &mad ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not get GUID info: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
- memcpy ( guid_info, &mad.mad.guid_info, sizeof ( *guid_info ) );
- return 0;
-}
-
-static int hermon_get_pkey_table ( struct hermon *hermon,
- struct ib_mad_pkey_table *pkey_table ) {
- union hermonprm_mad mad;
- struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
- int rc;
-
- memset ( &mad, 0, sizeof ( mad ) );
- hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- hdr->class_version = 1;
- hdr->method = IB_MGMT_METHOD_GET;
- hdr->attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE );
- if ( ( rc = hermon_mad_ifc ( hermon, &mad ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not get pkey table: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
- memcpy ( pkey_table, &mad.mad.pkey_table, sizeof ( *pkey_table ) );
- return 0;
-}
-
-static int hermon_get_port_gid ( struct hermon *hermon,
- struct ib_gid *port_gid ) {
- union {
- /* This union exists just to save stack space */
- struct ib_mad_port_info port_info;
- struct ib_mad_guid_info guid_info;
- } u;
- int rc;
-
- /* Port info gives us the first half of the port GID */
- if ( ( rc = hermon_get_port_info ( hermon, &u.port_info ) ) != 0 )
- return rc;
- memcpy ( &port_gid->u.bytes[0], u.port_info.gid_prefix, 8 );
-
- /* GUID info gives us the second half of the port GID */
- if ( ( rc = hermon_get_guid_info ( hermon, &u.guid_info ) ) != 0 )
- return rc;
- memcpy ( &port_gid->u.bytes[8], u.guid_info.gid_local, 8 );
-
- return 0;
-}
-
-static int hermon_get_sm_lid ( struct hermon *hermon,
- unsigned long *sm_lid ) {
- struct ib_mad_port_info port_info;
- int rc;
-
- if ( ( rc = hermon_get_port_info ( hermon, &port_info ) ) != 0 )
- return rc;
- *sm_lid = ntohs ( port_info.mastersm_lid );
- return 0;
-}
-
-static int hermon_get_pkey ( struct hermon *hermon, unsigned int *pkey ) {
- struct ib_mad_pkey_table pkey_table;
- int rc;
-
- if ( ( rc = hermon_get_pkey_table ( hermon, &pkey_table ) ) != 0 )
- return rc;
- *pkey = ntohs ( pkey_table.pkey[0][0] );
- return 0;
-}
-
-/**
- * Wait for link up
- *
- * @v hermon Hermon device
- * @ret rc Return status code
- *
- * This function shouldn't really exist. Unfortunately, IB links take
- * a long time to come up, and we can't get various key parameters
- * e.g. our own IPoIB MAC address without information from the subnet
- * manager). We should eventually make link-up an asynchronous event.
- */
-static int hermon_wait_for_link ( struct hermon *hermon ) {
- struct ib_mad_port_info port_info;
- unsigned int retries;
- int rc;
-
- printf ( "Waiting for Infiniband link-up..." );
- for ( retries = 20 ; retries ; retries-- ) {
- if ( ( rc = hermon_get_port_info ( hermon,
- &port_info ) ) != 0 )
- continue;
- if ( ( ( port_info.port_state__link_speed_supported ) & 0xf )
- == 4 ) {
- printf ( "ok\n" );
- return 0;
- }
- printf ( "." );
- sleep ( 1 );
- }
- printf ( "failed\n" );
- return -ENODEV;
-};
-
/**
- * Get MAD parameters
+ * Issue management datagram
*
- * @v hermon Hermon device
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @v len Length of management datagram
* @ret rc Return status code
*/
-static int hermon_get_mad_params ( struct ib_device *ibdev ) {
- struct hermon *hermon = ibdev->dev_priv;
+static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
+ size_t len ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ union hermonprm_mad mad_ifc;
int rc;
- /* Get subnet manager LID */
- if ( ( rc = hermon_get_sm_lid ( hermon, &ibdev->sm_lid ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not determine subnet manager "
- "LID: %s\n", hermon, strerror ( rc ) );
- return rc;
- }
+ /* Copy in request packet */
+ memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
+ assert ( len <= sizeof ( mad_ifc.mad ) );
+ memcpy ( &mad_ifc.mad, mad, len );
- /* Get port GID */
- if ( ( rc = hermon_get_port_gid ( hermon, &ibdev->port_gid ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not determine port GID: %s\n",
+ /* Issue MAD */
+ if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
+ &mad_ifc ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
hermon, strerror ( rc ) );
return rc;
}
- /* Get partition key */
- if ( ( rc = hermon_get_pkey ( hermon, &ibdev->pkey ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not determine partition key: "
- "%s\n", hermon, strerror ( rc ) );
- return rc;
- }
+ /* Copy out reply packet */
+ memcpy ( mad, &mad_ifc.mad, len );
+ if ( mad->status != 0 ) {
+ DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
+ hermon, ntohs ( mad->status ) );
+ return -EIO;
+ }
return 0;
}
+/** Hermon Infiniband operations */
+static struct ib_device_operations hermon_ib_operations = {
+ .create_cq = hermon_create_cq,
+ .destroy_cq = hermon_destroy_cq,
+ .create_qp = hermon_create_qp,
+ .destroy_qp = hermon_destroy_qp,
+ .post_send = hermon_post_send,
+ .post_recv = hermon_post_recv,
+ .poll_cq = hermon_poll_cq,
+ .open = hermon_open,
+ .close = hermon_close,
+ .mcast_attach = hermon_mcast_attach,
+ .mcast_detach = hermon_mcast_detach,
+ .mad = hermon_mad,
+};
+
/***************************************************************************
*
* Firmware control
hermon->icm = UNULL;
}
-/***************************************************************************
- *
- * Infiniband link-layer operations
- *
- ***************************************************************************
- */
-
-/**
- * Initialise Infiniband link
- *
- * @v hermon Hermon device
- * @ret rc Return status code
- */
-static int hermon_init_port ( struct hermon *hermon ) {
- struct hermonprm_init_port init_port;
- int rc;
-
- memset ( &init_port, 0, sizeof ( init_port ) );
- MLX_FILL_2 ( &init_port, 0,
- port_width_cap, 3,
- vl_cap, 1 );
- MLX_FILL_2 ( &init_port, 1,
- mtu, HERMON_MTU_2048,
- max_gid, 1 );
- MLX_FILL_1 ( &init_port, 2, max_pkey, 64 );
- if ( ( rc = hermon_cmd_init_port ( hermon, PXE_IB_PORT,
- &init_port ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not intialise port: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-/**
- * Close Infiniband link
- *
- * @v hermon Hermon device
- */
-static void hermon_close_port ( struct hermon *hermon ) {
- int rc;
-
- if ( ( rc = hermon_cmd_close_port ( hermon, PXE_IB_PORT ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not close port: %s\n",
- hermon, strerror ( rc ) );
- /* Nothing we can do about this */
- }
-}
-
/***************************************************************************
*
* PCI interface
*/
static int hermon_probe ( struct pci_device *pci,
const struct pci_device_id *id __unused ) {
- struct ib_device *ibdev;
struct hermon *hermon;
+ struct ib_device *ibdev;
struct hermonprm_init_hca init_hca;
+ int i;
int rc;
- /* Allocate Infiniband device */
- ibdev = alloc_ibdev ( sizeof ( *hermon ) );
- if ( ! ibdev ) {
+ /* Allocate Hermon device */
+ hermon = zalloc ( sizeof ( *hermon ) );
+ if ( ! hermon ) {
rc = -ENOMEM;
- goto err_ibdev;
+ goto err_alloc_hermon;
+ }
+ pci_set_drvdata ( pci, hermon );
+
+ /* Allocate Infiniband devices */
+ for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ ) {
+ ibdev = alloc_ibdev ( 0 );
+ if ( ! ibdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_ibdev;
+ }
+ hermon->ibdev[i] = ibdev;
+ ibdev->op = &hermon_ib_operations;
+ ibdev->dev = &pci->dev;
+ ibdev->port = ( HERMON_PORT_BASE + i );
+ ib_set_drvdata ( ibdev, hermon );
}
- ibdev->op = &hermon_ib_operations;
- pci_set_drvdata ( pci, ibdev );
- ibdev->dev = &pci->dev;
- hermon = ibdev->dev_priv;
- memset ( hermon, 0, sizeof ( *hermon ) );
/* Fix up PCI device */
adjust_pci_device ( pci );
if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
goto err_setup_mpt;
- /* Bring up IB layer */
- if ( ( rc = hermon_init_port ( hermon ) ) != 0 )
- goto err_init_port;
-
- /* Wait for link */
- if ( ( rc = hermon_wait_for_link ( hermon ) ) != 0 )
- goto err_wait_for_link;
-
- /* Get MAD parameters */
- if ( ( rc = hermon_get_mad_params ( ibdev ) ) != 0 )
- goto err_get_mad_params;
-
- DBGC ( hermon, "Hermon %p port GID is %08lx:%08lx:%08lx:%08lx\n",
- hermon, htonl ( ibdev->port_gid.u.dwords[0] ),
- htonl ( ibdev->port_gid.u.dwords[1] ),
- htonl ( ibdev->port_gid.u.dwords[2] ),
- htonl ( ibdev->port_gid.u.dwords[3] ) );
-
- /* Add IPoIB device */
- if ( ( rc = ipoib_probe ( ibdev ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not add IPoIB device: %s\n",
- hermon, strerror ( rc ) );
- goto err_ipoib_probe;
+ /* Register Infiniband devices */
+ for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ ) {
+ if ( ( rc = register_ibdev ( hermon->ibdev[i] ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not register IB "
+ "device: %s\n", hermon, strerror ( rc ) );
+ goto err_register_ibdev;
+ }
}
return 0;
- err_ipoib_probe:
- err_get_mad_params:
- err_wait_for_link:
- hermon_close_port ( hermon );
- err_init_port:
+ i = ( HERMON_NUM_PORTS - 1 );
+ err_register_ibdev:
+ for ( ; i >= 0 ; i-- )
+ unregister_ibdev ( hermon->ibdev[i] );
err_setup_mpt:
hermon_cmd_close_hca ( hermon );
err_init_hca:
err_mailbox_out:
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
err_mailbox_in:
- free_ibdev ( ibdev );
- err_ibdev:
+ i = ( HERMON_NUM_PORTS - 1 );
+ err_alloc_ibdev:
+ for ( ; i >= 0 ; i-- )
+ free_ibdev ( hermon->ibdev[i] );
+ free ( hermon );
+ err_alloc_hermon:
return rc;
}
* @v pci PCI device
*/
static void hermon_remove ( struct pci_device *pci ) {
- struct ib_device *ibdev = pci_get_drvdata ( pci );
- struct hermon *hermon = ibdev->dev_priv;
+ struct hermon *hermon = pci_get_drvdata ( pci );
+ int i;
- ipoib_remove ( ibdev );
- hermon_close_port ( hermon );
+ for ( i = ( HERMON_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
+ unregister_ibdev ( hermon->ibdev[i] );
hermon_cmd_close_hca ( hermon );
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 );
- free_ibdev ( ibdev );
+ for ( i = ( HERMON_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
+ free_ibdev ( hermon->ibdev[i] );
+ free ( hermon );
}
static struct pci_device_id hermon_nics[] = {