diff options
author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2012-08-03 04:40:45 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-09-30 23:33:34 -0400 |
commit | 0a9a01884d447c216eff75f8f274a0a3e82c7cee (patch) | |
tree | c25b38c66c4d26c71b82c65a558316eeb4419231 | |
parent | 37bfc7c1e83f1589bcdc5918c7216422662644ee (diff) |
mlx4: MAD_IFC paravirtualization
The MAD_IFC firmware command fulfills two functions.
First, it is used in the QP0/QP1 MAD-handling flow to obtain
information from the FW (for answering queries), and for setting
variables in the HCA (MAD SET packets).
For this, MAD_IFC should provide the FW (physical) view of the data.
This is the view that OpenSM needs. We call this the "network view".
In the second case, MAD_IFC is used by various verbs to obtain data
regarding the local HCA (e.g., ib_query_device()). We call this the
"host view".
This data needs to be paravirtualized.
MAD_IFC therefore needs a wrapper function, and also needs another
flag indicating whether it should provide the network view (when it is
called by ib_process_mad in special-qp packet handling), or the host
view (when it is called while implementing a verb).
There are currently 2 flag parameters in mlx4_MAD_IFC already:
ignore_bkey and ignore_mkey. These two parameters are replaced by a
single "mad_ifc_flags" parameter, with different bits set for each
flag. A third flag is added: "network-view/host-view".
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/hw/mlx4/mad.c | 20 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 64 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 162 |
4 files changed, 234 insertions, 26 deletions
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 8dfbf69f837..ba2580693f7 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c | |||
@@ -75,7 +75,7 @@ struct mlx4_rcv_tunnel_mad { | |||
75 | struct ib_mad mad; | 75 | struct ib_mad mad; |
76 | } __packed; | 76 | } __packed; |
77 | 77 | ||
78 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, | 78 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, |
79 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 79 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, |
80 | void *in_mad, void *response_mad) | 80 | void *in_mad, void *response_mad) |
81 | { | 81 | { |
@@ -102,10 +102,13 @@ int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, | |||
102 | * Key check traps can't be generated unless we have in_wc to | 102 | * Key check traps can't be generated unless we have in_wc to |
103 | * tell us where to send the trap. | 103 | * tell us where to send the trap. |
104 | */ | 104 | */ |
105 | if (ignore_mkey || !in_wc) | 105 | if ((mad_ifc_flags & MLX4_MAD_IFC_IGNORE_MKEY) || !in_wc) |
106 | op_modifier |= 0x1; | 106 | op_modifier |= 0x1; |
107 | if (ignore_bkey || !in_wc) | 107 | if ((mad_ifc_flags & MLX4_MAD_IFC_IGNORE_BKEY) || !in_wc) |
108 | op_modifier |= 0x2; | 108 | op_modifier |= 0x2; |
109 | if (mlx4_is_mfunc(dev->dev) && | ||
110 | (mad_ifc_flags & MLX4_MAD_IFC_NET_VIEW || in_wc)) | ||
111 | op_modifier |= 0x8; | ||
109 | 112 | ||
110 | if (in_wc) { | 113 | if (in_wc) { |
111 | struct { | 114 | struct { |
@@ -138,10 +141,10 @@ int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, | |||
138 | in_modifier |= in_wc->slid << 16; | 141 | in_modifier |= in_wc->slid << 16; |
139 | } | 142 | } |
140 | 143 | ||
141 | err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma, | 144 | err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma, in_modifier, |
142 | in_modifier, op_modifier, | 145 | mlx4_is_master(dev->dev) ? (op_modifier & ~0x8) : op_modifier, |
143 | MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, | 146 | MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, |
144 | MLX4_CMD_NATIVE); | 147 | (op_modifier & 0x8) ? MLX4_CMD_NATIVE : MLX4_CMD_WRAPPED); |
145 | 148 | ||
146 | if (!err) | 149 | if (!err) |
147 | memcpy(response_mad, outmailbox->buf, 256); | 150 | memcpy(response_mad, outmailbox->buf, 256); |
@@ -614,8 +617,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
614 | prev_lid = pattr.lid; | 617 | prev_lid = pattr.lid; |
615 | 618 | ||
616 | err = mlx4_MAD_IFC(to_mdev(ibdev), | 619 | err = mlx4_MAD_IFC(to_mdev(ibdev), |
617 | mad_flags & IB_MAD_IGNORE_MKEY, | 620 | (mad_flags & IB_MAD_IGNORE_MKEY ? MLX4_MAD_IFC_IGNORE_MKEY : 0) | |
618 | mad_flags & IB_MAD_IGNORE_BKEY, | 621 | (mad_flags & IB_MAD_IGNORE_BKEY ? MLX4_MAD_IFC_IGNORE_BKEY : 0) | |
622 | MLX4_MAD_IFC_NET_VIEW, | ||
619 | port_num, in_wc, in_grh, in_mad, out_mad); | 623 | port_num, in_wc, in_grh, in_mad, out_mad); |
620 | if (err) | 624 | if (err) |
621 | return IB_MAD_RESULT_FAILURE; | 625 | return IB_MAD_RESULT_FAILURE; |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 8e10ec2af7b..45a6cc04036 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -98,7 +98,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, | |||
98 | init_query_mad(in_mad); | 98 | init_query_mad(in_mad); |
99 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | 99 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; |
100 | 100 | ||
101 | err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); | 101 | err = mlx4_MAD_IFC(to_mdev(ibdev), MLX4_MAD_IFC_IGNORE_KEYS, |
102 | 1, NULL, NULL, in_mad, out_mad); | ||
102 | if (err) | 103 | if (err) |
103 | goto out; | 104 | goto out; |
104 | 105 | ||
@@ -182,11 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num) | |||
182 | } | 183 | } |
183 | 184 | ||
184 | static int ib_link_query_port(struct ib_device *ibdev, u8 port, | 185 | static int ib_link_query_port(struct ib_device *ibdev, u8 port, |
185 | struct ib_port_attr *props) | 186 | struct ib_port_attr *props, int netw_view) |
186 | { | 187 | { |
187 | struct ib_smp *in_mad = NULL; | 188 | struct ib_smp *in_mad = NULL; |
188 | struct ib_smp *out_mad = NULL; | 189 | struct ib_smp *out_mad = NULL; |
189 | int ext_active_speed; | 190 | int ext_active_speed; |
191 | int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS; | ||
190 | int err = -ENOMEM; | 192 | int err = -ENOMEM; |
191 | 193 | ||
192 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | 194 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
@@ -198,7 +200,10 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port, | |||
198 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | 200 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
199 | in_mad->attr_mod = cpu_to_be32(port); | 201 | in_mad->attr_mod = cpu_to_be32(port); |
200 | 202 | ||
201 | err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, | 203 | if (mlx4_is_mfunc(to_mdev(ibdev)->dev) && netw_view) |
204 | mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW; | ||
205 | |||
206 | err = mlx4_MAD_IFC(to_mdev(ibdev), mad_ifc_flags, port, NULL, NULL, | ||
202 | in_mad, out_mad); | 207 | in_mad, out_mad); |
203 | if (err) | 208 | if (err) |
204 | goto out; | 209 | goto out; |
@@ -211,7 +216,10 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port, | |||
211 | props->state = out_mad->data[32] & 0xf; | 216 | props->state = out_mad->data[32] & 0xf; |
212 | props->phys_state = out_mad->data[33] >> 4; | 217 | props->phys_state = out_mad->data[33] >> 4; |
213 | props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20)); | 218 | props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20)); |
214 | props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port]; | 219 | if (netw_view) |
220 | props->gid_tbl_len = out_mad->data[50]; | ||
221 | else | ||
222 | props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port]; | ||
215 | props->max_msg_sz = to_mdev(ibdev)->dev->caps.max_msg_sz; | 223 | props->max_msg_sz = to_mdev(ibdev)->dev->caps.max_msg_sz; |
216 | props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len[port]; | 224 | props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len[port]; |
217 | props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); | 225 | props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); |
@@ -244,7 +252,7 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port, | |||
244 | in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO; | 252 | in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO; |
245 | in_mad->attr_mod = cpu_to_be32(port); | 253 | in_mad->attr_mod = cpu_to_be32(port); |
246 | 254 | ||
247 | err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, | 255 | err = mlx4_MAD_IFC(to_mdev(ibdev), mad_ifc_flags, port, |
248 | NULL, NULL, in_mad, out_mad); | 256 | NULL, NULL, in_mad, out_mad); |
249 | if (err) | 257 | if (err) |
250 | goto out; | 258 | goto out; |
@@ -270,7 +278,7 @@ static u8 state_to_phys_state(enum ib_port_state state) | |||
270 | } | 278 | } |
271 | 279 | ||
272 | static int eth_link_query_port(struct ib_device *ibdev, u8 port, | 280 | static int eth_link_query_port(struct ib_device *ibdev, u8 port, |
273 | struct ib_port_attr *props) | 281 | struct ib_port_attr *props, int netw_view) |
274 | { | 282 | { |
275 | 283 | ||
276 | struct mlx4_ib_dev *mdev = to_mdev(ibdev); | 284 | struct mlx4_ib_dev *mdev = to_mdev(ibdev); |
@@ -320,20 +328,27 @@ out: | |||
320 | return err; | 328 | return err; |
321 | } | 329 | } |
322 | 330 | ||
323 | static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, | 331 | int __mlx4_ib_query_port(struct ib_device *ibdev, u8 port, |
324 | struct ib_port_attr *props) | 332 | struct ib_port_attr *props, int netw_view) |
325 | { | 333 | { |
326 | int err; | 334 | int err; |
327 | 335 | ||
328 | memset(props, 0, sizeof *props); | 336 | memset(props, 0, sizeof *props); |
329 | 337 | ||
330 | err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ? | 338 | err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ? |
331 | ib_link_query_port(ibdev, port, props) : | 339 | ib_link_query_port(ibdev, port, props, netw_view) : |
332 | eth_link_query_port(ibdev, port, props); | 340 | eth_link_query_port(ibdev, port, props, netw_view); |
333 | 341 | ||
334 | return err; | 342 | return err; |
335 | } | 343 | } |
336 | 344 | ||
345 | static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, | ||
346 | struct ib_port_attr *props) | ||
347 | { | ||
348 | /* returns host view */ | ||
349 | return __mlx4_ib_query_port(ibdev, port, props, 0); | ||
350 | } | ||
351 | |||
337 | static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, | 352 | static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, |
338 | union ib_gid *gid) | 353 | union ib_gid *gid) |
339 | { | 354 | { |
@@ -350,7 +365,8 @@ static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, | |||
350 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | 365 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
351 | in_mad->attr_mod = cpu_to_be32(port); | 366 | in_mad->attr_mod = cpu_to_be32(port); |
352 | 367 | ||
353 | err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); | 368 | err = mlx4_MAD_IFC(to_mdev(ibdev), MLX4_MAD_IFC_IGNORE_KEYS, port, |
369 | NULL, NULL, in_mad, out_mad); | ||
354 | if (err) | 370 | if (err) |
355 | goto out; | 371 | goto out; |
356 | 372 | ||
@@ -360,7 +376,8 @@ static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, | |||
360 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | 376 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; |
361 | in_mad->attr_mod = cpu_to_be32(index / 8); | 377 | in_mad->attr_mod = cpu_to_be32(index / 8); |
362 | 378 | ||
363 | err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); | 379 | err = mlx4_MAD_IFC(to_mdev(ibdev), MLX4_MAD_IFC_IGNORE_KEYS, port, |
380 | NULL, NULL, in_mad, out_mad); | ||
364 | if (err) | 381 | if (err) |
365 | goto out; | 382 | goto out; |
366 | 383 | ||
@@ -391,11 +408,12 @@ static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, | |||
391 | return iboe_query_gid(ibdev, port, index, gid); | 408 | return iboe_query_gid(ibdev, port, index, gid); |
392 | } | 409 | } |
393 | 410 | ||
394 | static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, | 411 | int __mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, |
395 | u16 *pkey) | 412 | u16 *pkey, int netw_view) |
396 | { | 413 | { |
397 | struct ib_smp *in_mad = NULL; | 414 | struct ib_smp *in_mad = NULL; |
398 | struct ib_smp *out_mad = NULL; | 415 | struct ib_smp *out_mad = NULL; |
416 | int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS; | ||
399 | int err = -ENOMEM; | 417 | int err = -ENOMEM; |
400 | 418 | ||
401 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | 419 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
@@ -407,7 +425,11 @@ static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, | |||
407 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | 425 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; |
408 | in_mad->attr_mod = cpu_to_be32(index / 32); | 426 | in_mad->attr_mod = cpu_to_be32(index / 32); |
409 | 427 | ||
410 | err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); | 428 | if (mlx4_is_mfunc(to_mdev(ibdev)->dev) && netw_view) |
429 | mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW; | ||
430 | |||
431 | err = mlx4_MAD_IFC(to_mdev(ibdev), mad_ifc_flags, port, NULL, NULL, | ||
432 | in_mad, out_mad); | ||
411 | if (err) | 433 | if (err) |
412 | goto out; | 434 | goto out; |
413 | 435 | ||
@@ -419,6 +441,11 @@ out: | |||
419 | return err; | 441 | return err; |
420 | } | 442 | } |
421 | 443 | ||
444 | static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) | ||
445 | { | ||
446 | return __mlx4_ib_query_pkey(ibdev, port, index, pkey, 0); | ||
447 | } | ||
448 | |||
422 | static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, | 449 | static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, |
423 | struct ib_device_modify *props) | 450 | struct ib_device_modify *props) |
424 | { | 451 | { |
@@ -849,6 +876,7 @@ static int init_node_data(struct mlx4_ib_dev *dev) | |||
849 | { | 876 | { |
850 | struct ib_smp *in_mad = NULL; | 877 | struct ib_smp *in_mad = NULL; |
851 | struct ib_smp *out_mad = NULL; | 878 | struct ib_smp *out_mad = NULL; |
879 | int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS; | ||
852 | int err = -ENOMEM; | 880 | int err = -ENOMEM; |
853 | 881 | ||
854 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | 882 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
@@ -858,8 +886,10 @@ static int init_node_data(struct mlx4_ib_dev *dev) | |||
858 | 886 | ||
859 | init_query_mad(in_mad); | 887 | init_query_mad(in_mad); |
860 | in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; | 888 | in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; |
889 | if (mlx4_is_master(dev->dev)) | ||
890 | mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW; | ||
861 | 891 | ||
862 | err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | 892 | err = mlx4_MAD_IFC(dev, mad_ifc_flags, 1, NULL, NULL, in_mad, out_mad); |
863 | if (err) | 893 | if (err) |
864 | goto out; | 894 | goto out; |
865 | 895 | ||
@@ -867,7 +897,7 @@ static int init_node_data(struct mlx4_ib_dev *dev) | |||
867 | 897 | ||
868 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | 898 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; |
869 | 899 | ||
870 | err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | 900 | err = mlx4_MAD_IFC(dev, mad_ifc_flags, 1, NULL, NULL, in_mad, out_mad); |
871 | if (err) | 901 | if (err) |
872 | goto out; | 902 | goto out; |
873 | 903 | ||
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 137941d7987..ac71d56ffc7 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -176,6 +176,14 @@ enum mlx4_ib_qp_type { | |||
176 | MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER | \ | 176 | MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER | \ |
177 | MLX4_IB_QPT_TUN_SMI | MLX4_IB_QPT_TUN_GSI) | 177 | MLX4_IB_QPT_TUN_SMI | MLX4_IB_QPT_TUN_GSI) |
178 | 178 | ||
179 | enum mlx4_ib_mad_ifc_flags { | ||
180 | MLX4_MAD_IFC_IGNORE_MKEY = 1, | ||
181 | MLX4_MAD_IFC_IGNORE_BKEY = 2, | ||
182 | MLX4_MAD_IFC_IGNORE_KEYS = (MLX4_MAD_IFC_IGNORE_MKEY | | ||
183 | MLX4_MAD_IFC_IGNORE_BKEY), | ||
184 | MLX4_MAD_IFC_NET_VIEW = 4, | ||
185 | }; | ||
186 | |||
179 | enum { | 187 | enum { |
180 | MLX4_NUM_TUNNEL_BUFS = 256, | 188 | MLX4_NUM_TUNNEL_BUFS = 256, |
181 | }; | 189 | }; |
@@ -512,7 +520,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
512 | int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, | 520 | int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, |
513 | struct ib_recv_wr **bad_wr); | 521 | struct ib_recv_wr **bad_wr); |
514 | 522 | ||
515 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, | 523 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, |
516 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 524 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, |
517 | void *in_mad, void *response_mad); | 525 | void *in_mad, void *response_mad); |
518 | int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 526 | int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
@@ -527,6 +535,10 @@ int mlx4_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, int npages, | |||
527 | u64 iova); | 535 | u64 iova); |
528 | int mlx4_ib_unmap_fmr(struct list_head *fmr_list); | 536 | int mlx4_ib_unmap_fmr(struct list_head *fmr_list); |
529 | int mlx4_ib_fmr_dealloc(struct ib_fmr *fmr); | 537 | int mlx4_ib_fmr_dealloc(struct ib_fmr *fmr); |
538 | int __mlx4_ib_query_port(struct ib_device *ibdev, u8 port, | ||
539 | struct ib_port_attr *props, int netw_view); | ||
540 | int __mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, | ||
541 | u16 *pkey, int netw_view); | ||
530 | 542 | ||
531 | int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr, | 543 | int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr, |
532 | u8 *mac, int *is_mcast, u8 port); | 544 | u8 *mac, int *is_mcast, u8 port); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 662a3c5da73..a13d8a69b3b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -40,6 +40,7 @@ | |||
40 | 40 | ||
41 | #include <linux/mlx4/cmd.h> | 41 | #include <linux/mlx4/cmd.h> |
42 | #include <linux/semaphore.h> | 42 | #include <linux/semaphore.h> |
43 | #include <rdma/ib_smi.h> | ||
43 | 44 | ||
44 | #include <asm/io.h> | 45 | #include <asm/io.h> |
45 | 46 | ||
@@ -627,6 +628,149 @@ static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr, | |||
627 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); | 628 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); |
628 | } | 629 | } |
629 | 630 | ||
631 | static int query_pkey_block(struct mlx4_dev *dev, u8 port, u16 index, u16 *pkey, | ||
632 | struct mlx4_cmd_mailbox *inbox, | ||
633 | struct mlx4_cmd_mailbox *outbox) | ||
634 | { | ||
635 | struct ib_smp *in_mad = (struct ib_smp *)(inbox->buf); | ||
636 | struct ib_smp *out_mad = (struct ib_smp *)(outbox->buf); | ||
637 | int err; | ||
638 | int i; | ||
639 | |||
640 | if (index & 0x1f) | ||
641 | return -EINVAL; | ||
642 | |||
643 | in_mad->attr_mod = cpu_to_be32(index / 32); | ||
644 | |||
645 | err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3, | ||
646 | MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, | ||
647 | MLX4_CMD_NATIVE); | ||
648 | if (err) | ||
649 | return err; | ||
650 | |||
651 | for (i = 0; i < 32; ++i) | ||
652 | pkey[i] = be16_to_cpu(((__be16 *) out_mad->data)[i]); | ||
653 | |||
654 | return err; | ||
655 | } | ||
656 | |||
657 | static int get_full_pkey_table(struct mlx4_dev *dev, u8 port, u16 *table, | ||
658 | struct mlx4_cmd_mailbox *inbox, | ||
659 | struct mlx4_cmd_mailbox *outbox) | ||
660 | { | ||
661 | int i; | ||
662 | int err; | ||
663 | |||
664 | for (i = 0; i < dev->caps.pkey_table_len[port]; i += 32) { | ||
665 | err = query_pkey_block(dev, port, i, table + i, inbox, outbox); | ||
666 | if (err) | ||
667 | return err; | ||
668 | } | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | #define PORT_CAPABILITY_LOCATION_IN_SMP 20 | ||
673 | #define PORT_STATE_OFFSET 32 | ||
674 | |||
675 | static enum ib_port_state vf_port_state(struct mlx4_dev *dev, int port, int vf) | ||
676 | { | ||
677 | /* will be modified when add alias_guid feature */ | ||
678 | return IB_PORT_DOWN; | ||
679 | } | ||
680 | |||
681 | static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, | ||
682 | struct mlx4_vhcr *vhcr, | ||
683 | struct mlx4_cmd_mailbox *inbox, | ||
684 | struct mlx4_cmd_mailbox *outbox, | ||
685 | struct mlx4_cmd_info *cmd) | ||
686 | { | ||
687 | struct ib_smp *smp = inbox->buf; | ||
688 | u32 index; | ||
689 | u8 port; | ||
690 | u16 *table; | ||
691 | int err; | ||
692 | int vidx, pidx; | ||
693 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
694 | struct ib_smp *outsmp = outbox->buf; | ||
695 | __be16 *outtab = (__be16 *)(outsmp->data); | ||
696 | __be32 slave_cap_mask; | ||
697 | port = vhcr->in_modifier; | ||
698 | |||
699 | if (smp->base_version == 1 && | ||
700 | smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED && | ||
701 | smp->class_version == 1) { | ||
702 | if (smp->method == IB_MGMT_METHOD_GET) { | ||
703 | if (smp->attr_id == IB_SMP_ATTR_PKEY_TABLE) { | ||
704 | index = be32_to_cpu(smp->attr_mod); | ||
705 | if (port < 1 || port > dev->caps.num_ports) | ||
706 | return -EINVAL; | ||
707 | table = kcalloc(dev->caps.pkey_table_len[port], sizeof *table, GFP_KERNEL); | ||
708 | if (!table) | ||
709 | return -ENOMEM; | ||
710 | /* need to get the full pkey table because the paravirtualized | ||
711 | * pkeys may be scattered among several pkey blocks. | ||
712 | */ | ||
713 | err = get_full_pkey_table(dev, port, table, inbox, outbox); | ||
714 | if (!err) { | ||
715 | for (vidx = index * 32; vidx < (index + 1) * 32; ++vidx) { | ||
716 | pidx = priv->virt2phys_pkey[slave][port - 1][vidx]; | ||
717 | outtab[vidx % 32] = cpu_to_be16(table[pidx]); | ||
718 | } | ||
719 | } | ||
720 | kfree(table); | ||
721 | return err; | ||
722 | } | ||
723 | if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) { | ||
724 | /*get the slave specific caps:*/ | ||
725 | /*do the command */ | ||
726 | err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, | ||
727 | vhcr->in_modifier, vhcr->op_modifier, | ||
728 | vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); | ||
729 | /* modify the response for slaves */ | ||
730 | if (!err && slave != mlx4_master_func_num(dev)) { | ||
731 | u8 *state = outsmp->data + PORT_STATE_OFFSET; | ||
732 | |||
733 | *state = (*state & 0xf0) | vf_port_state(dev, port, slave); | ||
734 | slave_cap_mask = priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; | ||
735 | memcpy(outsmp->data + PORT_CAPABILITY_LOCATION_IN_SMP, &slave_cap_mask, 4); | ||
736 | } | ||
737 | return err; | ||
738 | } | ||
739 | if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) { | ||
740 | /* compute slave's gid block */ | ||
741 | smp->attr_mod = cpu_to_be32(slave / 8); | ||
742 | /* execute cmd */ | ||
743 | err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, | ||
744 | vhcr->in_modifier, vhcr->op_modifier, | ||
745 | vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); | ||
746 | if (!err) { | ||
747 | /* if needed, move slave gid to index 0 */ | ||
748 | if (slave % 8) | ||
749 | memcpy(outsmp->data, | ||
750 | outsmp->data + (slave % 8) * 8, 8); | ||
751 | /* delete all other gids */ | ||
752 | memset(outsmp->data + 8, 0, 56); | ||
753 | } | ||
754 | return err; | ||
755 | } | ||
756 | } | ||
757 | } | ||
758 | if (slave != mlx4_master_func_num(dev) && | ||
759 | ((smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) || | ||
760 | (smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED && | ||
761 | smp->method == IB_MGMT_METHOD_SET))) { | ||
762 | mlx4_err(dev, "slave %d is trying to execute a Subnet MGMT MAD, " | ||
763 | "class 0x%x, method 0x%x for attr 0x%x. Rejecting\n", | ||
764 | slave, smp->method, smp->mgmt_class, | ||
765 | be16_to_cpu(smp->attr_id)); | ||
766 | return -EPERM; | ||
767 | } | ||
768 | /*default:*/ | ||
769 | return mlx4_cmd_box(dev, inbox->dma, outbox->dma, | ||
770 | vhcr->in_modifier, vhcr->op_modifier, | ||
771 | vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); | ||
772 | } | ||
773 | |||
630 | int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, | 774 | int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, |
631 | struct mlx4_vhcr *vhcr, | 775 | struct mlx4_vhcr *vhcr, |
632 | struct mlx4_cmd_mailbox *inbox, | 776 | struct mlx4_cmd_mailbox *inbox, |
@@ -1061,6 +1205,24 @@ static struct mlx4_cmd_info cmd_info[] = { | |||
1061 | .wrapper = mlx4_GEN_QP_wrapper | 1205 | .wrapper = mlx4_GEN_QP_wrapper |
1062 | }, | 1206 | }, |
1063 | { | 1207 | { |
1208 | .opcode = MLX4_CMD_CONF_SPECIAL_QP, | ||
1209 | .has_inbox = false, | ||
1210 | .has_outbox = false, | ||
1211 | .out_is_imm = false, | ||
1212 | .encode_slave_id = false, | ||
1213 | .verify = NULL, /* XXX verify: only demux can do this */ | ||
1214 | .wrapper = NULL | ||
1215 | }, | ||
1216 | { | ||
1217 | .opcode = MLX4_CMD_MAD_IFC, | ||
1218 | .has_inbox = true, | ||
1219 | .has_outbox = true, | ||
1220 | .out_is_imm = false, | ||
1221 | .encode_slave_id = false, | ||
1222 | .verify = NULL, | ||
1223 | .wrapper = mlx4_MAD_IFC_wrapper | ||
1224 | }, | ||
1225 | { | ||
1064 | .opcode = MLX4_CMD_QUERY_IF_STAT, | 1226 | .opcode = MLX4_CMD_QUERY_IF_STAT, |
1065 | .has_inbox = false, | 1227 | .has_inbox = false, |
1066 | .has_outbox = true, | 1228 | .has_outbox = true, |