History

IB/mlx4: Add support for RSS QP

Add support to work with a RSS QP by using an indirection table object upon QP creation. Other related QP verbs (e.g. modify/destroy/query) were updated as well for that QP mode. Notes: - The RX hash properties are supplied as driver private data. - The RSS QP port is used on the associated WQs in its indirection table. Applying different ports during WQ life time is not allowed. - The expected RSS QP flow is: create, modify(RST->INIT), modify(RST->RTR), destroy.

Guy Levi committed 9 years ago

Commit 3078f5f1 parent b8d46ca3 files · +472 −22Browse files

Unified · Split

3 files
  1. drivers/infiniband/hw/mlx4/mlx4_ib.h +8 −0
  2. drivers/infiniband/hw/mlx4/qp.c +431 −22
  3. include/uapi/rdma/mlx4-abi.h +33 −0
drivers/infiniband/hw/mlx4/mlx4_ib.h+8−0
@@ -46,6 +46,7 @@ · 45 unmodified lines
4646
4747 #include <linux/mlx4/device.h>
4848 #include <linux/mlx4/doorbell.h>
49+#include <linux/mlx4/qp.h>
4950
5051 #define MLX4_IB_DRV_NAME "mlx4_ib"
5152
@@ -299,6 +300,12 @@ struct mlx4_wqn_range { · 247 unmodified lines
299300 struct list_head list;
300301 };
301302
303+struct mlx4_ib_rss {
304+ unsigned int base_qpn_tbl_sz;
305+ u8 flags;
306+ u8 rss_key[MLX4_EN_RSS_KEY_SIZE];
307+};
308+
302309 struct mlx4_ib_qp {
303310 union {
304311 struct ib_qp ibqp;
@@ -345,6 +352,7 @@ struct mlx4_ib_qp { · 40 unmodified lines
345352 struct mlx4_wqn_range *wqn_range;
346353 /* Number of RSS QP parents that uses this WQ */
347354 u32 rss_usecnt;
355+ struct mlx4_ib_rss *rss_ctx;
348356 };
349357
350358 struct mlx4_ib_srq {
drivers/infiniband/hw/mlx4/qp.c+431−22
@@ -53,6 +53,7 @@ static void mlx4_ib_lock_cqs(struct mlx4_ib_cq *send_cq, · 52 unmodified lines
5353 struct mlx4_ib_cq *recv_cq);
5454 static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq,
5555 struct mlx4_ib_cq *recv_cq);
56+static int _mlx4_ib_modify_wq(struct ib_wq *ibwq, enum ib_wq_state new_state);
5657
5758 enum {
5859 MLX4_IB_ACK_REQ_FREQ = 8,
@@ -650,6 +651,212 @@ static void mlx4_ib_free_qp_counter(struct mlx4_ib_dev *dev, · 591 unmodified lines
650651 qp->counter_index = NULL;
651652 }
652653
654+static int set_qp_rss(struct mlx4_ib_dev *dev, struct mlx4_ib_rss *rss_ctx,
655+ struct ib_qp_init_attr *init_attr,
656+ struct mlx4_ib_create_qp_rss *ucmd)
657+{
658+ rss_ctx->base_qpn_tbl_sz = init_attr->rwq_ind_tbl->ind_tbl[0]->wq_num |
659+ (init_attr->rwq_ind_tbl->log_ind_tbl_size << 24);
660+
661+ if ((ucmd->rx_hash_function == MLX4_IB_RX_HASH_FUNC_TOEPLITZ) &&
662+ (dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP)) {
663+ memcpy(rss_ctx->rss_key, ucmd->rx_hash_key,
664+ MLX4_EN_RSS_KEY_SIZE);
665+ } else {
666+ pr_debug("RX Hash function is not supported\n");
667+ return (-EOPNOTSUPP);
668+ }
669+
670+ if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_IPV4) &&
671+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_IPV4)) {
672+ rss_ctx->flags = MLX4_RSS_IPV4;
673+ } else if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_IPV4) ||
674+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_IPV4)) {
675+ pr_debug("RX Hash fields_mask is not supported - both IPv4 SRC and DST must be set\n");
676+ return (-EOPNOTSUPP);
677+ }
678+
679+ if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_IPV6) &&
680+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_IPV6)) {
681+ rss_ctx->flags |= MLX4_RSS_IPV6;
682+ } else if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_IPV6) ||
683+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_IPV6)) {
684+ pr_debug("RX Hash fields_mask is not supported - both IPv6 SRC and DST must be set\n");
685+ return (-EOPNOTSUPP);
686+ }
687+
688+ if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_PORT_UDP) &&
689+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_PORT_UDP)) {
690+ if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
691+ pr_debug("RX Hash fields_mask for UDP is not supported\n");
692+ return (-EOPNOTSUPP);
693+ }
694+
695+ if (rss_ctx->flags & MLX4_RSS_IPV4) {
696+ rss_ctx->flags |= MLX4_RSS_UDP_IPV4;
697+ } else if (rss_ctx->flags & MLX4_RSS_IPV6) {
698+ rss_ctx->flags |= MLX4_RSS_UDP_IPV6;
699+ } else {
700+ pr_debug("RX Hash fields_mask is not supported - UDP must be set with IPv4 or IPv6\n");
701+ return (-EOPNOTSUPP);
702+ }
703+ } else if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_PORT_UDP) ||
704+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_PORT_UDP)) {
705+ pr_debug("RX Hash fields_mask is not supported - both UDP SRC and DST must be set\n");
706+ return (-EOPNOTSUPP);
707+ }
708+
709+ if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_PORT_TCP) &&
710+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_PORT_TCP)) {
711+ if (rss_ctx->flags & MLX4_RSS_IPV4) {
712+ rss_ctx->flags |= MLX4_RSS_TCP_IPV4;
713+ } else if (rss_ctx->flags & MLX4_RSS_IPV6) {
714+ rss_ctx->flags |= MLX4_RSS_TCP_IPV6;
715+ } else {
716+ pr_debug("RX Hash fields_mask is not supported - TCP must be set with IPv4 or IPv6\n");
717+ return (-EOPNOTSUPP);
718+ }
719+
720+ } else if ((ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_SRC_PORT_TCP) ||
721+ (ucmd->rx_hash_fields_mask & MLX4_IB_RX_HASH_DST_PORT_TCP)) {
722+ pr_debug("RX Hash fields_mask is not supported - both TCP SRC and DST must be set\n");
723+ return (-EOPNOTSUPP);
724+ }
725+
726+ return 0;
727+}
728+
729+static int create_qp_rss(struct mlx4_ib_dev *dev, struct ib_pd *ibpd,
730+ struct ib_qp_init_attr *init_attr,
731+ struct mlx4_ib_create_qp_rss *ucmd,
732+ struct mlx4_ib_qp *qp)
733+{
734+ int qpn;
735+ int err;
736+
737+ qp->mqp.usage = MLX4_RES_USAGE_USER_VERBS;
738+
739+ err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn, 0, qp->mqp.usage);
740+ if (err)
741+ return err;
742+
743+ err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp);
744+ if (err)
745+ goto err_qpn;
746+
747+ mutex_init(&qp->mutex);
748+
749+ INIT_LIST_HEAD(&qp->gid_list);
750+ INIT_LIST_HEAD(&qp->steering_rules);
751+
752+ qp->mlx4_ib_qp_type = MLX4_IB_QPT_RAW_ETHERTYPE;
753+ qp->state = IB_QPS_RESET;
754+
755+ /* Set dummy send resources to be compatible with HV and PRM */
756+ qp->sq_no_prefetch = 1;
757+ qp->sq.wqe_cnt = 1;
758+ qp->sq.wqe_shift = MLX4_IB_MIN_SQ_STRIDE;
759+ qp->buf_size = qp->sq.wqe_cnt << MLX4_IB_MIN_SQ_STRIDE;
760+ qp->mtt = (to_mqp(
761+ (struct ib_qp *)init_attr->rwq_ind_tbl->ind_tbl[0]))->mtt;
762+
763+ qp->rss_ctx = kzalloc(sizeof(*qp->rss_ctx), GFP_KERNEL);
764+ if (!qp->rss_ctx) {
765+ err = -ENOMEM;
766+ goto err_qp_alloc;
767+ }
768+
769+ err = set_qp_rss(dev, qp->rss_ctx, init_attr, ucmd);
770+ if (err)
771+ goto err;
772+
773+ return 0;
774+
775+err:
776+ kfree(qp->rss_ctx);
777+
778+err_qp_alloc:
779+ mlx4_qp_remove(dev->dev, &qp->mqp);
780+ mlx4_qp_free(dev->dev, &qp->mqp);
781+
782+err_qpn:
783+ mlx4_qp_release_range(dev->dev, qpn, 1);
784+ return err;
785+}
786+
787+static struct ib_qp *_mlx4_ib_create_qp_rss(struct ib_pd *pd,
788+ struct ib_qp_init_attr *init_attr,
789+ struct ib_udata *udata)
790+{
791+ struct mlx4_ib_qp *qp;
792+ struct mlx4_ib_create_qp_rss ucmd = {};
793+ size_t required_cmd_sz;
794+ int err;
795+
796+ if (!udata) {
797+ pr_debug("RSS QP with NULL udata\n");
798+ return ERR_PTR(-EINVAL);
799+ }
800+
801+ if (udata->outlen)
802+ return ERR_PTR(-EOPNOTSUPP);
803+
804+ required_cmd_sz = offsetof(typeof(ucmd), reserved1) +
805+ sizeof(ucmd.reserved1);
806+ if (udata->inlen < required_cmd_sz) {
807+ pr_debug("invalid inlen\n");
808+ return ERR_PTR(-EINVAL);
809+ }
810+
811+ if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
812+ pr_debug("copy failed\n");
813+ return ERR_PTR(-EFAULT);
814+ }
815+
816+ if (ucmd.comp_mask || ucmd.reserved1)
817+ return ERR_PTR(-EOPNOTSUPP);
818+
819+ if (udata->inlen > sizeof(ucmd) &&
820+ !ib_is_udata_cleared(udata, sizeof(ucmd),
821+ udata->inlen - sizeof(ucmd))) {
822+ pr_debug("inlen is not supported\n");
823+ return ERR_PTR(-EOPNOTSUPP);
824+ }
825+
826+ if (init_attr->qp_type != IB_QPT_RAW_PACKET) {
827+ pr_debug("RSS QP with unsupported QP type %d\n",
828+ init_attr->qp_type);
829+ return ERR_PTR(-EOPNOTSUPP);
830+ }
831+
832+ if (init_attr->create_flags) {
833+ pr_debug("RSS QP doesn't support create flags\n");
834+ return ERR_PTR(-EOPNOTSUPP);
835+ }
836+
837+ if (init_attr->send_cq || init_attr->cap.max_send_wr) {
838+ pr_debug("RSS QP with unsupported send attributes\n");
839+ return ERR_PTR(-EOPNOTSUPP);
840+ }
841+
842+ qp = kzalloc(sizeof(*qp), GFP_KERNEL);
843+ if (!qp)
844+ return ERR_PTR(-ENOMEM);
845+
846+ qp->pri.vid = 0xFFFF;
847+ qp->alt.vid = 0xFFFF;
848+
849+ err = create_qp_rss(to_mdev(pd->device), pd, init_attr, &ucmd, qp);
850+ if (err) {
851+ kfree(qp);
852+ return ERR_PTR(err);
853+ }
854+
855+ qp->ibqp.qp_num = qp->mqp.qpn;
856+
857+ return &qp->ibqp;
858+}
859+
653860 /*
654861 * This function allocates a WQN from a range which is consecutive and aligned
655862 * to its size. In case the range is full, then it creates a new range and
@@ -1186,6 +1393,36 @@ static void get_cqs(struct mlx4_ib_qp *qp, enum mlx4_ib_source_type src, · 530 unmodified lines
11861393 }
11871394 }
11881395
1396+static void destroy_qp_rss(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
1397+{
1398+ if (qp->state != IB_QPS_RESET) {
1399+ int i;
1400+
1401+ for (i = 0; i < (1 << qp->ibqp.rwq_ind_tbl->log_ind_tbl_size);
1402+ i++) {
1403+ struct ib_wq *ibwq = qp->ibqp.rwq_ind_tbl->ind_tbl[i];
1404+ struct mlx4_ib_qp *wq = to_mqp((struct ib_qp *)ibwq);
1405+
1406+ mutex_lock(&wq->mutex);
1407+
1408+ wq->rss_usecnt--;
1409+
1410+ mutex_unlock(&wq->mutex);
1411+ }
1412+
1413+ if (mlx4_qp_modify(dev->dev, NULL, to_mlx4_state(qp->state),
1414+ MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp))
1415+ pr_warn("modify QP %06x to RESET failed.\n",
1416+ qp->mqp.qpn);
1417+ }
1418+
1419+ mlx4_qp_remove(dev->dev, &qp->mqp);
1420+ mlx4_qp_free(dev->dev, &qp->mqp);
1421+ mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
1422+ del_gid_entries(qp);
1423+ kfree(qp->rss_ctx);
1424+}
1425+
11891426 static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
11901427 enum mlx4_ib_source_type src, int is_user)
11911428 {
@@ -1303,6 +1540,9 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd, · 111 unmodified lines
13031540 int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
13041541 u16 xrcdn = 0;
13051542
1543+ if (init_attr->rwq_ind_tbl)
1544+ return _mlx4_ib_create_qp_rss(pd, init_attr, udata);
1545+
13061546 /*
13071547 * We only support LSO, vendor flag1, and multicast loopback blocking,
13081548 * and only for kernel UD QPs.
@@ -1444,7 +1684,6 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp) · 135 unmodified lines
14441684 {
14451685 struct mlx4_ib_dev *dev = to_mdev(qp->device);
14461686 struct mlx4_ib_qp *mqp = to_mqp(qp);
1447− struct mlx4_ib_pd *pd;
14481687
14491688 if (is_qp0(dev, mqp))
14501689 mlx4_CLOSE_PORT(dev->dev, mqp->port);
@@ -1459,8 +1698,14 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp) · 8 unmodified lines
14591698 if (mqp->counter_index)
14601699 mlx4_ib_free_qp_counter(dev, mqp);
14611700
1462− pd = get_pd(mqp);
1463− destroy_qp_common(dev, mqp, MLX4_IB_QP_SRC, !!pd->ibpd.uobject);
1701+ if (qp->rwq_ind_tbl) {
1702+ destroy_qp_rss(dev, mqp);
1703+ } else {
1704+ struct mlx4_ib_pd *pd;
1705+
1706+ pd = get_pd(mqp);
1707+ destroy_qp_common(dev, mqp, MLX4_IB_QP_SRC, !!pd->ibpd.uobject);
1708+ }
14641709
14651710 if (is_sqp(dev, mqp))
14661711 kfree(to_msqp(mqp));
@@ -1783,12 +2028,116 @@ static u8 gid_type_to_qpc(enum ib_gid_type gid_type) · 316 unmodified lines
17832028 }
17842029 }
17852030
2031+/*
2032+ * Go over all RSS QP's childes (WQs) and apply their HW state according to
2033+ * their logic state if the RSS QP is the first RSS QP associated for the WQ.
2034+ */
2035+static int bringup_rss_rwqs(struct ib_rwq_ind_table *ind_tbl, u8 port_num)
2036+{
2037+ int i;
2038+ int err;
2039+
2040+ for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) {
2041+ struct ib_wq *ibwq = ind_tbl->ind_tbl[i];
2042+ struct mlx4_ib_qp *wq = to_mqp((struct ib_qp *)ibwq);
2043+
2044+ mutex_lock(&wq->mutex);
2045+
2046+ /* Mlx4_ib restrictions:
2047+ * WQ's is associated to a port according to the RSS QP it is
2048+ * associates to.
2049+ * In case the WQ is associated to a different port by another
2050+ * RSS QP, return a failure.
2051+ */
2052+ if ((wq->rss_usecnt > 0) && (wq->port != port_num)) {
2053+ err = -EINVAL;
2054+ mutex_unlock(&wq->mutex);
2055+ break;
2056+ }
2057+ wq->port = port_num;
2058+ if ((wq->rss_usecnt == 0) && (ibwq->state == IB_WQS_RDY)) {
2059+ err = _mlx4_ib_modify_wq(ibwq, IB_WQS_RDY);
2060+ if (err) {
2061+ mutex_unlock(&wq->mutex);
2062+ break;
2063+ }
2064+ }
2065+ wq->rss_usecnt++;
2066+
2067+ mutex_unlock(&wq->mutex);
2068+ }
2069+
2070+ if (i && err) {
2071+ int j;
2072+
2073+ for (j = (i - 1); j >= 0; j--) {
2074+ struct ib_wq *ibwq = ind_tbl->ind_tbl[j];
2075+ struct mlx4_ib_qp *wq = to_mqp((struct ib_qp *)ibwq);
2076+
2077+ mutex_lock(&wq->mutex);
2078+
2079+ if ((wq->rss_usecnt == 1) &&
2080+ (ibwq->state == IB_WQS_RDY))
2081+ if (_mlx4_ib_modify_wq(ibwq, IB_WQS_RESET))
2082+ pr_warn("failed to reverse WQN=0x%06x\n",
2083+ ibwq->wq_num);
2084+ wq->rss_usecnt--;
2085+
2086+ mutex_unlock(&wq->mutex);
2087+ }
2088+ }
2089+
2090+ return err;
2091+}
2092+
2093+static void bring_down_rss_rwqs(struct ib_rwq_ind_table *ind_tbl)
2094+{
2095+ int i;
2096+
2097+ for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) {
2098+ struct ib_wq *ibwq = ind_tbl->ind_tbl[i];
2099+ struct mlx4_ib_qp *wq = to_mqp((struct ib_qp *)ibwq);
2100+
2101+ mutex_lock(&wq->mutex);
2102+
2103+ if ((wq->rss_usecnt == 1) && (ibwq->state == IB_WQS_RDY))
2104+ if (_mlx4_ib_modify_wq(ibwq, IB_WQS_RESET))
2105+ pr_warn("failed to reverse WQN=%x\n",
2106+ ibwq->wq_num);
2107+ wq->rss_usecnt--;
2108+
2109+ mutex_unlock(&wq->mutex);
2110+ }
2111+}
2112+
2113+static void fill_qp_rss_context(struct mlx4_qp_context *context,
2114+ struct mlx4_ib_qp *qp)
2115+{
2116+ struct mlx4_rss_context *rss_context;
2117+
2118+ rss_context = (void *)context + offsetof(struct mlx4_qp_context,
2119+ pri_path) + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
2120+
2121+ rss_context->base_qpn = cpu_to_be32(qp->rss_ctx->base_qpn_tbl_sz);
2122+ rss_context->default_qpn =
2123+ cpu_to_be32(qp->rss_ctx->base_qpn_tbl_sz & 0xffffff);
2124+ if (qp->rss_ctx->flags & (MLX4_RSS_UDP_IPV4 | MLX4_RSS_UDP_IPV6))
2125+ rss_context->base_qpn_udp = rss_context->default_qpn;
2126+ rss_context->flags = qp->rss_ctx->flags;
2127+ /* Currently support just toeplitz */
2128+ rss_context->hash_fn = MLX4_RSS_HASH_TOP;
2129+
2130+ memcpy(rss_context->rss_key, qp->rss_ctx->rss_key,
2131+ MLX4_EN_RSS_KEY_SIZE);
2132+}
2133+
17862134 static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type,
17872135 const struct ib_qp_attr *attr, int attr_mask,
17882136 enum ib_qp_state cur_state, enum ib_qp_state new_state)
17892137 {
17902138 struct ib_uobject *ibuobject;
17912139 struct ib_srq *ibsrq;
2140+ struct ib_rwq_ind_table *rwq_ind_tbl;
17922141 enum ib_qp_type qp_type;
17932142 struct mlx4_ib_dev *dev;
17942143 struct mlx4_ib_qp *qp;
@@ -1804,23 +2153,25 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type, · 9 unmodified lines
18042153 if (src_type == MLX4_IB_RWQ_SRC) {
18052154 struct ib_wq *ibwq;
18062155
1807− ibwq = (struct ib_wq *)src;
1808− ibuobject = ibwq->uobject;
1809− ibsrq = NULL;
1810− qp_type = IB_QPT_RAW_PACKET;
1811− qp = to_mqp((struct ib_qp *)ibwq);
1812− dev = to_mdev(ibwq->device);
1813− pd = to_mpd(ibwq->pd);
2156+ ibwq = (struct ib_wq *)src;
2157+ ibuobject = ibwq->uobject;
2158+ ibsrq = NULL;
2159+ rwq_ind_tbl = NULL;
2160+ qp_type = IB_QPT_RAW_PACKET;
2161+ qp = to_mqp((struct ib_qp *)ibwq);
2162+ dev = to_mdev(ibwq->device);
2163+ pd = to_mpd(ibwq->pd);
18142164 } else {
18152165 struct ib_qp *ibqp;
18162166
1817− ibqp = (struct ib_qp *)src;
1818− ibuobject = ibqp->uobject;
1819− ibsrq = ibqp->srq;
1820− qp_type = ibqp->qp_type;
1821− qp = to_mqp(ibqp);
1822− dev = to_mdev(ibqp->device);
1823− pd = get_pd(qp);
2167+ ibqp = (struct ib_qp *)src;
2168+ ibuobject = ibqp->uobject;
2169+ ibsrq = ibqp->srq;
2170+ rwq_ind_tbl = ibqp->rwq_ind_tbl;
2171+ qp_type = ibqp->qp_type;
2172+ qp = to_mqp(ibqp);
2173+ dev = to_mdev(ibqp->device);
2174+ pd = get_pd(qp);
18242175 }
18252176
18262177 /* APM is not supported under RoCE */
@@ -1836,6 +2187,11 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type, · 9 unmodified lines
18362187 context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |
18372188 (to_mlx4_st(dev, qp->mlx4_ib_qp_type) << 16));
18382189
2190+ if (rwq_ind_tbl) {
2191+ fill_qp_rss_context(context, qp);
2192+ context->flags |= cpu_to_be32(1 << MLX4_RSS_QPC_FLAG_OFFSET);
2193+ }
2194+
18392195 if (!(attr_mask & IB_QP_PATH_MIG_STATE))
18402196 context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11);
18412197 else {
@@ -1876,9 +2232,11 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type, · 34 unmodified lines
18762232 ilog2(dev->dev->caps.max_msg_sz);
18772233 }
18782234
1879− if (qp->rq.wqe_cnt)
1880− context->rq_size_stride = ilog2(qp->rq.wqe_cnt) << 3;
1881− context->rq_size_stride |= qp->rq.wqe_shift - 4;
2235+ if (!rwq_ind_tbl) { /* PRM RSS receive side should be left zeros */
2236+ if (qp->rq.wqe_cnt)
2237+ context->rq_size_stride = ilog2(qp->rq.wqe_cnt) << 3;
2238+ context->rq_size_stride |= qp->rq.wqe_shift - 4;
2239+ }
18822240
18832241 if (qp->sq.wqe_cnt)
18842242 context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
@@ -2031,8 +2389,14 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type, · 146 unmodified lines
20312389 optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
20322390 }
20332391
2034− get_cqs(qp, src_type, &send_cq, &recv_cq);
2035− context->pd = cpu_to_be32(pd->pdn);
2392+ context->pd = cpu_to_be32(pd->pdn);
2393+
2394+ if (!rwq_ind_tbl) {
2395+ get_cqs(qp, src_type, &send_cq, &recv_cq);
2396+ } else { /* Set dummy CQs to be compatible with HV and PRM */
2397+ send_cq = to_mcq(rwq_ind_tbl->ind_tbl[0]->cq);
2398+ recv_cq = send_cq;
2399+ }
20362400 context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
20372401 context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
20382402 context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
@@ -2358,6 +2722,11 @@ out: · 319 unmodified lines
23582722 return err;
23592723 }
23602724
2725+enum {
2726+ MLX4_IB_MODIFY_QP_RSS_SUP_ATTR_MSK = (IB_QP_STATE |
2727+ IB_QP_PORT),
2728+};
2729+
23612730 static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
23622731 int attr_mask, struct ib_udata *udata)
23632732 {
@@ -2388,6 +2757,27 @@ static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, · 24 unmodified lines
23882757 goto out;
23892758 }
23902759
2760+ if (ibqp->rwq_ind_tbl) {
2761+ if (!(((cur_state == IB_QPS_RESET) &&
2762+ (new_state == IB_QPS_INIT)) ||
2763+ ((cur_state == IB_QPS_INIT) &&
2764+ (new_state == IB_QPS_RTR)))) {
2765+ pr_debug("qpn 0x%x: RSS QP unsupported transition %d to %d\n",
2766+ ibqp->qp_num, cur_state, new_state);
2767+
2768+ err = -EOPNOTSUPP;
2769+ goto out;
2770+ }
2771+
2772+ if (attr_mask & ~MLX4_IB_MODIFY_QP_RSS_SUP_ATTR_MSK) {
2773+ pr_debug("qpn 0x%x: RSS QP unsupported attribute mask 0x%x for transition %d to %d\n",
2774+ ibqp->qp_num, attr_mask, cur_state, new_state);
2775+
2776+ err = -EOPNOTSUPP;
2777+ goto out;
2778+ }
2779+ }
2780+
23912781 if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT)) {
23922782 if ((cur_state == IB_QPS_RESET) && (new_state == IB_QPS_INIT)) {
23932783 if ((ibqp->qp_type == IB_QPT_RC) ||
@@ -2452,9 +2842,18 @@ static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, · 58 unmodified lines
24522842 goto out;
24532843 }
24542844
2845+ if (ibqp->rwq_ind_tbl && (new_state == IB_QPS_INIT)) {
2846+ err = bringup_rss_rwqs(ibqp->rwq_ind_tbl, attr->port_num);
2847+ if (err)
2848+ goto out;
2849+ }
2850+
24552851 err = __mlx4_ib_modify_qp(ibqp, MLX4_IB_QP_SRC, attr, attr_mask,
24562852 cur_state, new_state);
24572853
2854+ if (ibqp->rwq_ind_tbl && err)
2855+ bring_down_rss_rwqs(ibqp->rwq_ind_tbl);
2856+
24582857 if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT))
24592858 attr->port_num = 1;
24602859
@@ -3643,6 +4042,9 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr · 1182 unmodified lines
36434042 int mlx4_state;
36444043 int err = 0;
36454044
4045+ if (ibqp->rwq_ind_tbl)
4046+ return -EOPNOTSUPP;
4047+
36464048 mutex_lock(&qp->mutex);
36474049
36484050 if (qp->state == IB_QPS_RESET) {
@@ -3917,6 +4319,11 @@ int mlx4_ib_modify_wq(struct ib_wq *ibwq, struct ib_wq_attr *wq_attr, · 268 unmodified lines
39174319 if ((new_state == IB_WQS_ERR) && (cur_state == IB_WQS_RESET))
39184320 return -EINVAL;
39194321
4322+ /* Need to protect against the parent RSS which also may modify WQ
4323+ * state.
4324+ */
4325+ mutex_lock(&qp->mutex);
4326+
39204327 /* Can update HW state only if a RSS QP has already associated to this
39214328 * WQ, so we can apply its port on the WQ.
39224329 */
@@ -3926,6 +4333,8 @@ int mlx4_ib_modify_wq(struct ib_wq *ibwq, struct ib_wq_attr *wq_attr, · 3 unmodified lines
39264333 if (!err)
39274334 ibwq->state = new_state;
39284335
4336+ mutex_unlock(&qp->mutex);
4337+
39294338 return err;
39304339 }
39314340
include/uapi/rdma/mlx4-abi.h+33−0
@@ -95,6 +95,16 @@ struct mlx4_ib_create_srq_resp { · 94 unmodified lines
9595 __u32 reserved;
9696 };
9797
98+struct mlx4_ib_create_qp_rss {
99+ __u64 rx_hash_fields_mask;
100+ __u8 rx_hash_function;
101+ __u8 rx_key_len;
102+ __u8 reserved[6];
103+ __u8 rx_hash_key[40];
104+ __u32 comp_mask;
105+ __u32 reserved1;
106+};
107+
98108 struct mlx4_ib_create_qp {
99109 __u64 buf_addr;
100110 __u64 db_addr;
@@ -123,4 +133,27 @@ struct mlx4_ib_create_rwq_ind_tbl_resp { · 22 unmodified lines
123133 __u32 response_length;
124134 __u32 reserved;
125135 };
136+
137+/* RX Hash function flags */
138+enum mlx4_ib_rx_hash_function_flags {
139+ MLX4_IB_RX_HASH_FUNC_TOEPLITZ = 1 << 0,
140+};
141+
142+/*
143+ * RX Hash flags, these flags allows to set which incoming packet's field should
144+ * participates in RX Hash. Each flag represent certain packet's field,
145+ * when the flag is set the field that is represented by the flag will
146+ * participate in RX Hash calculation.
147+ */
148+enum mlx4_ib_rx_hash_fields {
149+ MLX4_IB_RX_HASH_SRC_IPV4 = 1 << 0,
150+ MLX4_IB_RX_HASH_DST_IPV4 = 1 << 1,
151+ MLX4_IB_RX_HASH_SRC_IPV6 = 1 << 2,
152+ MLX4_IB_RX_HASH_DST_IPV6 = 1 << 3,
153+ MLX4_IB_RX_HASH_SRC_PORT_TCP = 1 << 4,
154+ MLX4_IB_RX_HASH_DST_PORT_TCP = 1 << 5,
155+ MLX4_IB_RX_HASH_SRC_PORT_UDP = 1 << 6,
156+ MLX4_IB_RX_HASH_DST_PORT_UDP = 1 << 7
157+};
158+
126159 #endif /* MLX4_ABI_USER_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t