Browse Source

[hermon] Allocate space for GRH on UD queue pairs

The Infiniband specification (volume 1, section 11.4.1.2 "Post Receive
Request") notes that for UD QPs, the GRH will be placed in the first
40 bytes of the receive buffer if present.  (If no GRH is present,
which is normal, then the first 40 bytes of the receive buffer will be
unused.)

Mellanox hardware performs this placement automatically: other headers
will be stripped (and their values returned via the CQE), but the
first 40 bytes of the data buffer will be consumed by the (probably
non-existent) GRH.

This does not fit neatly into iPXE's internal abstraction, which
expects the data buffer to represent just the data payload with the
addresses from the GRH (if present) passed as additional parameters to
ib_complete_recv().

The end result of this discrepancy is that attempts to receive
full-sized 2048-byte IPoIB packets on Mellanox hardware will fail.

Fix by allocating a separate ring buffer to hold the received GRHs.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
e84c917f39
2 changed files with 47 additions and 12 deletions
  1. 42
    11
      src/drivers/infiniband/hermon.c
  2. 5
    1
      src/drivers/infiniband/hermon.h

+ 42
- 11
src/drivers/infiniband/hermon.c View File

1111
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1111
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1112
 	struct hermon_queue_pair *hermon_qp;
1112
 	struct hermon_queue_pair *hermon_qp;
1113
 	struct hermonprm_qp_ee_state_transitions qpctx;
1113
 	struct hermonprm_qp_ee_state_transitions qpctx;
1114
+	struct hermonprm_wqe_segment_data_ptr *data;
1115
+	unsigned int i;
1114
 	int rc;
1116
 	int rc;
1115
 
1117
 
1116
 	/* Calculate queue pair number */
1118
 	/* Calculate queue pair number */
1147
 				     sizeof ( hermon_qp->send.wqe[0] ) );
1149
 				     sizeof ( hermon_qp->send.wqe[0] ) );
1148
 	hermon_qp->recv.wqe_size = ( qp->recv.num_wqes *
1150
 	hermon_qp->recv.wqe_size = ( qp->recv.num_wqes *
1149
 				     sizeof ( hermon_qp->recv.wqe[0] ) );
1151
 				     sizeof ( hermon_qp->recv.wqe[0] ) );
1152
+	if ( ( qp->type == IB_QPT_SMI ) || ( qp->type == IB_QPT_GSI ) ||
1153
+	     ( qp->type == IB_QPT_UD ) ) {
1154
+		hermon_qp->recv.grh_size = ( qp->recv.num_wqes *
1155
+					     sizeof ( hermon_qp->recv.grh[0] ));
1156
+	}
1150
 	hermon_qp->wqe_size = ( hermon_qp->send.wqe_size +
1157
 	hermon_qp->wqe_size = ( hermon_qp->send.wqe_size +
1151
-				hermon_qp->recv.wqe_size );
1158
+				hermon_qp->recv.wqe_size +
1159
+				hermon_qp->recv.grh_size );
1152
 	hermon_qp->wqe = malloc_dma ( hermon_qp->wqe_size,
1160
 	hermon_qp->wqe = malloc_dma ( hermon_qp->wqe_size,
1153
 				      sizeof ( hermon_qp->send.wqe[0] ) );
1161
 				      sizeof ( hermon_qp->send.wqe[0] ) );
1154
 	if ( ! hermon_qp->wqe ) {
1162
 	if ( ! hermon_qp->wqe ) {
1156
 		goto err_alloc_wqe;
1164
 		goto err_alloc_wqe;
1157
 	}
1165
 	}
1158
 	hermon_qp->send.wqe = hermon_qp->wqe;
1166
 	hermon_qp->send.wqe = hermon_qp->wqe;
1159
-	memset ( hermon_qp->send.wqe, 0xff, hermon_qp->send.wqe_size );
1160
 	hermon_qp->recv.wqe = ( hermon_qp->wqe + hermon_qp->send.wqe_size );
1167
 	hermon_qp->recv.wqe = ( hermon_qp->wqe + hermon_qp->send.wqe_size );
1168
+	if ( hermon_qp->recv.grh_size ) {
1169
+		hermon_qp->recv.grh = ( hermon_qp->wqe +
1170
+					hermon_qp->send.wqe_size +
1171
+					hermon_qp->recv.wqe_size );
1172
+	}
1173
+
1174
+	/* Initialise work queue entries */
1175
+	memset ( hermon_qp->send.wqe, 0xff, hermon_qp->send.wqe_size );
1161
 	memset ( hermon_qp->recv.wqe, 0, hermon_qp->recv.wqe_size );
1176
 	memset ( hermon_qp->recv.wqe, 0, hermon_qp->recv.wqe_size );
1177
+	data = &hermon_qp->recv.wqe[0].recv.data[0];
1178
+	for ( i = 0 ; i < ( hermon_qp->recv.wqe_size / sizeof ( *data ) ); i++){
1179
+		MLX_FILL_1 ( data, 1, l_key, HERMON_INVALID_LKEY );
1180
+		data++;
1181
+	}
1162
 
1182
 
1163
 	/* Allocate MTT entries */
1183
 	/* Allocate MTT entries */
1164
 	if ( ( rc = hermon_alloc_mtt ( hermon, hermon_qp->wqe,
1184
 	if ( ( rc = hermon_alloc_mtt ( hermon, hermon_qp->wqe,
1633
 	struct ib_work_queue *wq = &qp->recv;
1653
 	struct ib_work_queue *wq = &qp->recv;
1634
 	struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv;
1654
 	struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv;
1635
 	struct hermonprm_recv_wqe *wqe;
1655
 	struct hermonprm_recv_wqe *wqe;
1656
+	struct hermonprm_wqe_segment_data_ptr *data;
1657
+	struct ib_global_route_header *grh;
1636
 	unsigned int wqe_idx_mask;
1658
 	unsigned int wqe_idx_mask;
1637
 
1659
 
1638
 	/* Allocate work queue entry */
1660
 	/* Allocate work queue entry */
1646
 	wqe = &hermon_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv;
1668
 	wqe = &hermon_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv;
1647
 
1669
 
1648
 	/* Construct work queue entry */
1670
 	/* Construct work queue entry */
1649
-	MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
1650
-	MLX_FILL_1 ( &wqe->data[0], 1, l_key, hermon->lkey );
1651
-	MLX_FILL_H ( &wqe->data[0], 2,
1652
-		     local_address_h, virt_to_bus ( iobuf->data ) );
1653
-	MLX_FILL_1 ( &wqe->data[0], 3,
1654
-		     local_address_l, virt_to_bus ( iobuf->data ) );
1671
+	data = &wqe->data[0];
1672
+	if ( hermon_qp->recv.grh ) {
1673
+		grh = &hermon_qp->recv.grh[wq->next_idx & wqe_idx_mask];
1674
+		MLX_FILL_1 ( data, 0, byte_count, sizeof ( *grh ) );
1675
+		MLX_FILL_1 ( data, 1, l_key, hermon->lkey );
1676
+		MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( grh ) );
1677
+		MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( grh ) );
1678
+		data++;
1679
+	}
1680
+	MLX_FILL_1 ( data, 0, byte_count, iob_tailroom ( iobuf ) );
1681
+	MLX_FILL_1 ( data, 1, l_key, hermon->lkey );
1682
+	MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( iobuf->data ) );
1683
+	MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( iobuf->data ) );
1655
 
1684
 
1656
 	/* Update work queue's index */
1685
 	/* Update work queue's index */
1657
 	wq->next_idx++;
1686
 	wq->next_idx++;
1676
 			     struct ib_completion_queue *cq,
1705
 			     struct ib_completion_queue *cq,
1677
 			     union hermonprm_completion_entry *cqe ) {
1706
 			     union hermonprm_completion_entry *cqe ) {
1678
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1707
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1708
+	struct hermon_queue_pair *hermon_qp;
1679
 	struct ib_work_queue *wq;
1709
 	struct ib_work_queue *wq;
1680
 	struct ib_queue_pair *qp;
1710
 	struct ib_queue_pair *qp;
1681
 	struct io_buffer *iobuf;
1711
 	struct io_buffer *iobuf;
1713
 		return -EIO;
1743
 		return -EIO;
1714
 	}
1744
 	}
1715
 	qp = wq->qp;
1745
 	qp = wq->qp;
1746
+	hermon_qp = ib_qp_get_drvdata ( qp );
1716
 
1747
 
1717
 	/* Identify work queue entry */
1748
 	/* Identify work queue entry */
1718
 	wqe_idx = MLX_GET ( &cqe->normal, wqe_counter );
1749
 	wqe_idx = MLX_GET ( &cqe->normal, wqe_counter );
1747
 		case IB_QPT_SMI:
1778
 		case IB_QPT_SMI:
1748
 		case IB_QPT_GSI:
1779
 		case IB_QPT_GSI:
1749
 		case IB_QPT_UD:
1780
 		case IB_QPT_UD:
1750
-			assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
1751
-			grh = iobuf->data;
1752
-			iob_pull ( iobuf, sizeof ( *grh ) );
1781
+			/* Locate corresponding GRH */
1782
+			assert ( hermon_qp->recv.grh != NULL );
1783
+			grh = &hermon_qp->recv.grh[ wqe_idx & wqe_idx_mask ];
1753
 			/* Construct address vector */
1784
 			/* Construct address vector */
1754
 			source = &recv_source;
1785
 			source = &recv_source;
1755
 			source->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
1786
 			source->qpn = MLX_GET ( &cqe->normal, srq_rqpn );

+ 5
- 1
src/drivers/infiniband/hermon.h View File

515
 	struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
515
 	struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
516
 } __attribute__ (( packed ));
516
 } __attribute__ (( packed ));
517
 
517
 
518
-#define HERMON_MAX_SCATTER 1
518
+#define HERMON_MAX_SCATTER 2
519
 
519
 
520
 struct hermonprm_recv_wqe {
520
 struct hermonprm_recv_wqe {
521
 	struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_SCATTER];
521
 	struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_SCATTER];
686
 	union hermon_recv_wqe *wqe;
686
 	union hermon_recv_wqe *wqe;
687
 	/** Size of work queue */
687
 	/** Size of work queue */
688
 	size_t wqe_size;
688
 	size_t wqe_size;
689
+	/** GRH buffers (if applicable) */
690
+	struct ib_global_route_header *grh;
691
+	/** Size of GRH buffers */
692
+	size_t grh_size;
689
 	/** Doorbell record */
693
 	/** Doorbell record */
690
 	struct hermonprm_qp_db_record *doorbell;
694
 	struct hermonprm_qp_db_record *doorbell;
691
 };
695
 };

Loading…
Cancel
Save