diff options
Diffstat (limited to 'drivers/infiniband/hw/mlx4')
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 273 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 12 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 53 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/sysfs.c | 8 |
4 files changed, 324 insertions, 22 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index bf218d9ec089..c2702f549f10 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #define DRV_RELDATE "April 4, 2008" | 57 | #define DRV_RELDATE "April 4, 2008" |
58 | 58 | ||
59 | #define MLX4_IB_FLOW_MAX_PRIO 0xFFF | 59 | #define MLX4_IB_FLOW_MAX_PRIO 0xFFF |
60 | #define MLX4_IB_FLOW_QPN_MASK 0xFFFFFF | ||
60 | 61 | ||
61 | MODULE_AUTHOR("Roland Dreier"); | 62 | MODULE_AUTHOR("Roland Dreier"); |
62 | MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); | 63 | MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); |
@@ -94,21 +95,27 @@ static union ib_gid zgid; | |||
94 | 95 | ||
95 | static int check_flow_steering_support(struct mlx4_dev *dev) | 96 | static int check_flow_steering_support(struct mlx4_dev *dev) |
96 | { | 97 | { |
98 | int eth_num_ports = 0; | ||
97 | int ib_num_ports = 0; | 99 | int ib_num_ports = 0; |
98 | int i; | ||
99 | |||
100 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | ||
101 | ib_num_ports++; | ||
102 | 100 | ||
103 | if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { | 101 | int dmfs = dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED; |
104 | if (ib_num_ports || mlx4_is_mfunc(dev)) { | 102 | |
105 | pr_warn("Device managed flow steering is unavailable " | 103 | if (dmfs) { |
106 | "for IB ports or in multifunction env.\n"); | 104 | int i; |
107 | return 0; | 105 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) |
106 | eth_num_ports++; | ||
107 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | ||
108 | ib_num_ports++; | ||
109 | dmfs &= (!ib_num_ports || | ||
110 | (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DMFS_IPOIB)) && | ||
111 | (!eth_num_ports || | ||
112 | (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FS_EN)); | ||
113 | if (ib_num_ports && mlx4_is_mfunc(dev)) { | ||
114 | pr_warn("Device managed flow steering is unavailable for IB port in multifunction env.\n"); | ||
115 | dmfs = 0; | ||
108 | } | 116 | } |
109 | return 1; | ||
110 | } | 117 | } |
111 | return 0; | 118 | return dmfs; |
112 | } | 119 | } |
113 | 120 | ||
114 | static int mlx4_ib_query_device(struct ib_device *ibdev, | 121 | static int mlx4_ib_query_device(struct ib_device *ibdev, |
@@ -167,7 +174,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, | |||
167 | props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B; | 174 | props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B; |
168 | else | 175 | else |
169 | props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2A; | 176 | props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2A; |
170 | if (check_flow_steering_support(dev->dev)) | 177 | if (dev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) |
171 | props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING; | 178 | props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING; |
172 | } | 179 | } |
173 | 180 | ||
@@ -816,6 +823,7 @@ struct mlx4_ib_steering { | |||
816 | }; | 823 | }; |
817 | 824 | ||
818 | static int parse_flow_attr(struct mlx4_dev *dev, | 825 | static int parse_flow_attr(struct mlx4_dev *dev, |
826 | u32 qp_num, | ||
819 | union ib_flow_spec *ib_spec, | 827 | union ib_flow_spec *ib_spec, |
820 | struct _rule_hw *mlx4_spec) | 828 | struct _rule_hw *mlx4_spec) |
821 | { | 829 | { |
@@ -831,6 +839,14 @@ static int parse_flow_attr(struct mlx4_dev *dev, | |||
831 | mlx4_spec->eth.vlan_tag = ib_spec->eth.val.vlan_tag; | 839 | mlx4_spec->eth.vlan_tag = ib_spec->eth.val.vlan_tag; |
832 | mlx4_spec->eth.vlan_tag_msk = ib_spec->eth.mask.vlan_tag; | 840 | mlx4_spec->eth.vlan_tag_msk = ib_spec->eth.mask.vlan_tag; |
833 | break; | 841 | break; |
842 | case IB_FLOW_SPEC_IB: | ||
843 | type = MLX4_NET_TRANS_RULE_ID_IB; | ||
844 | mlx4_spec->ib.l3_qpn = | ||
845 | cpu_to_be32(qp_num); | ||
846 | mlx4_spec->ib.qpn_mask = | ||
847 | cpu_to_be32(MLX4_IB_FLOW_QPN_MASK); | ||
848 | break; | ||
849 | |||
834 | 850 | ||
835 | case IB_FLOW_SPEC_IPV4: | 851 | case IB_FLOW_SPEC_IPV4: |
836 | type = MLX4_NET_TRANS_RULE_ID_IPV4; | 852 | type = MLX4_NET_TRANS_RULE_ID_IPV4; |
@@ -862,6 +878,115 @@ static int parse_flow_attr(struct mlx4_dev *dev, | |||
862 | return mlx4_hw_rule_sz(dev, type); | 878 | return mlx4_hw_rule_sz(dev, type); |
863 | } | 879 | } |
864 | 880 | ||
881 | struct default_rules { | ||
882 | __u32 mandatory_fields[IB_FLOW_SPEC_SUPPORT_LAYERS]; | ||
883 | __u32 mandatory_not_fields[IB_FLOW_SPEC_SUPPORT_LAYERS]; | ||
884 | __u32 rules_create_list[IB_FLOW_SPEC_SUPPORT_LAYERS]; | ||
885 | __u8 link_layer; | ||
886 | }; | ||
887 | static const struct default_rules default_table[] = { | ||
888 | { | ||
889 | .mandatory_fields = {IB_FLOW_SPEC_IPV4}, | ||
890 | .mandatory_not_fields = {IB_FLOW_SPEC_ETH}, | ||
891 | .rules_create_list = {IB_FLOW_SPEC_IB}, | ||
892 | .link_layer = IB_LINK_LAYER_INFINIBAND | ||
893 | } | ||
894 | }; | ||
895 | |||
896 | static int __mlx4_ib_default_rules_match(struct ib_qp *qp, | ||
897 | struct ib_flow_attr *flow_attr) | ||
898 | { | ||
899 | int i, j, k; | ||
900 | void *ib_flow; | ||
901 | const struct default_rules *pdefault_rules = default_table; | ||
902 | u8 link_layer = rdma_port_get_link_layer(qp->device, flow_attr->port); | ||
903 | |||
904 | for (i = 0; i < sizeof(default_table)/sizeof(default_table[0]); i++, | ||
905 | pdefault_rules++) { | ||
906 | __u32 field_types[IB_FLOW_SPEC_SUPPORT_LAYERS]; | ||
907 | memset(&field_types, 0, sizeof(field_types)); | ||
908 | |||
909 | if (link_layer != pdefault_rules->link_layer) | ||
910 | continue; | ||
911 | |||
912 | ib_flow = flow_attr + 1; | ||
913 | /* we assume the specs are sorted */ | ||
914 | for (j = 0, k = 0; k < IB_FLOW_SPEC_SUPPORT_LAYERS && | ||
915 | j < flow_attr->num_of_specs; k++) { | ||
916 | union ib_flow_spec *current_flow = | ||
917 | (union ib_flow_spec *)ib_flow; | ||
918 | |||
919 | /* same layer but different type */ | ||
920 | if (((current_flow->type & IB_FLOW_SPEC_LAYER_MASK) == | ||
921 | (pdefault_rules->mandatory_fields[k] & | ||
922 | IB_FLOW_SPEC_LAYER_MASK)) && | ||
923 | (current_flow->type != | ||
924 | pdefault_rules->mandatory_fields[k])) | ||
925 | goto out; | ||
926 | |||
927 | /* same layer, try match next one */ | ||
928 | if (current_flow->type == | ||
929 | pdefault_rules->mandatory_fields[k]) { | ||
930 | j++; | ||
931 | ib_flow += | ||
932 | ((union ib_flow_spec *)ib_flow)->size; | ||
933 | } | ||
934 | } | ||
935 | |||
936 | ib_flow = flow_attr + 1; | ||
937 | for (j = 0; j < flow_attr->num_of_specs; | ||
938 | j++, ib_flow += ((union ib_flow_spec *)ib_flow)->size) | ||
939 | for (k = 0; k < IB_FLOW_SPEC_SUPPORT_LAYERS; k++) | ||
940 | /* same layer and same type */ | ||
941 | if (((union ib_flow_spec *)ib_flow)->type == | ||
942 | pdefault_rules->mandatory_not_fields[k]) | ||
943 | goto out; | ||
944 | |||
945 | return i; | ||
946 | } | ||
947 | out: | ||
948 | return -1; | ||
949 | } | ||
950 | |||
951 | static int __mlx4_ib_create_default_rules( | ||
952 | struct mlx4_ib_dev *mdev, | ||
953 | struct ib_qp *qp, | ||
954 | const struct default_rules *pdefault_rules, | ||
955 | struct _rule_hw *mlx4_spec) { | ||
956 | int size = 0; | ||
957 | int i; | ||
958 | |||
959 | for (i = 0; i < sizeof(pdefault_rules->rules_create_list)/ | ||
960 | sizeof(pdefault_rules->rules_create_list[0]); i++) { | ||
961 | int ret; | ||
962 | union ib_flow_spec ib_spec; | ||
963 | switch (pdefault_rules->rules_create_list[i]) { | ||
964 | case 0: | ||
965 | /* no rule */ | ||
966 | continue; | ||
967 | case IB_FLOW_SPEC_IB: | ||
968 | ib_spec.type = IB_FLOW_SPEC_IB; | ||
969 | ib_spec.size = sizeof(struct ib_flow_spec_ib); | ||
970 | |||
971 | break; | ||
972 | default: | ||
973 | /* invalid rule */ | ||
974 | return -EINVAL; | ||
975 | } | ||
976 | /* We must put empty rule, qpn is being ignored */ | ||
977 | ret = parse_flow_attr(mdev->dev, 0, &ib_spec, | ||
978 | mlx4_spec); | ||
979 | if (ret < 0) { | ||
980 | pr_info("invalid parsing\n"); | ||
981 | return -EINVAL; | ||
982 | } | ||
983 | |||
984 | mlx4_spec = (void *)mlx4_spec + ret; | ||
985 | size += ret; | ||
986 | } | ||
987 | return size; | ||
988 | } | ||
989 | |||
865 | static int __mlx4_ib_create_flow(struct ib_qp *qp, struct ib_flow_attr *flow_attr, | 990 | static int __mlx4_ib_create_flow(struct ib_qp *qp, struct ib_flow_attr *flow_attr, |
866 | int domain, | 991 | int domain, |
867 | enum mlx4_net_trans_promisc_mode flow_type, | 992 | enum mlx4_net_trans_promisc_mode flow_type, |
@@ -873,6 +998,7 @@ static int __mlx4_ib_create_flow(struct ib_qp *qp, struct ib_flow_attr *flow_att | |||
873 | struct mlx4_ib_dev *mdev = to_mdev(qp->device); | 998 | struct mlx4_ib_dev *mdev = to_mdev(qp->device); |
874 | struct mlx4_cmd_mailbox *mailbox; | 999 | struct mlx4_cmd_mailbox *mailbox; |
875 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | 1000 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; |
1001 | int default_flow; | ||
876 | 1002 | ||
877 | static const u16 __mlx4_domain[] = { | 1003 | static const u16 __mlx4_domain[] = { |
878 | [IB_FLOW_DOMAIN_USER] = MLX4_DOMAIN_UVERBS, | 1004 | [IB_FLOW_DOMAIN_USER] = MLX4_DOMAIN_UVERBS, |
@@ -907,8 +1033,21 @@ static int __mlx4_ib_create_flow(struct ib_qp *qp, struct ib_flow_attr *flow_att | |||
907 | 1033 | ||
908 | ib_flow = flow_attr + 1; | 1034 | ib_flow = flow_attr + 1; |
909 | size += sizeof(struct mlx4_net_trans_rule_hw_ctrl); | 1035 | size += sizeof(struct mlx4_net_trans_rule_hw_ctrl); |
1036 | /* Add default flows */ | ||
1037 | default_flow = __mlx4_ib_default_rules_match(qp, flow_attr); | ||
1038 | if (default_flow >= 0) { | ||
1039 | ret = __mlx4_ib_create_default_rules( | ||
1040 | mdev, qp, default_table + default_flow, | ||
1041 | mailbox->buf + size); | ||
1042 | if (ret < 0) { | ||
1043 | mlx4_free_cmd_mailbox(mdev->dev, mailbox); | ||
1044 | return -EINVAL; | ||
1045 | } | ||
1046 | size += ret; | ||
1047 | } | ||
910 | for (i = 0; i < flow_attr->num_of_specs; i++) { | 1048 | for (i = 0; i < flow_attr->num_of_specs; i++) { |
911 | ret = parse_flow_attr(mdev->dev, ib_flow, mailbox->buf + size); | 1049 | ret = parse_flow_attr(mdev->dev, qp->qp_num, ib_flow, |
1050 | mailbox->buf + size); | ||
912 | if (ret < 0) { | 1051 | if (ret < 0) { |
913 | mlx4_free_cmd_mailbox(mdev->dev, mailbox); | 1052 | mlx4_free_cmd_mailbox(mdev->dev, mailbox); |
914 | return -EINVAL; | 1053 | return -EINVAL; |
@@ -1820,6 +1959,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
1820 | } | 1959 | } |
1821 | 1960 | ||
1822 | if (check_flow_steering_support(dev)) { | 1961 | if (check_flow_steering_support(dev)) { |
1962 | ibdev->steering_support = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
1823 | ibdev->ib_dev.create_flow = mlx4_ib_create_flow; | 1963 | ibdev->ib_dev.create_flow = mlx4_ib_create_flow; |
1824 | ibdev->ib_dev.destroy_flow = mlx4_ib_destroy_flow; | 1964 | ibdev->ib_dev.destroy_flow = mlx4_ib_destroy_flow; |
1825 | 1965 | ||
@@ -1848,8 +1988,35 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
1848 | spin_lock_init(&ibdev->sm_lock); | 1988 | spin_lock_init(&ibdev->sm_lock); |
1849 | mutex_init(&ibdev->cap_mask_mutex); | 1989 | mutex_init(&ibdev->cap_mask_mutex); |
1850 | 1990 | ||
1991 | if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
1992 | ibdev->steer_qpn_count = MLX4_IB_UC_MAX_NUM_QPS; | ||
1993 | err = mlx4_qp_reserve_range(dev, ibdev->steer_qpn_count, | ||
1994 | MLX4_IB_UC_STEER_QPN_ALIGN, | ||
1995 | &ibdev->steer_qpn_base); | ||
1996 | if (err) | ||
1997 | goto err_counter; | ||
1998 | |||
1999 | ibdev->ib_uc_qpns_bitmap = | ||
2000 | kmalloc(BITS_TO_LONGS(ibdev->steer_qpn_count) * | ||
2001 | sizeof(long), | ||
2002 | GFP_KERNEL); | ||
2003 | if (!ibdev->ib_uc_qpns_bitmap) { | ||
2004 | dev_err(&dev->pdev->dev, "bit map alloc failed\n"); | ||
2005 | goto err_steer_qp_release; | ||
2006 | } | ||
2007 | |||
2008 | bitmap_zero(ibdev->ib_uc_qpns_bitmap, ibdev->steer_qpn_count); | ||
2009 | |||
2010 | err = mlx4_FLOW_STEERING_IB_UC_QP_RANGE( | ||
2011 | dev, ibdev->steer_qpn_base, | ||
2012 | ibdev->steer_qpn_base + | ||
2013 | ibdev->steer_qpn_count - 1); | ||
2014 | if (err) | ||
2015 | goto err_steer_free_bitmap; | ||
2016 | } | ||
2017 | |||
1851 | if (ib_register_device(&ibdev->ib_dev, NULL)) | 2018 | if (ib_register_device(&ibdev->ib_dev, NULL)) |
1852 | goto err_counter; | 2019 | goto err_steer_free_bitmap; |
1853 | 2020 | ||
1854 | if (mlx4_ib_mad_init(ibdev)) | 2021 | if (mlx4_ib_mad_init(ibdev)) |
1855 | goto err_reg; | 2022 | goto err_reg; |
@@ -1938,6 +2105,13 @@ err_mad: | |||
1938 | err_reg: | 2105 | err_reg: |
1939 | ib_unregister_device(&ibdev->ib_dev); | 2106 | ib_unregister_device(&ibdev->ib_dev); |
1940 | 2107 | ||
2108 | err_steer_free_bitmap: | ||
2109 | kfree(ibdev->ib_uc_qpns_bitmap); | ||
2110 | |||
2111 | err_steer_qp_release: | ||
2112 | if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
2113 | mlx4_qp_release_range(dev, ibdev->steer_qpn_base, | ||
2114 | ibdev->steer_qpn_count); | ||
1941 | err_counter: | 2115 | err_counter: |
1942 | for (; i; --i) | 2116 | for (; i; --i) |
1943 | if (ibdev->counters[i - 1] != -1) | 2117 | if (ibdev->counters[i - 1] != -1) |
@@ -1958,6 +2132,69 @@ err_dealloc: | |||
1958 | return NULL; | 2132 | return NULL; |
1959 | } | 2133 | } |
1960 | 2134 | ||
2135 | int mlx4_ib_steer_qp_alloc(struct mlx4_ib_dev *dev, int count, int *qpn) | ||
2136 | { | ||
2137 | int offset; | ||
2138 | |||
2139 | WARN_ON(!dev->ib_uc_qpns_bitmap); | ||
2140 | |||
2141 | offset = bitmap_find_free_region(dev->ib_uc_qpns_bitmap, | ||
2142 | dev->steer_qpn_count, | ||
2143 | get_count_order(count)); | ||
2144 | if (offset < 0) | ||
2145 | return offset; | ||
2146 | |||
2147 | *qpn = dev->steer_qpn_base + offset; | ||
2148 | return 0; | ||
2149 | } | ||
2150 | |||
2151 | void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count) | ||
2152 | { | ||
2153 | if (!qpn || | ||
2154 | dev->steering_support != MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
2155 | return; | ||
2156 | |||
2157 | BUG_ON(qpn < dev->steer_qpn_base); | ||
2158 | |||
2159 | bitmap_release_region(dev->ib_uc_qpns_bitmap, | ||
2160 | qpn - dev->steer_qpn_base, | ||
2161 | get_count_order(count)); | ||
2162 | } | ||
2163 | |||
2164 | int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, | ||
2165 | int is_attach) | ||
2166 | { | ||
2167 | int err; | ||
2168 | size_t flow_size; | ||
2169 | struct ib_flow_attr *flow = NULL; | ||
2170 | struct ib_flow_spec_ib *ib_spec; | ||
2171 | |||
2172 | if (is_attach) { | ||
2173 | flow_size = sizeof(struct ib_flow_attr) + | ||
2174 | sizeof(struct ib_flow_spec_ib); | ||
2175 | flow = kzalloc(flow_size, GFP_KERNEL); | ||
2176 | if (!flow) | ||
2177 | return -ENOMEM; | ||
2178 | flow->port = mqp->port; | ||
2179 | flow->num_of_specs = 1; | ||
2180 | flow->size = flow_size; | ||
2181 | ib_spec = (struct ib_flow_spec_ib *)(flow + 1); | ||
2182 | ib_spec->type = IB_FLOW_SPEC_IB; | ||
2183 | ib_spec->size = sizeof(struct ib_flow_spec_ib); | ||
2184 | /* Add an empty rule for IB L2 */ | ||
2185 | memset(&ib_spec->mask, 0, sizeof(ib_spec->mask)); | ||
2186 | |||
2187 | err = __mlx4_ib_create_flow(&mqp->ibqp, flow, | ||
2188 | IB_FLOW_DOMAIN_NIC, | ||
2189 | MLX4_FS_REGULAR, | ||
2190 | &mqp->reg_id); | ||
2191 | } else { | ||
2192 | err = __mlx4_ib_destroy_flow(mdev->dev, mqp->reg_id); | ||
2193 | } | ||
2194 | kfree(flow); | ||
2195 | return err; | ||
2196 | } | ||
2197 | |||
1961 | static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) | 2198 | static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) |
1962 | { | 2199 | { |
1963 | struct mlx4_ib_dev *ibdev = ibdev_ptr; | 2200 | struct mlx4_ib_dev *ibdev = ibdev_ptr; |
@@ -1971,6 +2208,13 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) | |||
1971 | pr_warn("failure unregistering notifier\n"); | 2208 | pr_warn("failure unregistering notifier\n"); |
1972 | ibdev->iboe.nb.notifier_call = NULL; | 2209 | ibdev->iboe.nb.notifier_call = NULL; |
1973 | } | 2210 | } |
2211 | |||
2212 | if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
2213 | mlx4_qp_release_range(dev, ibdev->steer_qpn_base, | ||
2214 | ibdev->steer_qpn_count); | ||
2215 | kfree(ibdev->ib_uc_qpns_bitmap); | ||
2216 | } | ||
2217 | |||
1974 | if (ibdev->iboe.nb_inet.notifier_call) { | 2218 | if (ibdev->iboe.nb_inet.notifier_call) { |
1975 | if (unregister_inetaddr_notifier(&ibdev->iboe.nb_inet)) | 2219 | if (unregister_inetaddr_notifier(&ibdev->iboe.nb_inet)) |
1976 | pr_warn("failure unregistering notifier\n"); | 2220 | pr_warn("failure unregistering notifier\n"); |
@@ -1983,6 +2227,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) | |||
1983 | ibdev->iboe.nb_inet6.notifier_call = NULL; | 2227 | ibdev->iboe.nb_inet6.notifier_call = NULL; |
1984 | } | 2228 | } |
1985 | #endif | 2229 | #endif |
2230 | |||
1986 | iounmap(ibdev->uar_map); | 2231 | iounmap(ibdev->uar_map); |
1987 | for (p = 0; p < ibdev->num_ports; ++p) | 2232 | for (p = 0; p < ibdev->num_ports; ++p) |
1988 | if (ibdev->counters[p] != -1) | 2233 | if (ibdev->counters[p] != -1) |
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index c06f571619df..a230683af940 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -68,6 +68,8 @@ enum { | |||
68 | /*module param to indicate if SM assigns the alias_GUID*/ | 68 | /*module param to indicate if SM assigns the alias_GUID*/ |
69 | extern int mlx4_ib_sm_guid_assign; | 69 | extern int mlx4_ib_sm_guid_assign; |
70 | 70 | ||
71 | #define MLX4_IB_UC_STEER_QPN_ALIGN 1 | ||
72 | #define MLX4_IB_UC_MAX_NUM_QPS 256 | ||
71 | struct mlx4_ib_ucontext { | 73 | struct mlx4_ib_ucontext { |
72 | struct ib_ucontext ibucontext; | 74 | struct ib_ucontext ibucontext; |
73 | struct mlx4_uar uar; | 75 | struct mlx4_uar uar; |
@@ -153,6 +155,7 @@ struct mlx4_ib_wq { | |||
153 | enum mlx4_ib_qp_flags { | 155 | enum mlx4_ib_qp_flags { |
154 | MLX4_IB_QP_LSO = IB_QP_CREATE_IPOIB_UD_LSO, | 156 | MLX4_IB_QP_LSO = IB_QP_CREATE_IPOIB_UD_LSO, |
155 | MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK = IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK, | 157 | MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK = IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK, |
158 | MLX4_IB_QP_NETIF = IB_QP_CREATE_NETIF_QP, | ||
156 | MLX4_IB_SRIOV_TUNNEL_QP = 1 << 30, | 159 | MLX4_IB_SRIOV_TUNNEL_QP = 1 << 30, |
157 | MLX4_IB_SRIOV_SQP = 1 << 31, | 160 | MLX4_IB_SRIOV_SQP = 1 << 31, |
158 | }; | 161 | }; |
@@ -270,6 +273,7 @@ struct mlx4_ib_qp { | |||
270 | struct list_head gid_list; | 273 | struct list_head gid_list; |
271 | struct list_head steering_rules; | 274 | struct list_head steering_rules; |
272 | struct mlx4_ib_buf *sqp_proxy_rcv; | 275 | struct mlx4_ib_buf *sqp_proxy_rcv; |
276 | u64 reg_id; | ||
273 | 277 | ||
274 | }; | 278 | }; |
275 | 279 | ||
@@ -497,6 +501,10 @@ struct mlx4_ib_dev { | |||
497 | struct kobject *dev_ports_parent[MLX4_MFUNC_MAX]; | 501 | struct kobject *dev_ports_parent[MLX4_MFUNC_MAX]; |
498 | struct mlx4_ib_iov_port iov_ports[MLX4_MAX_PORTS]; | 502 | struct mlx4_ib_iov_port iov_ports[MLX4_MAX_PORTS]; |
499 | struct pkey_mgt pkeys; | 503 | struct pkey_mgt pkeys; |
504 | unsigned long *ib_uc_qpns_bitmap; | ||
505 | int steer_qpn_count; | ||
506 | int steer_qpn_base; | ||
507 | int steering_support; | ||
500 | }; | 508 | }; |
501 | 509 | ||
502 | struct ib_event_work { | 510 | struct ib_event_work { |
@@ -752,5 +760,9 @@ void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device); | |||
752 | 760 | ||
753 | __be64 mlx4_ib_gen_node_guid(void); | 761 | __be64 mlx4_ib_gen_node_guid(void); |
754 | 762 | ||
763 | int mlx4_ib_steer_qp_alloc(struct mlx4_ib_dev *dev, int count, int *qpn); | ||
764 | void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count); | ||
765 | int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, | ||
766 | int is_attach); | ||
755 | 767 | ||
756 | #endif /* MLX4_IB_H */ | 768 | #endif /* MLX4_IB_H */ |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index e0c2186529ff..d8f4d1fe8494 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -731,6 +731,14 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, | |||
731 | if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) | 731 | if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) |
732 | qp->flags |= MLX4_IB_QP_LSO; | 732 | qp->flags |= MLX4_IB_QP_LSO; |
733 | 733 | ||
734 | if (init_attr->create_flags & IB_QP_CREATE_NETIF_QP) { | ||
735 | if (dev->steering_support == | ||
736 | MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
737 | qp->flags |= MLX4_IB_QP_NETIF; | ||
738 | else | ||
739 | goto err; | ||
740 | } | ||
741 | |||
734 | err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp); | 742 | err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp); |
735 | if (err) | 743 | if (err) |
736 | goto err; | 744 | goto err; |
@@ -780,7 +788,11 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, | |||
780 | if (init_attr->qp_type == IB_QPT_RAW_PACKET) | 788 | if (init_attr->qp_type == IB_QPT_RAW_PACKET) |
781 | err = mlx4_qp_reserve_range(dev->dev, 1, 1 << 8, &qpn); | 789 | err = mlx4_qp_reserve_range(dev->dev, 1, 1 << 8, &qpn); |
782 | else | 790 | else |
783 | err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn); | 791 | if (qp->flags & MLX4_IB_QP_NETIF) |
792 | err = mlx4_ib_steer_qp_alloc(dev, 1, &qpn); | ||
793 | else | ||
794 | err = mlx4_qp_reserve_range(dev->dev, 1, 1, | ||
795 | &qpn); | ||
784 | if (err) | 796 | if (err) |
785 | goto err_proxy; | 797 | goto err_proxy; |
786 | } | 798 | } |
@@ -805,8 +817,12 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, | |||
805 | return 0; | 817 | return 0; |
806 | 818 | ||
807 | err_qpn: | 819 | err_qpn: |
808 | if (!sqpn) | 820 | if (!sqpn) { |
809 | mlx4_qp_release_range(dev->dev, qpn, 1); | 821 | if (qp->flags & MLX4_IB_QP_NETIF) |
822 | mlx4_ib_steer_qp_free(dev, qpn, 1); | ||
823 | else | ||
824 | mlx4_qp_release_range(dev->dev, qpn, 1); | ||
825 | } | ||
810 | err_proxy: | 826 | err_proxy: |
811 | if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI) | 827 | if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI) |
812 | free_proxy_bufs(pd->device, qp); | 828 | free_proxy_bufs(pd->device, qp); |
@@ -947,8 +963,12 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, | |||
947 | 963 | ||
948 | mlx4_qp_free(dev->dev, &qp->mqp); | 964 | mlx4_qp_free(dev->dev, &qp->mqp); |
949 | 965 | ||
950 | if (!is_sqp(dev, qp) && !is_tunnel_qp(dev, qp)) | 966 | if (!is_sqp(dev, qp) && !is_tunnel_qp(dev, qp)) { |
951 | mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1); | 967 | if (qp->flags & MLX4_IB_QP_NETIF) |
968 | mlx4_ib_steer_qp_free(dev, qp->mqp.qpn, 1); | ||
969 | else | ||
970 | mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1); | ||
971 | } | ||
952 | 972 | ||
953 | mlx4_mtt_cleanup(dev->dev, &qp->mtt); | 973 | mlx4_mtt_cleanup(dev->dev, &qp->mtt); |
954 | 974 | ||
@@ -1002,9 +1022,16 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, | |||
1002 | */ | 1022 | */ |
1003 | if (init_attr->create_flags & ~(MLX4_IB_QP_LSO | | 1023 | if (init_attr->create_flags & ~(MLX4_IB_QP_LSO | |
1004 | MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK | | 1024 | MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK | |
1005 | MLX4_IB_SRIOV_TUNNEL_QP | MLX4_IB_SRIOV_SQP)) | 1025 | MLX4_IB_SRIOV_TUNNEL_QP | |
1026 | MLX4_IB_SRIOV_SQP | | ||
1027 | MLX4_IB_QP_NETIF)) | ||
1006 | return ERR_PTR(-EINVAL); | 1028 | return ERR_PTR(-EINVAL); |
1007 | 1029 | ||
1030 | if (init_attr->create_flags & IB_QP_CREATE_NETIF_QP) { | ||
1031 | if (init_attr->qp_type != IB_QPT_UD) | ||
1032 | return ERR_PTR(-EINVAL); | ||
1033 | } | ||
1034 | |||
1008 | if (init_attr->create_flags && | 1035 | if (init_attr->create_flags && |
1009 | (udata || | 1036 | (udata || |
1010 | ((init_attr->create_flags & ~MLX4_IB_SRIOV_SQP) && | 1037 | ((init_attr->create_flags & ~MLX4_IB_SRIOV_SQP) && |
@@ -1276,6 +1303,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, | |||
1276 | struct mlx4_qp_context *context; | 1303 | struct mlx4_qp_context *context; |
1277 | enum mlx4_qp_optpar optpar = 0; | 1304 | enum mlx4_qp_optpar optpar = 0; |
1278 | int sqd_event; | 1305 | int sqd_event; |
1306 | int steer_qp = 0; | ||
1279 | int err = -EINVAL; | 1307 | int err = -EINVAL; |
1280 | 1308 | ||
1281 | context = kzalloc(sizeof *context, GFP_KERNEL); | 1309 | context = kzalloc(sizeof *context, GFP_KERNEL); |
@@ -1360,6 +1388,11 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, | |||
1360 | optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX; | 1388 | optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX; |
1361 | } else | 1389 | } else |
1362 | context->pri_path.counter_index = 0xff; | 1390 | context->pri_path.counter_index = 0xff; |
1391 | |||
1392 | if (qp->flags & MLX4_IB_QP_NETIF) { | ||
1393 | mlx4_ib_steer_qp_reg(dev, qp, 1); | ||
1394 | steer_qp = 1; | ||
1395 | } | ||
1363 | } | 1396 | } |
1364 | 1397 | ||
1365 | if (attr_mask & IB_QP_PKEY_INDEX) { | 1398 | if (attr_mask & IB_QP_PKEY_INDEX) { |
@@ -1599,9 +1632,14 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, | |||
1599 | qp->sq_next_wqe = 0; | 1632 | qp->sq_next_wqe = 0; |
1600 | if (qp->rq.wqe_cnt) | 1633 | if (qp->rq.wqe_cnt) |
1601 | *qp->db.db = 0; | 1634 | *qp->db.db = 0; |
1635 | |||
1636 | if (qp->flags & MLX4_IB_QP_NETIF) | ||
1637 | mlx4_ib_steer_qp_reg(dev, qp, 0); | ||
1602 | } | 1638 | } |
1603 | 1639 | ||
1604 | out: | 1640 | out: |
1641 | if (err && steer_qp) | ||
1642 | mlx4_ib_steer_qp_reg(dev, qp, 0); | ||
1605 | kfree(context); | 1643 | kfree(context); |
1606 | return err; | 1644 | return err; |
1607 | } | 1645 | } |
@@ -2824,6 +2862,9 @@ done: | |||
2824 | if (qp->flags & MLX4_IB_QP_LSO) | 2862 | if (qp->flags & MLX4_IB_QP_LSO) |
2825 | qp_init_attr->create_flags |= IB_QP_CREATE_IPOIB_UD_LSO; | 2863 | qp_init_attr->create_flags |= IB_QP_CREATE_IPOIB_UD_LSO; |
2826 | 2864 | ||
2865 | if (qp->flags & MLX4_IB_QP_NETIF) | ||
2866 | qp_init_attr->create_flags |= IB_QP_CREATE_NETIF_QP; | ||
2867 | |||
2827 | qp_init_attr->sq_sig_type = | 2868 | qp_init_attr->sq_sig_type = |
2828 | qp->sq_signal_bits == cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) ? | 2869 | qp->sq_signal_bits == cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) ? |
2829 | IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; | 2870 | IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; |
diff --git a/drivers/infiniband/hw/mlx4/sysfs.c b/drivers/infiniband/hw/mlx4/sysfs.c index 97516eb363b7..db2ea31df832 100644 --- a/drivers/infiniband/hw/mlx4/sysfs.c +++ b/drivers/infiniband/hw/mlx4/sysfs.c | |||
@@ -582,8 +582,10 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) | |||
582 | p->pkey_group.attrs = | 582 | p->pkey_group.attrs = |
583 | alloc_group_attrs(show_port_pkey, store_port_pkey, | 583 | alloc_group_attrs(show_port_pkey, store_port_pkey, |
584 | dev->dev->caps.pkey_table_len[port_num]); | 584 | dev->dev->caps.pkey_table_len[port_num]); |
585 | if (!p->pkey_group.attrs) | 585 | if (!p->pkey_group.attrs) { |
586 | ret = -ENOMEM; | ||
586 | goto err_alloc; | 587 | goto err_alloc; |
588 | } | ||
587 | 589 | ||
588 | ret = sysfs_create_group(&p->kobj, &p->pkey_group); | 590 | ret = sysfs_create_group(&p->kobj, &p->pkey_group); |
589 | if (ret) | 591 | if (ret) |
@@ -591,8 +593,10 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) | |||
591 | 593 | ||
592 | p->gid_group.name = "gid_idx"; | 594 | p->gid_group.name = "gid_idx"; |
593 | p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1); | 595 | p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1); |
594 | if (!p->gid_group.attrs) | 596 | if (!p->gid_group.attrs) { |
597 | ret = -ENOMEM; | ||
595 | goto err_free_pkey; | 598 | goto err_free_pkey; |
599 | } | ||
596 | 600 | ||
597 | ret = sysfs_create_group(&p->kobj, &p->gid_group); | 601 | ret = sysfs_create_group(&p->kobj, &p->gid_group); |
598 | if (ret) | 602 | if (ret) |