From bc3f0a25c6e3ce8344fa3c255a8e3a981f59309b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 27 Feb 2008 13:59:56 +0000 Subject: [PATCH] [Infiniband] Add preliminary support for multi-port devices. Arbel and Hermon cards both have multiple ports. Add the infrastructure required to register each port as a separate IB device. Don't yet register more than one port, since registration will currently fail unless a valid link is detected. Use ib_*_{set,get}_{drv,owner}data wrappers to access driver- and owner-private data on Infiniband structures. --- src/drivers/infiniband/arbel.c | 115 +++++++++++++++----------- src/drivers/infiniband/arbel.h | 7 ++ src/drivers/infiniband/hermon.c | 115 +++++++++++++++----------- src/drivers/infiniband/hermon.h | 7 ++ src/drivers/net/ipoib.c | 10 +-- src/include/gpxe/infiniband.h | 138 ++++++++++++++++++++++++++++---- src/net/infiniband.c | 11 ++- 7 files changed, 284 insertions(+), 119 deletions(-) diff --git a/src/drivers/infiniband/arbel.c b/src/drivers/infiniband/arbel.c index 8e2187fc..147cf8b9 100644 --- a/src/drivers/infiniband/arbel.c +++ b/src/drivers/infiniband/arbel.c @@ -43,9 +43,6 @@ * */ -/* Port to use */ -#define PXE_IB_PORT 1 - /*************************************************************************** * * Queue number allocation @@ -482,7 +479,7 @@ arbel_cmd_map_fa ( struct arbel *arbel, */ static int arbel_create_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbel_completion_queue *arbel_cq; struct arbelprm_completion_queue_context cqctx; struct arbelprm_cq_ci_db_record *ci_db_rec; @@ -560,7 +557,7 @@ static int arbel_create_cq ( struct ib_device *ibdev, DBGC ( arbel, "Arbel %p CQN %#lx ring at [%p,%p)\n", arbel, cq->cqn, arbel_cq->cqe, ( ( ( void * ) arbel_cq->cqe ) + arbel_cq->cqe_size ) ); - cq->dev_priv = arbel_cq; + ib_cq_set_drvdata ( cq, arbel_cq ); return 0; err_sw2hw_cq: @@ -583,8 +580,8 @@ static int arbel_create_cq ( struct ib_device *ibdev, */ static void arbel_destroy_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ) { - struct arbel *arbel = ibdev->dev_priv; - struct arbel_completion_queue *arbel_cq = cq->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); + struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq ); struct arbelprm_completion_queue_context cqctx; struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_arm_db_record *arm_db_rec; @@ -613,7 +610,7 @@ static void arbel_destroy_cq ( struct ib_device *ibdev, cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs ); arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset ); - cq->dev_priv = NULL; + ib_cq_set_drvdata ( cq, NULL ); } /*************************************************************************** @@ -712,7 +709,7 @@ static int arbel_create_recv_wq ( struct arbel_recv_work_queue *arbel_recv_wq, */ static int arbel_create_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbel_queue_pair *arbel_qp; struct arbelprm_qp_ee_state_transitions qpctx; struct arbelprm_qp_db_record *send_db_rec; @@ -819,7 +816,7 @@ static int arbel_create_qp ( struct ib_device *ibdev, DBGC ( arbel, "Arbel %p QPN %#lx receive ring at [%p,%p)\n", arbel, qp->qpn, arbel_qp->recv.wqe, ( ( (void *) arbel_qp->recv.wqe ) + arbel_qp->recv.wqe_size ) ); - qp->dev_priv = arbel_qp; + ib_qp_set_drvdata ( qp, arbel_qp ); return 0; err_rtr2rts_qpee: @@ -847,8 +844,8 @@ static int arbel_create_qp ( struct ib_device *ibdev, */ static void arbel_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { - struct arbel *arbel = ibdev->dev_priv; - struct arbel_queue_pair *arbel_qp = qp->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); + struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); struct arbelprm_qp_db_record *send_db_rec; struct arbelprm_qp_db_record *recv_db_rec; int qpn_offset; @@ -877,7 +874,7 @@ static void arbel_destroy_qp ( struct ib_device *ibdev, qpn_offset = ( qp->qpn - ARBEL_QPN_BASE - arbel->limits.reserved_qps ); arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset ); - qp->dev_priv = NULL; + ib_qp_set_drvdata ( qp, NULL ); } /*************************************************************************** @@ -926,8 +923,8 @@ static int arbel_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf ) { - struct arbel *arbel = ibdev->dev_priv; - struct arbel_queue_pair *arbel_qp = qp->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); + struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); struct ib_work_queue *wq = &qp->send; struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send; struct arbelprm_ud_send_wqe *prev_wqe; @@ -1016,8 +1013,8 @@ static int arbel_post_send ( struct ib_device *ibdev, static int arbel_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf ) { - struct arbel *arbel = ibdev->dev_priv; - struct arbel_queue_pair *arbel_qp = qp->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); + struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); struct ib_work_queue *wq = &qp->recv; struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv; struct arbelprm_recv_wqe *wqe; @@ -1066,7 +1063,7 @@ static int arbel_complete ( struct ib_device *ibdev, union arbelprm_completion_entry *cqe, ib_completer_t complete_send, ib_completer_t complete_recv ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); struct ib_completion completion; struct ib_work_queue *wq; struct ib_queue_pair *qp; @@ -1108,7 +1105,7 @@ static int arbel_complete ( struct ib_device *ibdev, return -EIO; } qp = wq->qp; - arbel_qp = qp->dev_priv; + arbel_qp = ib_qp_get_drvdata ( qp ); arbel_send_wq = &arbel_qp->send; arbel_recv_wq = &arbel_qp->recv; @@ -1170,8 +1167,8 @@ static void arbel_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq, ib_completer_t complete_send, ib_completer_t complete_recv ) { - struct arbel *arbel = ibdev->dev_priv; - struct arbel_completion_queue *arbel_cq = cq->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); + struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq ); struct arbelprm_cq_ci_db_record *ci_db_rec; union arbelprm_completion_entry *cqe; unsigned int cqe_idx_mask; @@ -1220,7 +1217,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev, * @ret rc Return status code */ static int arbel_open ( struct ib_device *ibdev ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbelprm_init_ib init_ib; int rc; @@ -1247,7 +1244,7 @@ static int arbel_open ( struct ib_device *ibdev ) { * @v ibdev Infiniband device */ static void arbel_close ( struct ib_device *ibdev ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); int rc; if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) { @@ -1275,7 +1272,7 @@ static void arbel_close ( struct ib_device *ibdev ) { static int arbel_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbelprm_mgm_hash hash; struct arbelprm_mgm_entry mgm; unsigned int index; @@ -1330,7 +1327,7 @@ static int arbel_mcast_attach ( struct ib_device *ibdev, static void arbel_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, struct ib_gid *gid ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbelprm_mgm_hash hash; struct arbelprm_mgm_entry mgm; unsigned int index; @@ -1370,7 +1367,7 @@ static void arbel_mcast_detach ( struct ib_device *ibdev, */ static int arbel_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) { - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = ib_get_drvdata ( ibdev ); union arbelprm_mad mad_ifc; int rc; @@ -1837,23 +1834,33 @@ static int arbel_setup_mpt ( struct arbel *arbel ) { */ static int arbel_probe ( struct pci_device *pci, const struct pci_device_id *id __unused ) { - struct ib_device *ibdev; struct arbel *arbel; + struct ib_device *ibdev; struct arbelprm_init_hca init_hca; + int i; int rc; - /* Allocate Infiniband device */ - ibdev = alloc_ibdev ( sizeof ( *arbel ) ); - if ( ! ibdev ) { + /* Allocate Arbel device */ + arbel = zalloc ( sizeof ( *arbel ) ); + if ( ! arbel ) { rc = -ENOMEM; - goto err_ibdev; + goto err_alloc_arbel; + } + pci_set_drvdata ( pci, arbel ); + + /* Allocate Infiniband devices */ + for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) { + ibdev = alloc_ibdev ( 0 ); + if ( ! ibdev ) { + rc = -ENOMEM; + goto err_alloc_ibdev; + } + arbel->ibdev[i] = ibdev; + ibdev->op = &arbel_ib_operations; + ibdev->dev = &pci->dev; + ibdev->port = ( ARBEL_PORT_BASE + i ); + ib_set_drvdata ( ibdev, arbel ); } - ibdev->op = &arbel_ib_operations; - pci_set_drvdata ( pci, ibdev ); - ibdev->dev = &pci->dev; - ibdev->port = PXE_IB_PORT; - arbel = ibdev->dev_priv; - memset ( arbel, 0, sizeof ( *arbel ) ); /* Fix up PCI device */ adjust_pci_device ( pci ); @@ -1902,16 +1909,21 @@ static int arbel_probe ( struct pci_device *pci, if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 ) goto err_setup_mpt; - /* Register Infiniband device */ - if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { - DBGC ( arbel, "Arbel %p could not register IB device: %s\n", - arbel, strerror ( rc ) ); - goto err_register_ibdev; + /* Register Infiniband devices */ + for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) { + if ( ( rc = register_ibdev ( arbel->ibdev[i] ) ) != 0 ) { + DBGC ( arbel, "Arbel %p could not register IB " + "device: %s\n", arbel, strerror ( rc ) ); + goto err_register_ibdev; + } } return 0; + i = ( ARBEL_NUM_PORTS - 1 ); err_register_ibdev: + for ( ; i >= 0 ; i-- ) + unregister_ibdev ( arbel->ibdev[i] ); err_setup_mpt: arbel_cmd_close_hca ( arbel ); err_init_hca: @@ -1924,8 +1936,12 @@ static int arbel_probe ( struct pci_device *pci, err_mailbox_out: free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); err_mailbox_in: - free_ibdev ( ibdev ); - err_ibdev: + i = ( ARBEL_NUM_PORTS - 1 ); + err_alloc_ibdev: + for ( ; i >= 0 ; i-- ) + free_ibdev ( arbel->ibdev[i] ); + free ( arbel ); + err_alloc_arbel: return rc; } @@ -1935,17 +1951,20 @@ static int arbel_probe ( struct pci_device *pci, * @v pci PCI device */ static void arbel_remove ( struct pci_device *pci ) { - struct ib_device *ibdev = pci_get_drvdata ( pci ); - struct arbel *arbel = ibdev->dev_priv; + struct arbel *arbel = pci_get_drvdata ( pci ); + int i; - unregister_ibdev ( ibdev ); + for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) + unregister_ibdev ( arbel->ibdev[i] ); arbel_cmd_close_hca ( arbel ); arbel_free_icm ( arbel ); arbel_stop_firmware ( arbel ); arbel_stop_firmware ( arbel ); free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE ); free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); - free_ibdev ( ibdev ); + for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) + free_ibdev ( arbel->ibdev[i] ); + free ( arbel ); } static struct pci_device_id arbel_nics[] = { diff --git a/src/drivers/infiniband/arbel.h b/src/drivers/infiniband/arbel.h index 4d7e4fc6..94fa67c1 100644 --- a/src/drivers/infiniband/arbel.h +++ b/src/drivers/infiniband/arbel.h @@ -17,6 +17,10 @@ * */ +/* Ports in existence */ +#define ARBEL_NUM_PORTS 1 +#define ARBEL_PORT_BASE 1 + /* PCI BARs */ #define ARBEL_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0 #define ARBEL_PCI_CONFIG_BAR_SIZE 0x100000 @@ -344,6 +348,9 @@ struct arbel { /** Device limits */ struct arbel_dev_limits limits; + + /** Infiniband devices */ + struct ib_device *ibdev[ARBEL_NUM_PORTS]; }; /** Global protection domain */ diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index ce1d0cf6..fecf3988 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -41,9 +41,6 @@ * */ -/* Port to use */ -#define PXE_IB_PORT 1 - /*************************************************************************** * * Queue number allocation @@ -599,7 +596,7 @@ static void hermon_free_mtt ( struct hermon *hermon, */ 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; @@ -665,7 +662,7 @@ static int hermon_create_cq ( struct ib_device *ibdev, 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: @@ -688,8 +685,8 @@ static int hermon_create_cq ( struct ib_device *ibdev, */ 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; @@ -713,7 +710,7 @@ static void hermon_destroy_cq ( struct ib_device *ibdev, 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 ); } /*************************************************************************** @@ -732,7 +729,7 @@ static void hermon_destroy_cq ( struct ib_device *ibdev, */ 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; @@ -845,7 +842,7 @@ static int hermon_create_qp ( struct ib_device *ibdev, 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: @@ -871,8 +868,8 @@ static int hermon_create_qp ( struct ib_device *ibdev, */ 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; @@ -896,7 +893,7 @@ static void hermon_destroy_qp ( struct ib_device *ibdev, hermon->cap.reserved_qps ); hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 ); - qp->dev_priv = NULL; + ib_qp_set_drvdata ( qp, NULL ); } /*************************************************************************** @@ -924,8 +921,8 @@ static int hermon_post_send ( struct ib_device *ibdev, 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; @@ -1000,8 +997,8 @@ static int hermon_post_send ( struct ib_device *ibdev, 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; @@ -1048,7 +1045,7 @@ static int hermon_complete ( struct ib_device *ibdev, 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; @@ -1085,7 +1082,7 @@ static int hermon_complete ( struct ib_device *ibdev, 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 ) & @@ -1128,8 +1125,8 @@ static void hermon_poll_cq ( struct ib_device *ibdev, 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; @@ -1177,7 +1174,7 @@ static void hermon_poll_cq ( struct ib_device *ibdev, * @ret rc Return status code */ static int hermon_open ( struct ib_device *ibdev ) { - struct hermon *hermon = ibdev->dev_priv; + struct hermon *hermon = ib_get_drvdata ( ibdev ); struct hermonprm_init_port init_port; int rc; @@ -1205,7 +1202,7 @@ static int hermon_open ( struct ib_device *ibdev ) { * @v ibdev Infiniband device */ static void hermon_close ( struct ib_device *ibdev ) { - struct hermon *hermon = ibdev->dev_priv; + struct hermon *hermon = ib_get_drvdata ( ibdev ); int rc; if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) { @@ -1233,7 +1230,7 @@ static void hermon_close ( struct ib_device *ibdev ) { 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; @@ -1287,7 +1284,7 @@ static int hermon_mcast_attach ( struct ib_device *ibdev, 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; @@ -1327,7 +1324,7 @@ static void hermon_mcast_detach ( struct ib_device *ibdev, */ static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) { - struct hermon *hermon = ibdev->dev_priv; + struct hermon *hermon = ib_get_drvdata ( ibdev ); union hermonprm_mad mad_ifc; int rc; @@ -1870,23 +1867,33 @@ static int hermon_setup_mpt ( struct hermon *hermon ) { */ 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; - ibdev->port = PXE_IB_PORT; - hermon = ibdev->dev_priv; - memset ( hermon, 0, sizeof ( *hermon ) ); /* Fix up PCI device */ adjust_pci_device ( pci ); @@ -1939,16 +1946,21 @@ static int hermon_probe ( struct pci_device *pci, if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 ) goto err_setup_mpt; - /* Register Infiniband device */ - if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { - DBGC ( hermon, "Hermon %p could not register IB device: %s\n", - hermon, strerror ( rc ) ); - goto err_register_ibdev; + /* 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; + 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: @@ -1961,8 +1973,12 @@ static int hermon_probe ( struct pci_device *pci, 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; } @@ -1972,17 +1988,20 @@ static int hermon_probe ( struct pci_device *pci, * @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; - unregister_ibdev ( ibdev ); + 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[] = { diff --git a/src/drivers/infiniband/hermon.h b/src/drivers/infiniband/hermon.h index 1aee4439..959e6a9d 100644 --- a/src/drivers/infiniband/hermon.h +++ b/src/drivers/infiniband/hermon.h @@ -17,6 +17,10 @@ * */ +/* Ports in existence */ +#define HERMON_NUM_PORTS 1 +#define HERMON_PORT_BASE 1 + /* PCI BARs */ #define HERMON_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0 #define HERMON_PCI_CONFIG_BAR_SIZE 0x100000 @@ -402,6 +406,9 @@ struct hermon { /** Device capabilities */ struct hermon_dev_cap cap; + + /** Infiniband devices */ + struct ib_device *ibdev[HERMON_NUM_PORTS]; }; /** Global protection domain */ diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 784c0720..905051bf 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -294,7 +294,7 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib, rc = -ENOMEM; goto err; } - qset->qp->owner_priv = ipoib->netdev; + ib_qp_set_ownerdata ( qset->qp, ipoib->netdev ); return 0; @@ -506,7 +506,7 @@ static void ipoib_data_complete_send ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct ib_completion *completion, struct io_buffer *iobuf ) { - struct net_device *netdev = qp->owner_priv; + struct net_device *netdev = ib_qp_get_ownerdata ( qp ); netdev_tx_complete_err ( netdev, iobuf, ( completion->syndrome ? -EIO : 0 ) ); @@ -524,7 +524,7 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct ib_completion *completion, struct io_buffer *iobuf ) { - struct net_device *netdev = qp->owner_priv; + struct net_device *netdev = ib_qp_get_ownerdata ( qp ); struct ipoib_device *ipoib = netdev->priv; struct ipoib_pseudo_hdr *ipoib_pshdr; @@ -572,7 +572,7 @@ static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct ib_completion *completion, struct io_buffer *iobuf ) { - struct net_device *netdev = qp->owner_priv; + struct net_device *netdev = ib_qp_get_ownerdata ( qp ); struct ipoib_device *ipoib = netdev->priv; if ( completion->syndrome ) { @@ -640,7 +640,7 @@ static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct ib_completion *completion, struct io_buffer *iobuf ) { - struct net_device *netdev = qp->owner_priv; + struct net_device *netdev = ib_qp_get_ownerdata ( qp ); struct ipoib_device *ipoib = netdev->priv; union ib_mad *mad; diff --git a/src/include/gpxe/infiniband.h b/src/include/gpxe/infiniband.h index ad64b2a3..354dc579 100644 --- a/src/include/gpxe/infiniband.h +++ b/src/include/gpxe/infiniband.h @@ -75,8 +75,8 @@ struct ib_work_queue { unsigned long next_idx; /** I/O buffers assigned to work queue */ struct io_buffer **iobufs; - /** Device private data */ - void *dev_priv; + /** Driver private data */ + void *drv_priv; }; /** An Infiniband Queue Pair */ @@ -89,8 +89,8 @@ struct ib_queue_pair { struct ib_work_queue send; /** Receive queue */ struct ib_work_queue recv; - /** Device private data */ - void *dev_priv; + /** Driver private data */ + void *drv_priv; /** Queue owner private data */ void *owner_priv; }; @@ -111,8 +111,8 @@ struct ib_completion_queue { unsigned long next_idx; /** List of work queues completing to this queue */ struct list_head work_queues; - /** Device private data */ - void *dev_priv; + /** Driver private data */ + void *drv_priv; }; /** An Infiniband completion */ @@ -297,8 +297,8 @@ struct ib_device { unsigned long sm_lid; /** Partition key */ unsigned int pkey; - /** Device private data */ - void *dev_priv; + /** Driver private data */ + void *drv_priv; /** Owner private data */ void *owner_priv; }; @@ -425,20 +425,130 @@ ib_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) { } /** - * Set Infiniband owner-private data + * Set Infiniband work queue driver-private data * - * @v pci Infiniband device + * @v wq Work queue * @v priv Private data */ static inline __attribute__ (( always_inline )) void -ib_set_ownerdata ( struct ib_device *ibdev, void *owner_priv ) { - ibdev->owner_priv = owner_priv; +ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) { + wq->drv_priv = priv; } /** - * Get Infiniband owner-private data + * Get Infiniband work queue driver-private data * - * @v pci Infiniband device + * @v wq Work queue + * @ret priv Private data + */ +static inline __attribute__ (( always_inline )) void * +ib_wq_get_drvdata ( struct ib_work_queue *wq ) { + return wq->drv_priv; +} + +/** + * Set Infiniband queue pair driver-private data + * + * @v qp Queue pair + * @v priv Private data + */ +static inline __attribute__ (( always_inline )) void +ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) { + qp->drv_priv = priv; +} + +/** + * Get Infiniband queue pair driver-private data + * + * @v qp Queue pair + * @ret priv Private data + */ +static inline __attribute__ (( always_inline )) void * +ib_qp_get_drvdata ( struct ib_queue_pair *qp ) { + return qp->drv_priv; +} + +/** + * Set Infiniband queue pair owner-private data + * + * @v qp Queue pair + * @v priv Private data + */ +static inline __attribute__ (( always_inline )) void +ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) { + qp->owner_priv = priv; +} + +/** + * Get Infiniband queue pair owner-private data + * + * @v qp Queue pair + * @ret priv Private data + */ +static inline __attribute__ (( always_inline )) void * +ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) { + return qp->owner_priv; +} + +/** + * Set Infiniband completion queue driver-private data + * + * @v cq Completion queue + * @v priv Private data + */ +static inline __attribute__ (( always_inline )) void +ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) { + cq->drv_priv = priv; +} + +/** + * Get Infiniband completion queue driver-private data + * + * @v cq Completion queue + * @ret priv Private data + */ +static inline __attribute__ (( always_inline )) void * +ib_cq_get_drvdata ( struct ib_completion_queue *cq ) { + return cq->drv_priv; +} + +/** + * Set Infiniband device driver-private data + * + * @v ibdev Infiniband device + * @v priv Private data + */ +static inline __attribute__ (( always_inline )) void +ib_set_drvdata ( struct ib_device *ibdev, void *priv ) { + ibdev->drv_priv = priv; +} + +/** + * Get Infiniband device driver-private data + * + * @v ibdev Infiniband device + * @ret priv Private data + */ +static inline __attribute__ (( always_inline )) void * +ib_get_drvdata ( struct ib_device *ibdev ) { + return ibdev->drv_priv; +} + +/** + * Set Infiniband device owner-private data + * + * @v ibdev Infiniband device + * @v priv Private data + */ +static inline __attribute__ (( always_inline )) void +ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) { + ibdev->owner_priv = priv; +} + +/** + * Get Infiniband device owner-private data + * + * @v ibdev Infiniband device * @ret priv Private data */ static inline __attribute__ (( always_inline )) void * diff --git a/src/net/infiniband.c b/src/net/infiniband.c index 2edadc99..39d11285 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -67,7 +67,8 @@ struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev, } DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) " - "with CQN %#lx\n", ibdev, num_cqes, cq, cq->dev_priv, cq->cqn ); + "with CQN %#lx\n", ibdev, num_cqes, cq, + ib_cq_get_drvdata ( cq ), cq->cqn ); return cq; } @@ -141,7 +142,7 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, } DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n", - ibdev, qp, qp->dev_priv, qp->qpn ); + ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn ); DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n", ibdev, qp->qpn, num_send_wqes, qp->send.iobufs, qp->recv.iobufs ); @@ -360,17 +361,19 @@ static int ib_get_mad_params ( struct ib_device *ibdev ) { /** * Allocate Infiniband device * - * @v priv_size Size of private data area + * @v priv_size Size of driver private data area * @ret ibdev Infiniband device, or NULL */ struct ib_device * alloc_ibdev ( size_t priv_size ) { struct ib_device *ibdev; + void *drv_priv; size_t total_len; total_len = ( sizeof ( *ibdev ) + priv_size ); ibdev = zalloc ( total_len ); if ( ibdev ) { - ibdev->dev_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) ); + drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) ); + ib_set_drvdata ( ibdev, drv_priv ); } return ibdev; }