diff options
| author | Michael Brown | 2007-09-17 09:36:56 +0200 |
|---|---|---|
| committer | Michael Brown | 2007-09-17 09:36:56 +0200 |
| commit | b3d3814c176a068980f8c178e74d36e524fa7572 (patch) | |
| tree | c878bf6fe43f5be1908f099c87d48000bc1925a9 /src/drivers/net/ipoib.c | |
| parent | Use pkey table access to determine broadcast GID directly. (diff) | |
| download | ipxe-b3d3814c176a068980f8c178e74d36e524fa7572.tar.gz ipxe-b3d3814c176a068980f8c178e74d36e524fa7572.tar.xz ipxe-b3d3814c176a068980f8c178e74d36e524fa7572.zip | |
Obtains a response to the get path record!
Diffstat (limited to 'src/drivers/net/ipoib.c')
| -rw-r--r-- | src/drivers/net/ipoib.c | 181 |
1 files changed, 172 insertions, 9 deletions
diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 2d351e4b..a848b711 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -44,15 +44,24 @@ extern struct ib_address_vector hack_ipoib_bcast_av; /** IPoIB MTU */ #define IPOIB_MTU 2048 -/** Number of IPoIB send work queue entries */ +/** Number of IPoIB data send work queue entries */ #define IPOIB_DATA_NUM_SEND_WQES 4 -/** Number of IPoIB receive work queue entries */ -#define IPOIB_DATA_NUM_RECV_WQES 8 +/** Number of IPoIB data receive work queue entries */ +#define IPOIB_DATA_NUM_RECV_WQES 4 -/** Number of IPoIB completion entries */ +/** Number of IPoIB data completion entries */ #define IPOIB_DATA_NUM_CQES 8 +/** Number of IPoIB metadata send work queue entries */ +#define IPOIB_META_NUM_SEND_WQES 4 + +/** Number of IPoIB metadata receive work queue entries */ +#define IPOIB_META_NUM_RECV_WQES 4 + +/** Number of IPoIB metadata completion entries */ +#define IPOIB_META_NUM_CQES 8 + /** An IPoIB queue set */ struct ipoib_queue_set { /** Completion queue */ @@ -84,10 +93,15 @@ struct ipoib_device { **************************************************************************** */ +/** Broadcast QPN used in IPoIB MAC addresses + * + * This is a guaranteed invalid real QPN + */ +#define IPOIB_BROADCAST_QPN 0xffffffffUL + /** Broadcast IPoIB address */ static struct ipoib_mac ipoib_broadcast = { - .gid = { { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff } }, + .qpn = ntohl ( IPOIB_BROADCAST_QPN ), }; /** @@ -245,6 +259,73 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib, } /** + * Transmit path record request + * + * @v ipoib IPoIB device + * @v gid Destination GID + * @ret rc Return status code + */ +static int ipoib_get_path_record ( struct ipoib_device *ipoib, + struct ib_gid *gid ) { + struct ib_device *ibdev = ipoib->ibdev; + struct io_buffer *iobuf; + struct ib_mad_path_record *path_record; + struct ib_address_vector av; + static uint32_t tid = 0; + int rc; + + DBG ( "get_path_record():\n" ); + int get_path_record(struct ib_gid *dgid, uint16_t *dlid_p, + uint8_t *sl_p, uint8_t *rate_p); + uint16_t tmp_dlid; + uint8_t tmp_sl; + uint8_t tmp_rate; + get_path_record ( gid, &tmp_dlid, &tmp_sl, &tmp_rate ); + + DBG ( "ipoib_get_path_record():\n" ); + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( sizeof ( *path_record ) ); + if ( ! iobuf ) + return -ENOMEM; + iob_put ( iobuf, sizeof ( *path_record ) ); + path_record = iobuf->data; + memset ( path_record, 0, sizeof ( *path_record ) ); + + /* Construct path record request */ + path_record->mad_hdr.base_version = IB_MGMT_BASE_VERSION; + path_record->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM; + path_record->mad_hdr.class_version = 2; + path_record->mad_hdr.method = IB_MGMT_METHOD_GET; + path_record->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC ); + path_record->mad_hdr.tid = tid++; + path_record->sa_hdr.comp_mask[1] = + htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID ); + memcpy ( &path_record->dgid, gid, sizeof ( path_record->dgid ) ); + memcpy ( &path_record->sgid, &ibdev->port_gid, + sizeof ( path_record->sgid ) ); + + DBG_HD ( path_record, sizeof ( *path_record ) ); + + /* Construct address vector */ + memset ( &av, 0, sizeof ( av ) ); + av.dlid = ibdev->sm_lid; + av.dest_qp = IB_SA_QPN; + av.qkey = IB_SA_QKEY; + + /* Post send request */ + if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av, + iobuf ) ) != 0 ) { + DBGC ( ipoib, "IPoIB %p could not send get path record: %s\n", + ipoib, strerror ( rc ) ); + free_iob ( iobuf ); + return rc; + } + + return 0; +} + +/** * Transmit packet via IPoIB network device * * @v netdev Network device @@ -256,19 +337,29 @@ static int ipoib_transmit ( struct net_device *netdev, struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; struct ipoib_pseudo_hdr *ipoib_pshdr = iobuf->data; + int rc; if ( iob_len ( iobuf ) < sizeof ( *ipoib_pshdr ) ) { DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib ); return -EINVAL; } + DBG ( "TX pseudo-header:\n" ); + DBG_HD ( ipoib_pshdr, sizeof ( *ipoib_pshdr ) ); + if ( ipoib_pshdr->peer.qpn != htonl ( IPOIB_BROADCAST_QPN ) ) { + DBG ( "Get path record\n" ); + rc = ipoib_get_path_record ( ipoib, &ipoib_pshdr->peer.gid ); + free_iob ( iobuf ); + return 0; + } + iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) ); return ib_post_send ( ibdev, ipoib->data.qp, &hack_ipoib_bcast_av, iobuf ); } /** - * Handle IPoIB send completion + * Handle IPoIB data send completion * * @v ibdev Infiniband device * @v qp Queue pair @@ -286,7 +377,7 @@ static void ipoib_data_complete_send ( struct ib_device *ibdev __unused, } /** - * Handle IPoIB receive completion + * Handle IPoIB data receive completion * * @v ibdev Infiniband device * @v qp Queue pair @@ -316,6 +407,61 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused, } /** + * Handle IPoIB metadata send completion + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v completion Completion + * @v iobuf I/O buffer + */ +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 ipoib_device *ipoib = netdev->priv; + + DBG ( "Woohoo! METADATA TX completion\n" ); + + + if ( completion->syndrome ) { + DBGC ( ipoib, "IPoIB %p metadata TX completion error %x\n", + ipoib, completion->syndrome ); + } + free_iob ( iobuf ); +} + +/** + * Handle IPoIB metadata receive completion + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v completion Completion + * @v iobuf I/O buffer + */ +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 ipoib_device *ipoib = netdev->priv; + + DBG ( "***************** META TX!!!!!! ********\n" ); + + if ( completion->syndrome ) { + DBGC ( ipoib, "IPoIB %p metadata RX completion error %x\n", + ipoib, completion->syndrome ); + } else { + iob_put ( iobuf, completion->len ); + DBG ( "Metadata RX:\n" ); + DBG_HD ( iobuf->data, iob_len ( iobuf ) ); + } + + ipoib->meta.recv_fill--; + free_iob ( iobuf ); +} + +/** * Refill IPoIB receive ring * * @v ipoib IPoIB device @@ -349,6 +495,9 @@ static void ipoib_poll ( struct net_device *netdev ) { ib_poll_cq ( ibdev, ipoib->data.cq, ipoib_data_complete_send, ipoib_data_complete_recv ); + ib_poll_cq ( ibdev, ipoib->meta.cq, ipoib_meta_complete_send, + ipoib_meta_complete_recv ); + ipoib_refill_recv ( ipoib, &ipoib->meta ); ipoib_refill_recv ( ipoib, &ipoib->data ); } @@ -382,7 +531,8 @@ static int ipoib_open ( struct net_device *netdev ) { return rc; } - /* Fill receive ring */ + /* Fill receive rings */ + ipoib_refill_recv ( ipoib, &ipoib->meta ); ipoib_refill_recv ( ipoib, &ipoib->data ); return 0; @@ -436,6 +586,17 @@ int ipoib_probe ( struct ib_device *ibdev ) { ipoib->netdev = netdev; ipoib->ibdev = ibdev; + /* Allocate metadata queue set */ + if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta, + IPOIB_META_NUM_CQES, + IPOIB_META_NUM_SEND_WQES, + IPOIB_META_NUM_RECV_WQES, + IB_SA_QKEY ) ) != 0 ) { + DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n", + ipoib, strerror ( rc ) ); + goto err_create_meta_qset; + } + /* Allocate data queue set */ if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data, IPOIB_DATA_NUM_CQES, @@ -461,6 +622,8 @@ int ipoib_probe ( struct ib_device *ibdev ) { err_register_netdev: ipoib_destroy_qset ( ipoib, &ipoib->data ); err_create_data_qset: + ipoib_destroy_qset ( ipoib, &ipoib->meta ); + err_create_meta_qset: netdev_nullify ( netdev ); netdev_put ( netdev ); return rc; |
