return 0;
 }
 
-static void init_port(struct mlx4_ib_dev *dev, int port)
-{
-       struct mlx4_init_port_param param;
-       int err;
-
-       memset(¶m, 0, sizeof param);
-
-       param.port_width_cap = dev->dev->caps.port_width_cap;
-       param.vl_cap         = dev->dev->caps.vl_cap;
-       param.mtu            = ib_mtu_enum_to_int(dev->dev->caps.mtu_cap);
-       param.max_gid        = dev->dev->caps.gid_table_len;
-       param.max_pkey       = dev->dev->caps.pkey_table_len;
-
-       err = mlx4_INIT_PORT(dev->dev, ¶m, port);
-       if (err)
-               printk(KERN_WARNING "INIT_PORT failed, return code %d.\n", err);
-}
-
 static int to_mlx4_st(enum ib_qp_type type)
 {
        switch (type) {
        path->counter_index = 0xff;
 
        if (ah->ah_flags & IB_AH_GRH) {
-               if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len) {
+               if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
                        printk(KERN_ERR "sgid_index (%u) too large. max is %d\n",
-                              ah->grh.sgid_index, dev->dev->caps.gid_table_len - 1);
+                              ah->grh.sgid_index, dev->dev->caps.gid_table_len[port] - 1);
                        return -1;
                }
 
        }
 
        if (attr_mask & IB_QP_ALT_PATH) {
-               if (attr->alt_pkey_index >= dev->dev->caps.pkey_table_len)
-                       return -EINVAL;
-
                if (attr->alt_port_num == 0 ||
                    attr->alt_port_num > dev->dev->caps.num_ports)
                        return -EINVAL;
 
+               if (attr->alt_pkey_index >=
+                   dev->dev->caps.pkey_table_len[attr->alt_port_num])
+                       return -EINVAL;
+
                if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path,
                                  attr->alt_port_num))
                        return -EINVAL;
         */
        if (is_qp0(dev, qp)) {
                if (cur_state != IB_QPS_RTR && new_state == IB_QPS_RTR)
-                       init_port(dev, qp->port);
+                       if (mlx4_INIT_PORT(dev->dev, qp->port))
+                               printk(KERN_WARNING "INIT_PORT failed for port %d\n",
+                                      qp->port);
 
                if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR &&
                    (new_state == IB_QPS_RESET || new_state == IB_QPS_ERR))
        if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
                goto out;
 
-       if ((attr_mask & IB_QP_PKEY_INDEX) &&
-            attr->pkey_index >= dev->dev->caps.pkey_table_len) {
-               goto out;
-       }
-
        if ((attr_mask & IB_QP_PORT) &&
            (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
                goto out;
        }
 
+       if (attr_mask & IB_QP_PKEY_INDEX) {
+               int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
+               if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p])
+                       goto out;
+       }
+
        if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
            attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
                goto out;
 
 #include "icm.h"
 
 enum {
-       MLX4_COMMAND_INTERFACE_REV      = 2,
+       MLX4_COMMAND_INTERFACE_MIN_REV          = 2,
+       MLX4_COMMAND_INTERFACE_MAX_REV          = 3,
+       MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS    = 3,
 };
 
 extern void __buggy_use_of_MLX4_GET(void);
        u16 size;
        u16 stat_rate;
        int err;
+       int i;
 
 #define QUERY_DEV_CAP_OUT_SIZE                0x100
 #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET                0x10
 
        err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
                           MLX4_CMD_TIME_CLASS_A);
-
        if (err)
                goto out;
 
        dev_cap->max_rdma_global = 1 << (field & 0x3f);
        MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
        dev_cap->local_ca_ack_delay = field & 0x1f;
-       MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
-       dev_cap->max_mtu        = field >> 4;
-       dev_cap->max_port_width = field & 0xf;
        MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
-       dev_cap->max_vl    = field >> 4;
        dev_cap->num_ports = field & 0xf;
-       MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
-       dev_cap->max_gids = 1 << (field & 0xf);
        MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
        dev_cap->stat_rate_support = stat_rate;
-       MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
-       dev_cap->max_pkeys = 1 << (field & 0xf);
        MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
        MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
        dev_cap->reserved_uars = field >> 4;
        MLX4_GET(dev_cap->max_icm_sz, outbox,
                 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
 
+       if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+               for (i = 1; i <= dev_cap->num_ports; ++i) {
+                       MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
+                       dev_cap->max_vl[i]         = field >> 4;
+                       MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
+                       dev_cap->max_mtu[i]        = field >> 4;
+                       dev_cap->max_port_width[i] = field & 0xf;
+                       MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
+                       dev_cap->max_gids[i]       = 1 << (field & 0xf);
+                       MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
+                       dev_cap->max_pkeys[i]      = 1 << (field & 0xf);
+               }
+       } else {
+#define QUERY_PORT_MTU_OFFSET                  0x01
+#define QUERY_PORT_WIDTH_OFFSET                        0x06
+#define QUERY_PORT_MAX_GID_PKEY_OFFSET         0x07
+#define QUERY_PORT_MAX_VL_OFFSET               0x0b
+
+               for (i = 1; i <= dev_cap->num_ports; ++i) {
+                       err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
+                                          MLX4_CMD_TIME_CLASS_B);
+                       if (err)
+                               goto out;
+
+                       MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
+                       dev_cap->max_mtu[i]        = field & 0xf;
+                       MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
+                       dev_cap->max_port_width[i] = field & 0xf;
+                       MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
+                       dev_cap->max_gids[i]       = 1 << (field >> 4);
+                       dev_cap->max_pkeys[i]      = 1 << (field & 0xf);
+                       MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
+                       dev_cap->max_vl[i]         = field & 0xf;
+               }
+       }
+
        if (dev_cap->bmme_flags & 1)
                mlx4_dbg(dev, "Base MM extensions: yes "
                         "(flags %d, rsvd L_Key %08x)\n",
        mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
                 dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
        mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
-                dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu,
-                dev_cap->max_port_width);
+                dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1],
+                dev_cap->max_port_width[1]);
        mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
                 dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
        mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
                ((fw_ver & 0x0000ffffull) << 16);
 
        MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
-       if (cmd_if_rev != MLX4_COMMAND_INTERFACE_REV) {
+       if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
+           cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
                mlx4_err(dev, "Installed FW has unsupported "
                         "command interface revision %d.\n",
                         cmd_if_rev);
                         (int) (dev->caps.fw_ver >> 32),
                         (int) (dev->caps.fw_ver >> 16) & 0xffff,
                         (int) dev->caps.fw_ver & 0xffff);
-               mlx4_err(dev, "This driver version supports only revision %d.\n",
-                        MLX4_COMMAND_INTERFACE_REV);
+               mlx4_err(dev, "This driver version supports only revisions %d to %d.\n",
+                        MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV);
                err = -ENODEV;
                goto out;
        }
 
+       if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS)
+               dev->flags |= MLX4_FLAG_OLD_PORT_CMDS;
+
        MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
        cmd->max_cmds = 1 << lg;
 
        return err;
 }
 
-int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port)
+int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
 {
        struct mlx4_cmd_mailbox *mailbox;
        u32 *inbox;
        int err;
        u32 flags;
+       u16 field;
 
+       if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
 #define INIT_PORT_IN_SIZE          256
 #define INIT_PORT_FLAGS_OFFSET     0x00
 #define INIT_PORT_FLAG_SIG         (1 << 18)
 #define INIT_PORT_NODE_GUID_OFFSET 0x18
 #define INIT_PORT_SI_GUID_OFFSET   0x20
 
-       mailbox = mlx4_alloc_cmd_mailbox(dev);
-       if (IS_ERR(mailbox))
-               return PTR_ERR(mailbox);
-       inbox = mailbox->buf;
+               mailbox = mlx4_alloc_cmd_mailbox(dev);
+               if (IS_ERR(mailbox))
+                       return PTR_ERR(mailbox);
+               inbox = mailbox->buf;
 
-       memset(inbox, 0, INIT_PORT_IN_SIZE);
+               memset(inbox, 0, INIT_PORT_IN_SIZE);
 
-       flags = 0;
-       flags |= param->set_guid0     ? INIT_PORT_FLAG_G0  : 0;
-       flags |= param->set_node_guid ? INIT_PORT_FLAG_NG  : 0;
-       flags |= param->set_si_guid   ? INIT_PORT_FLAG_SIG : 0;
-       flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT;
-       flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
-       MLX4_PUT(inbox, flags,            INIT_PORT_FLAGS_OFFSET);
+               flags = 0;
+               flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT;
+               flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
+               MLX4_PUT(inbox, flags,            INIT_PORT_FLAGS_OFFSET);
 
-       MLX4_PUT(inbox, param->mtu,       INIT_PORT_MTU_OFFSET);
-       MLX4_PUT(inbox, param->max_gid,   INIT_PORT_MAX_GID_OFFSET);
-       MLX4_PUT(inbox, param->max_pkey,  INIT_PORT_MAX_PKEY_OFFSET);
-       MLX4_PUT(inbox, param->guid0,     INIT_PORT_GUID0_OFFSET);
-       MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET);
-       MLX4_PUT(inbox, param->si_guid,   INIT_PORT_SI_GUID_OFFSET);
+               field = 128 << dev->caps.mtu_cap[port];
+               MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
+               field = dev->caps.gid_table_len[port];
+               MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
+               field = dev->caps.pkey_table_len[port];
+               MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET);
 
-       err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
-                      MLX4_CMD_TIME_CLASS_A);
+               err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
+                              MLX4_CMD_TIME_CLASS_A);
 
-       mlx4_free_cmd_mailbox(dev, mailbox);
+               mlx4_free_cmd_mailbox(dev, mailbox);
+       } else
+               err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
+                              MLX4_CMD_TIME_CLASS_A);
 
        return err;
 }