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
46 46
47#include <linux/mlx4/device.h>47#include <linux/mlx4/device.h>
48#include <linux/mlx4/doorbell.h>48#include <linux/mlx4/doorbell.h>
49#include <linux/mlx4/qp.h>
49 50
50#define MLX4_IB_DRV_NAME "mlx4_ib"51#define MLX4_IB_DRV_NAME "mlx4_ib"
51 52
@@ -299,6 +300,12 @@ struct mlx4_wqn_range { · 247 unmodified lines
299 struct list_head list;300 struct list_head list;
300};301};
301 302
303struct mlx4_ib_rss {
304 unsigned int base_qpn_tbl_sz;
305 u8 flags;
306 u8 rss_key[MLX4_EN_RSS_KEY_SIZE];
307};
308
302struct mlx4_ib_qp {309struct mlx4_ib_qp {
303 union {310 union {
304 struct ib_qp ibqp;311 struct ib_qp ibqp;
@@ -345,6 +352,7 @@ struct mlx4_ib_qp { · 40 unmodified lines
345 struct mlx4_wqn_range *wqn_range;352 struct mlx4_wqn_range *wqn_range;
346 /* Number of RSS QP parents that uses this WQ */353 /* Number of RSS QP parents that uses this WQ */
347 u32 rss_usecnt;354 u32 rss_usecnt;
355 struct mlx4_ib_rss *rss_ctx;
348};356};
349 357
350struct mlx4_ib_srq {358struct 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
53 struct mlx4_ib_cq *recv_cq);53 struct mlx4_ib_cq *recv_cq);
54static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq,54static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq,
55 struct mlx4_ib_cq *recv_cq);55 struct mlx4_ib_cq *recv_cq);
56static int _mlx4_ib_modify_wq(struct ib_wq *ibwq, enum ib_wq_state new_state);
56 57
57enum {58enum {
58 MLX4_IB_ACK_REQ_FREQ = 8,59 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
650 qp->counter_index = NULL;651 qp->counter_index = NULL;
651}652}
652 653
654static 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
729static 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
775err:
776 kfree(qp->rss_ctx);
777
778err_qp_alloc:
779 mlx4_qp_remove(dev->dev, &qp->mqp);
780 mlx4_qp_free(dev->dev, &qp->mqp);
781
782err_qpn:
783 mlx4_qp_release_range(dev->dev, qpn, 1);
784 return err;
785}
786
787static 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
653/*860/*
654 * This function allocates a WQN from a range which is consecutive and aligned861 * This function allocates a WQN from a range which is consecutive and aligned
655 * to its size. In case the range is full, then it creates a new range and862 * 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
1186 }1393 }
1187}1394}
1188 1395
1396static 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
1189static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,1426static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
1190 enum mlx4_ib_source_type src, int is_user)1427 enum mlx4_ib_source_type src, int is_user)
1191{1428{
@@ -1303,6 +1540,9 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd, · 111 unmodified lines
1303 int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;1540 int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
1304 u16 xrcdn = 0;1541 u16 xrcdn = 0;
1305 1542
1543 if (init_attr->rwq_ind_tbl)
1544 return _mlx4_ib_create_qp_rss(pd, init_attr, udata);
1545
1306 /*1546 /*
1307 * We only support LSO, vendor flag1, and multicast loopback blocking,1547 * We only support LSO, vendor flag1, and multicast loopback blocking,
1308 * and only for kernel UD QPs.1548 * and only for kernel UD QPs.
@@ -1444,7 +1684,6 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp) · 135 unmodified lines
1444{1684{
1445 struct mlx4_ib_dev *dev = to_mdev(qp->device);1685 struct mlx4_ib_dev *dev = to_mdev(qp->device);
1446 struct mlx4_ib_qp *mqp = to_mqp(qp);1686 struct mlx4_ib_qp *mqp = to_mqp(qp);
1447 struct mlx4_ib_pd *pd;
1448 1687
1449 if (is_qp0(dev, mqp))1688 if (is_qp0(dev, mqp))
1450 mlx4_CLOSE_PORT(dev->dev, mqp->port);1689 mlx4_CLOSE_PORT(dev->dev, mqp->port);
@@ -1459,8 +1698,14 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp) · 8 unmodified lines
1459 if (mqp->counter_index)1698 if (mqp->counter_index)
1460 mlx4_ib_free_qp_counter(dev, mqp);1699 mlx4_ib_free_qp_counter(dev, mqp);
1461 1700
1462 pd = get_pd(mqp);1701 if (qp->rwq_ind_tbl) {
1463 destroy_qp_common(dev, mqp, MLX4_IB_QP_SRC, !!pd->ibpd.uobject);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 }
1464 1709
1465 if (is_sqp(dev, mqp))1710 if (is_sqp(dev, mqp))
1466 kfree(to_msqp(mqp));1711 kfree(to_msqp(mqp));
@@ -1783,12 +2028,116 @@ static u8 gid_type_to_qpc(enum ib_gid_type gid_type) · 316 unmodified lines
1783 }2028 }
1784}2029}
1785 2030
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 */
2035static 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
2093static 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
2113static 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
1786static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type,2134static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type,
1787 const struct ib_qp_attr *attr, int attr_mask,2135 const struct ib_qp_attr *attr, int attr_mask,
1788 enum ib_qp_state cur_state, enum ib_qp_state new_state)2136 enum ib_qp_state cur_state, enum ib_qp_state new_state)
1789{2137{
1790 struct ib_uobject *ibuobject;2138 struct ib_uobject *ibuobject;
1791 struct ib_srq *ibsrq;2139 struct ib_srq *ibsrq;
2140 struct ib_rwq_ind_table *rwq_ind_tbl;
1792 enum ib_qp_type qp_type;2141 enum ib_qp_type qp_type;
1793 struct mlx4_ib_dev *dev;2142 struct mlx4_ib_dev *dev;
1794 struct mlx4_ib_qp *qp;2143 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
1804 if (src_type == MLX4_IB_RWQ_SRC) {2153 if (src_type == MLX4_IB_RWQ_SRC) {
1805 struct ib_wq *ibwq;2154 struct ib_wq *ibwq;
1806 2155
1807 ibwq = (struct ib_wq *)src;2156 ibwq = (struct ib_wq *)src;
1808 ibuobject = ibwq->uobject;2157 ibuobject = ibwq->uobject;
1809 ibsrq = NULL;2158 ibsrq = NULL;
1810 qp_type = IB_QPT_RAW_PACKET;2159 rwq_ind_tbl = NULL;
1811 qp = to_mqp((struct ib_qp *)ibwq);2160 qp_type = IB_QPT_RAW_PACKET;
1812 dev = to_mdev(ibwq->device);2161 qp = to_mqp((struct ib_qp *)ibwq);
1813 pd = to_mpd(ibwq->pd);2162 dev = to_mdev(ibwq->device);
2163 pd = to_mpd(ibwq->pd);
1814 } else {2164 } else {
1815 struct ib_qp *ibqp;2165 struct ib_qp *ibqp;
1816 2166
1817 ibqp = (struct ib_qp *)src;2167 ibqp = (struct ib_qp *)src;
1818 ibuobject = ibqp->uobject;2168 ibuobject = ibqp->uobject;
1819 ibsrq = ibqp->srq;2169 ibsrq = ibqp->srq;
1820 qp_type = ibqp->qp_type;2170 rwq_ind_tbl = ibqp->rwq_ind_tbl;
1821 qp = to_mqp(ibqp);2171 qp_type = ibqp->qp_type;
1822 dev = to_mdev(ibqp->device);2172 qp = to_mqp(ibqp);
1823 pd = get_pd(qp);2173 dev = to_mdev(ibqp->device);
2174 pd = get_pd(qp);
1824 }2175 }
1825 2176
1826 /* APM is not supported under RoCE */2177 /* 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
1836 context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |2187 context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |
1837 (to_mlx4_st(dev, qp->mlx4_ib_qp_type) << 16));2188 (to_mlx4_st(dev, qp->mlx4_ib_qp_type) << 16));
1838 2189
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
1839 if (!(attr_mask & IB_QP_PATH_MIG_STATE))2195 if (!(attr_mask & IB_QP_PATH_MIG_STATE))
1840 context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11);2196 context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11);
1841 else {2197 else {
@@ -1876,9 +2232,11 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type, · 34 unmodified lines
1876 ilog2(dev->dev->caps.max_msg_sz);2232 ilog2(dev->dev->caps.max_msg_sz);
1877 }2233 }
1878 2234
1879 if (qp->rq.wqe_cnt)2235 if (!rwq_ind_tbl) { /* PRM RSS receive side should be left zeros */
1880 context->rq_size_stride = ilog2(qp->rq.wqe_cnt) << 3;2236 if (qp->rq.wqe_cnt)
1881 context->rq_size_stride |= qp->rq.wqe_shift - 4;2237 context->rq_size_stride = ilog2(qp->rq.wqe_cnt) << 3;
2238 context->rq_size_stride |= qp->rq.wqe_shift - 4;
2239 }
1882 2240
1883 if (qp->sq.wqe_cnt)2241 if (qp->sq.wqe_cnt)
1884 context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;2242 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
2031 optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;2389 optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
2032 }2390 }
2033 2391
2034 get_cqs(qp, src_type, &send_cq, &recv_cq);2392 context->pd = cpu_to_be32(pd->pdn);
2035 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 }
2036 context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);2400 context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
2037 context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);2401 context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
2038 context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);2402 context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
@@ -2358,6 +2722,11 @@ out: · 319 unmodified lines
2358 return err;2722 return err;
2359}2723}
2360 2724
2725enum {
2726 MLX4_IB_MODIFY_QP_RSS_SUP_ATTR_MSK = (IB_QP_STATE |
2727 IB_QP_PORT),
2728};
2729
2361static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,2730static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
2362 int attr_mask, struct ib_udata *udata)2731 int attr_mask, struct ib_udata *udata)
2363{2732{
@@ -2388,6 +2757,27 @@ static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, · 24 unmodified lines
2388 goto out;2757 goto out;
2389 }2758 }
2390 2759
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
2391 if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT)) {2781 if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT)) {
2392 if ((cur_state == IB_QPS_RESET) && (new_state == IB_QPS_INIT)) {2782 if ((cur_state == IB_QPS_RESET) && (new_state == IB_QPS_INIT)) {
2393 if ((ibqp->qp_type == IB_QPT_RC) ||2783 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
2452 goto out;2842 goto out;
2453 }2843 }
2454 2844
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
2455 err = __mlx4_ib_modify_qp(ibqp, MLX4_IB_QP_SRC, attr, attr_mask,2851 err = __mlx4_ib_modify_qp(ibqp, MLX4_IB_QP_SRC, attr, attr_mask,
2456 cur_state, new_state);2852 cur_state, new_state);
2457 2853
2854 if (ibqp->rwq_ind_tbl && err)
2855 bring_down_rss_rwqs(ibqp->rwq_ind_tbl);
2856
2458 if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT))2857 if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT))
2459 attr->port_num = 1;2858 attr->port_num = 1;
2460 2859
@@ -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
3643 int mlx4_state;4042 int mlx4_state;
3644 int err = 0;4043 int err = 0;
3645 4044
4045 if (ibqp->rwq_ind_tbl)
4046 return -EOPNOTSUPP;
4047
3646 mutex_lock(&qp->mutex);4048 mutex_lock(&qp->mutex);
3647 4049
3648 if (qp->state == IB_QPS_RESET) {4050 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
3917 if ((new_state == IB_WQS_ERR) && (cur_state == IB_WQS_RESET))4319 if ((new_state == IB_WQS_ERR) && (cur_state == IB_WQS_RESET))
3918 return -EINVAL;4320 return -EINVAL;
3919 4321
4322 /* Need to protect against the parent RSS which also may modify WQ
4323 * state.
4324 */
4325 mutex_lock(&qp->mutex);
4326
3920 /* Can update HW state only if a RSS QP has already associated to this4327 /* Can update HW state only if a RSS QP has already associated to this
3921 * WQ, so we can apply its port on the WQ.4328 * WQ, so we can apply its port on the WQ.
3922 */4329 */
@@ -3926,6 +4333,8 @@ int mlx4_ib_modify_wq(struct ib_wq *ibwq, struct ib_wq_attr *wq_attr, · 3 unmodified lines
3926 if (!err)4333 if (!err)
3927 ibwq->state = new_state;4334 ibwq->state = new_state;
3928 4335
4336 mutex_unlock(&qp->mutex);
4337
3929 return err;4338 return err;
3930}4339}
3931 4340
include/uapi/rdma/mlx4-abi.h+33−0
@@ -95,6 +95,16 @@ struct mlx4_ib_create_srq_resp { · 94 unmodified lines
95 __u32 reserved;95 __u32 reserved;
96};96};
97 97
98struct 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
98struct mlx4_ib_create_qp {108struct mlx4_ib_create_qp {
99 __u64 buf_addr;109 __u64 buf_addr;
100 __u64 db_addr;110 __u64 db_addr;
@@ -123,4 +133,27 @@ struct mlx4_ib_create_rwq_ind_tbl_resp { · 22 unmodified lines
123 __u32 response_length;133 __u32 response_length;
124 __u32 reserved;134 __u32 reserved;
125};135};
136
137/* RX Hash function flags */
138enum 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 */
148enum 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
126#endif /* MLX4_ABI_USER_H */159#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