| @@ -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); |
| 54 | static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq, | 54 | static 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); |
| | 56 | static int _mlx4_ib_modify_wq(struct ib_wq *ibwq, enum ib_wq_state new_state); |
| 56 | | 57 | |
| 57 | enum { | 58 | enum { |
| 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 | |
| | 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 | |
| 653 | /* | 860 | /* |
| 654 | * This function allocates a WQN from a range which is consecutive and aligned | 861 | * 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 and | 862 | * 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 | |
| | 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 | |
| 1189 | static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, | 1426 | static 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 | */ |
| | 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 | |
| 1786 | static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type, | 2134 | static 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 | |
| | 2725 | enum { |
| | 2726 | MLX4_IB_MODIFY_QP_RSS_SUP_ATTR_MSK = (IB_QP_STATE | |
| | 2727 | IB_QP_PORT), |
| | 2728 | }; |
| | 2729 | |
| 2361 | static int _mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | 2730 | static 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 this | 4327 | /* 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 | |