diff options
Diffstat (limited to 'drivers/net/mlx4/fw.c')
-rw-r--r-- | drivers/net/mlx4/fw.c | 110 |
1 files changed, 73 insertions, 37 deletions
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index 81fc546a1c44..d2b065351e45 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c | |||
@@ -38,7 +38,9 @@ | |||
38 | #include "icm.h" | 38 | #include "icm.h" |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | MLX4_COMMAND_INTERFACE_REV = 2, | 41 | MLX4_COMMAND_INTERFACE_MIN_REV = 2, |
42 | MLX4_COMMAND_INTERFACE_MAX_REV = 3, | ||
43 | MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS = 3, | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | extern void __buggy_use_of_MLX4_GET(void); | 46 | extern void __buggy_use_of_MLX4_GET(void); |
@@ -107,6 +109,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
107 | u16 size; | 109 | u16 size; |
108 | u16 stat_rate; | 110 | u16 stat_rate; |
109 | int err; | 111 | int err; |
112 | int i; | ||
110 | 113 | ||
111 | #define QUERY_DEV_CAP_OUT_SIZE 0x100 | 114 | #define QUERY_DEV_CAP_OUT_SIZE 0x100 |
112 | #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 | 115 | #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 |
@@ -176,7 +179,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
176 | 179 | ||
177 | err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, | 180 | err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, |
178 | MLX4_CMD_TIME_CLASS_A); | 181 | MLX4_CMD_TIME_CLASS_A); |
179 | |||
180 | if (err) | 182 | if (err) |
181 | goto out; | 183 | goto out; |
182 | 184 | ||
@@ -216,18 +218,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
216 | dev_cap->max_rdma_global = 1 << (field & 0x3f); | 218 | dev_cap->max_rdma_global = 1 << (field & 0x3f); |
217 | MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); | 219 | MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); |
218 | dev_cap->local_ca_ack_delay = field & 0x1f; | 220 | dev_cap->local_ca_ack_delay = field & 0x1f; |
219 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); | ||
220 | dev_cap->max_mtu = field >> 4; | ||
221 | dev_cap->max_port_width = field & 0xf; | ||
222 | MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); | 221 | MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); |
223 | dev_cap->max_vl = field >> 4; | ||
224 | dev_cap->num_ports = field & 0xf; | 222 | dev_cap->num_ports = field & 0xf; |
225 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); | ||
226 | dev_cap->max_gids = 1 << (field & 0xf); | ||
227 | MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); | 223 | MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); |
228 | dev_cap->stat_rate_support = stat_rate; | 224 | dev_cap->stat_rate_support = stat_rate; |
229 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); | ||
230 | dev_cap->max_pkeys = 1 << (field & 0xf); | ||
231 | MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); | 225 | MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); |
232 | MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); | 226 | MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); |
233 | dev_cap->reserved_uars = field >> 4; | 227 | dev_cap->reserved_uars = field >> 4; |
@@ -304,6 +298,42 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
304 | MLX4_GET(dev_cap->max_icm_sz, outbox, | 298 | MLX4_GET(dev_cap->max_icm_sz, outbox, |
305 | QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); | 299 | QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); |
306 | 300 | ||
301 | if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { | ||
302 | for (i = 1; i <= dev_cap->num_ports; ++i) { | ||
303 | MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); | ||
304 | dev_cap->max_vl[i] = field >> 4; | ||
305 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); | ||
306 | dev_cap->max_mtu[i] = field >> 4; | ||
307 | dev_cap->max_port_width[i] = field & 0xf; | ||
308 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); | ||
309 | dev_cap->max_gids[i] = 1 << (field & 0xf); | ||
310 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); | ||
311 | dev_cap->max_pkeys[i] = 1 << (field & 0xf); | ||
312 | } | ||
313 | } else { | ||
314 | #define QUERY_PORT_MTU_OFFSET 0x01 | ||
315 | #define QUERY_PORT_WIDTH_OFFSET 0x06 | ||
316 | #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 | ||
317 | #define QUERY_PORT_MAX_VL_OFFSET 0x0b | ||
318 | |||
319 | for (i = 1; i <= dev_cap->num_ports; ++i) { | ||
320 | err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, | ||
321 | MLX4_CMD_TIME_CLASS_B); | ||
322 | if (err) | ||
323 | goto out; | ||
324 | |||
325 | MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); | ||
326 | dev_cap->max_mtu[i] = field & 0xf; | ||
327 | MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); | ||
328 | dev_cap->max_port_width[i] = field & 0xf; | ||
329 | MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); | ||
330 | dev_cap->max_gids[i] = 1 << (field >> 4); | ||
331 | dev_cap->max_pkeys[i] = 1 << (field & 0xf); | ||
332 | MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); | ||
333 | dev_cap->max_vl[i] = field & 0xf; | ||
334 | } | ||
335 | } | ||
336 | |||
307 | if (dev_cap->bmme_flags & 1) | 337 | if (dev_cap->bmme_flags & 1) |
308 | mlx4_dbg(dev, "Base MM extensions: yes " | 338 | mlx4_dbg(dev, "Base MM extensions: yes " |
309 | "(flags %d, rsvd L_Key %08x)\n", | 339 | "(flags %d, rsvd L_Key %08x)\n", |
@@ -338,8 +368,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
338 | mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", | 368 | mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", |
339 | dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); | 369 | dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); |
340 | mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", | 370 | mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", |
341 | dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu, | 371 | dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1], |
342 | dev_cap->max_port_width); | 372 | dev_cap->max_port_width[1]); |
343 | mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", | 373 | mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", |
344 | dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); | 374 | dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); |
345 | mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", | 375 | mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", |
@@ -491,7 +521,8 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) | |||
491 | ((fw_ver & 0x0000ffffull) << 16); | 521 | ((fw_ver & 0x0000ffffull) << 16); |
492 | 522 | ||
493 | MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); | 523 | MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); |
494 | if (cmd_if_rev != MLX4_COMMAND_INTERFACE_REV) { | 524 | if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV || |
525 | cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) { | ||
495 | mlx4_err(dev, "Installed FW has unsupported " | 526 | mlx4_err(dev, "Installed FW has unsupported " |
496 | "command interface revision %d.\n", | 527 | "command interface revision %d.\n", |
497 | cmd_if_rev); | 528 | cmd_if_rev); |
@@ -499,12 +530,15 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) | |||
499 | (int) (dev->caps.fw_ver >> 32), | 530 | (int) (dev->caps.fw_ver >> 32), |
500 | (int) (dev->caps.fw_ver >> 16) & 0xffff, | 531 | (int) (dev->caps.fw_ver >> 16) & 0xffff, |
501 | (int) dev->caps.fw_ver & 0xffff); | 532 | (int) dev->caps.fw_ver & 0xffff); |
502 | mlx4_err(dev, "This driver version supports only revision %d.\n", | 533 | mlx4_err(dev, "This driver version supports only revisions %d to %d.\n", |
503 | MLX4_COMMAND_INTERFACE_REV); | 534 | MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV); |
504 | err = -ENODEV; | 535 | err = -ENODEV; |
505 | goto out; | 536 | goto out; |
506 | } | 537 | } |
507 | 538 | ||
539 | if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS) | ||
540 | dev->flags |= MLX4_FLAG_OLD_PORT_CMDS; | ||
541 | |||
508 | MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); | 542 | MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); |
509 | cmd->max_cmds = 1 << lg; | 543 | cmd->max_cmds = 1 << lg; |
510 | 544 | ||
@@ -708,13 +742,15 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
708 | return err; | 742 | return err; |
709 | } | 743 | } |
710 | 744 | ||
711 | int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port) | 745 | int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) |
712 | { | 746 | { |
713 | struct mlx4_cmd_mailbox *mailbox; | 747 | struct mlx4_cmd_mailbox *mailbox; |
714 | u32 *inbox; | 748 | u32 *inbox; |
715 | int err; | 749 | int err; |
716 | u32 flags; | 750 | u32 flags; |
751 | u16 field; | ||
717 | 752 | ||
753 | if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { | ||
718 | #define INIT_PORT_IN_SIZE 256 | 754 | #define INIT_PORT_IN_SIZE 256 |
719 | #define INIT_PORT_FLAGS_OFFSET 0x00 | 755 | #define INIT_PORT_FLAGS_OFFSET 0x00 |
720 | #define INIT_PORT_FLAG_SIG (1 << 18) | 756 | #define INIT_PORT_FLAG_SIG (1 << 18) |
@@ -729,32 +765,32 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int | |||
729 | #define INIT_PORT_NODE_GUID_OFFSET 0x18 | 765 | #define INIT_PORT_NODE_GUID_OFFSET 0x18 |
730 | #define INIT_PORT_SI_GUID_OFFSET 0x20 | 766 | #define INIT_PORT_SI_GUID_OFFSET 0x20 |
731 | 767 | ||
732 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 768 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
733 | if (IS_ERR(mailbox)) | 769 | if (IS_ERR(mailbox)) |
734 | return PTR_ERR(mailbox); | 770 | return PTR_ERR(mailbox); |
735 | inbox = mailbox->buf; | 771 | inbox = mailbox->buf; |
736 | 772 | ||
737 | memset(inbox, 0, INIT_PORT_IN_SIZE); | 773 | memset(inbox, 0, INIT_PORT_IN_SIZE); |
738 | 774 | ||
739 | flags = 0; | 775 | flags = 0; |
740 | flags |= param->set_guid0 ? INIT_PORT_FLAG_G0 : 0; | 776 | flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT; |
741 | flags |= param->set_node_guid ? INIT_PORT_FLAG_NG : 0; | 777 | flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; |
742 | flags |= param->set_si_guid ? INIT_PORT_FLAG_SIG : 0; | 778 | MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); |
743 | flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT; | ||
744 | flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; | ||
745 | MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); | ||
746 | 779 | ||
747 | MLX4_PUT(inbox, param->mtu, INIT_PORT_MTU_OFFSET); | 780 | field = 128 << dev->caps.mtu_cap[port]; |
748 | MLX4_PUT(inbox, param->max_gid, INIT_PORT_MAX_GID_OFFSET); | 781 | MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET); |
749 | MLX4_PUT(inbox, param->max_pkey, INIT_PORT_MAX_PKEY_OFFSET); | 782 | field = dev->caps.gid_table_len[port]; |
750 | MLX4_PUT(inbox, param->guid0, INIT_PORT_GUID0_OFFSET); | 783 | MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET); |
751 | MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET); | 784 | field = dev->caps.pkey_table_len[port]; |
752 | MLX4_PUT(inbox, param->si_guid, INIT_PORT_SI_GUID_OFFSET); | 785 | MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET); |
753 | 786 | ||
754 | err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, | 787 | err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, |
755 | MLX4_CMD_TIME_CLASS_A); | 788 | MLX4_CMD_TIME_CLASS_A); |
756 | 789 | ||
757 | mlx4_free_cmd_mailbox(dev, mailbox); | 790 | mlx4_free_cmd_mailbox(dev, mailbox); |
791 | } else | ||
792 | err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, | ||
793 | MLX4_CMD_TIME_CLASS_A); | ||
758 | 794 | ||
759 | return err; | 795 | return err; |
760 | } | 796 | } |