svn commit: r272027 - in head: contrib/ofed/libibverbs/examples contrib/ofed/libmlx4/src sys/conf sys/modules/mlx4 sys/modules/mlxen sys/ofed/drivers/infiniband/hw/mlx4 sys/ofed/drivers/infiniband/...

Hans Petter Selasky hselasky at FreeBSD.org
Tue Sep 23 12:37:06 UTC 2014


Author: hselasky
Date: Tue Sep 23 12:37:01 2014
New Revision: 272027
URL: http://svnweb.freebsd.org/changeset/base/272027

Log:
  Hardware driver update from Mellanox Technologies, including:
   - improved performance
   - better stability
   - new features
   - bugfixes
  
  Supported HCAs:
   - ConnectX-2
   - ConnectX-3
   - ConnectX-3 Pro
  
  Sponsored by:	Mellanox Technologies
  MFC after:	1 week

Added:
  head/sys/ofed/drivers/net/mlx4/mlx4_stats.h   (contents, props changed)
  head/sys/ofed/drivers/net/mlx4/utils.c   (contents, props changed)
  head/sys/ofed/drivers/net/mlx4/utils.h   (contents, props changed)
Modified:
  head/contrib/ofed/libibverbs/examples/asyncwatch.c
  head/contrib/ofed/libibverbs/examples/device_list.c
  head/contrib/ofed/libibverbs/examples/devinfo.c
  head/contrib/ofed/libmlx4/src/mlx4-abi.h
  head/sys/conf/files
  head/sys/modules/mlx4/Makefile
  head/sys/modules/mlxen/Makefile
  head/sys/ofed/drivers/infiniband/hw/mlx4/mad.c
  head/sys/ofed/drivers/infiniband/hw/mlx4/main.c
  head/sys/ofed/drivers/infiniband/hw/mlx4/qp.c
  head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c
  head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
  head/sys/ofed/drivers/net/mlx4/alloc.c
  head/sys/ofed/drivers/net/mlx4/catas.c
  head/sys/ofed/drivers/net/mlx4/cmd.c
  head/sys/ofed/drivers/net/mlx4/cq.c
  head/sys/ofed/drivers/net/mlx4/en_cq.c
  head/sys/ofed/drivers/net/mlx4/en_ethtool.c
  head/sys/ofed/drivers/net/mlx4/en_main.c
  head/sys/ofed/drivers/net/mlx4/en_netdev.c
  head/sys/ofed/drivers/net/mlx4/en_port.c
  head/sys/ofed/drivers/net/mlx4/en_port.h
  head/sys/ofed/drivers/net/mlx4/en_resources.c
  head/sys/ofed/drivers/net/mlx4/en_rx.c
  head/sys/ofed/drivers/net/mlx4/en_selftest.c
  head/sys/ofed/drivers/net/mlx4/en_tx.c
  head/sys/ofed/drivers/net/mlx4/eq.c
  head/sys/ofed/drivers/net/mlx4/fw.c
  head/sys/ofed/drivers/net/mlx4/fw.h
  head/sys/ofed/drivers/net/mlx4/icm.c
  head/sys/ofed/drivers/net/mlx4/icm.h
  head/sys/ofed/drivers/net/mlx4/intf.c
  head/sys/ofed/drivers/net/mlx4/main.c
  head/sys/ofed/drivers/net/mlx4/mcg.c
  head/sys/ofed/drivers/net/mlx4/mlx4.h
  head/sys/ofed/drivers/net/mlx4/mlx4_en.h
  head/sys/ofed/drivers/net/mlx4/mr.c
  head/sys/ofed/drivers/net/mlx4/pd.c
  head/sys/ofed/drivers/net/mlx4/port.c
  head/sys/ofed/drivers/net/mlx4/profile.c
  head/sys/ofed/drivers/net/mlx4/qp.c
  head/sys/ofed/drivers/net/mlx4/reset.c
  head/sys/ofed/drivers/net/mlx4/resource_tracker.c
  head/sys/ofed/drivers/net/mlx4/sense.c
  head/sys/ofed/drivers/net/mlx4/srq.c
  head/sys/ofed/drivers/net/mlx4/sys_tune.c
  head/sys/ofed/include/linux/mlx4/cmd.h
  head/sys/ofed/include/linux/mlx4/cq.h
  head/sys/ofed/include/linux/mlx4/device.h
  head/sys/ofed/include/linux/mlx4/driver.h
  head/sys/ofed/include/linux/mlx4/qp.h
  head/sys/ofed/include/linux/mlx4/srq.h

Modified: head/contrib/ofed/libibverbs/examples/asyncwatch.c
==============================================================================
--- head/contrib/ofed/libibverbs/examples/asyncwatch.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/contrib/ofed/libibverbs/examples/asyncwatch.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -35,8 +35,6 @@
 #endif /* HAVE_CONFIG_H */
 
 #include <stdio.h>
-#include <endian.h>
-#include <byteswap.h>
 
 #include <infiniband/verbs.h>
 

Modified: head/contrib/ofed/libibverbs/examples/device_list.c
==============================================================================
--- head/contrib/ofed/libibverbs/examples/device_list.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/contrib/ofed/libibverbs/examples/device_list.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -36,9 +36,6 @@
 
 #include <stdio.h>
 
-#include <endian.h>
-#include <byteswap.h>
-
 #include <infiniband/verbs.h>
 #include <infiniband/arch.h>
 

Modified: head/contrib/ofed/libibverbs/examples/devinfo.c
==============================================================================
--- head/contrib/ofed/libibverbs/examples/devinfo.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/contrib/ofed/libibverbs/examples/devinfo.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -41,8 +41,6 @@
 #include <string.h>
 #include <getopt.h>
 #include <netinet/in.h>
-#include <endian.h>
-#include <byteswap.h>
 
 #include <infiniband/verbs.h>
 #include <infiniband/driver.h>

Modified: head/contrib/ofed/libmlx4/src/mlx4-abi.h
==============================================================================
--- head/contrib/ofed/libmlx4/src/mlx4-abi.h	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/contrib/ofed/libmlx4/src/mlx4-abi.h	Tue Sep 23 12:37:01 2014	(r272027)
@@ -36,7 +36,7 @@
 #include <infiniband/kern-abi.h>
 
 #define MLX4_UVERBS_MIN_ABI_VERSION	2
-#define MLX4_UVERBS_MAX_ABI_VERSION	3
+#define MLX4_UVERBS_MAX_ABI_VERSION	4
 
 struct mlx4_alloc_ucontext_resp {
 	struct ibv_get_context_resp	ibv_resp;

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/conf/files	Tue Sep 23 12:37:01 2014	(r272027)
@@ -3781,7 +3781,7 @@ ofed/drivers/net/mlx4/sys_tune.c		option
 ofed/drivers/net/mlx4/en_cq.c			optional mlxen		\
 	no-depend obj-prefix "mlx4_"					\
 	compile-with "${OFED_C_NOIMP} -I$S/ofed/drivers/net/mlx4/"
-ofed/drivers/net/mlx4/en_frag.c			optional mlxen		\
+ofed/drivers/net/mlx4/utils.c			optional mlxen		\
 	no-depend obj-prefix "mlx4_"					\
 	compile-with "${OFED_C_NOIMP} -I$S/ofed/drivers/net/mlx4/"
 ofed/drivers/net/mlx4/en_main.c			optional mlxen		\

Modified: head/sys/modules/mlx4/Makefile
==============================================================================
--- head/sys/modules/mlx4/Makefile	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/modules/mlx4/Makefile	Tue Sep 23 12:37:01 2014	(r272027)
@@ -2,7 +2,7 @@
 .PATH:  ${.CURDIR}/../../ofed/drivers/net/mlx4
 .PATH:  ${.CURDIR}/../../ofed/include/linux
 KMOD    = mlx4
-SRCS    = device_if.h bus_if.h pci_if.h vnode_if.h
+SRCS    = device_if.h bus_if.h pci_if.h vnode_if.h opt_inet.h opt_inet6.h
 SRCS+= alloc.c catas.c cmd.c cq.c eq.c fw.c icm.c intf.c main.c mcg.c mr.c linux_compat.c linux_radix.c	linux_idr.c
 SRCS+=	pd.c port.c profile.c qp.c reset.c sense.c srq.c resource_tracker.c sys_tune.c
 

Modified: head/sys/modules/mlxen/Makefile
==============================================================================
--- head/sys/modules/mlxen/Makefile	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/modules/mlxen/Makefile	Tue Sep 23 12:37:01 2014	(r272027)
@@ -3,8 +3,8 @@
 
 KMOD    = mlxen
 SRCS    = device_if.h bus_if.h pci_if.h vnode_if.h
-SRCS	+= en_cq.c en_frag.c en_main.c en_netdev.c en_port.c en_resources.c
-SRCS	+= en_rx.c en_tx.c
+SRCS	+= en_cq.c en_main.c en_netdev.c en_port.c en_resources.c
+SRCS	+= en_rx.c en_tx.c utils.c
 SRCS	+= opt_inet.h opt_inet6.h
 CFLAGS+= -I${.CURDIR}/../../ofed/drivers/net/mlx4
 CFLAGS+= -I${.CURDIR}/../../ofed/include/

Modified: head/sys/ofed/drivers/infiniband/hw/mlx4/mad.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/hw/mlx4/mad.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/infiniband/hw/mlx4/mad.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -1081,7 +1081,7 @@ static void handle_lid_change_event(stru
 
 	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down)
 		mlx4_gen_slaves_port_mgt_ev(dev->dev, port_num,
-					    MLX4_EQ_PORT_INFO_LID_CHANGE_MASK);
+					    MLX4_EQ_PORT_INFO_LID_CHANGE_MASK, 0, 0);
 }
 
 static void handle_client_rereg_event(struct mlx4_ib_dev *dev, u8 port_num)
@@ -1093,7 +1093,7 @@ static void handle_client_rereg_event(st
 		if (!dev->sriov.is_going_down) {
 			mlx4_ib_mcg_port_cleanup(&dev->sriov.demux[port_num - 1], 0);
 			mlx4_gen_slaves_port_mgt_ev(dev->dev, port_num,
-						    MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK);
+						    MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK, 0, 0);
 		}
 	}
 	mlx4_ib_dispatch_event(dev, port_num, IB_EVENT_CLIENT_REREGISTER);
@@ -1191,7 +1191,7 @@ void handle_port_mgmt_change_event(struc
 			/*if master, notify all slaves*/
 			if (mlx4_is_master(dev->dev))
 				mlx4_gen_slaves_port_mgt_ev(dev->dev, port,
-							    MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK);
+							    MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK, 0, 0);
 		}
 
 		if (changed_attr & MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK)

Modified: head/sys/ofed/drivers/infiniband/hw/mlx4/main.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/hw/mlx4/main.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/infiniband/hw/mlx4/main.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -1005,7 +1005,7 @@ static int flow_spec_to_net_rule(struct 
 	case IB_FLOW_IB_UC:
 		spec_l2->id = MLX4_NET_TRANS_RULE_ID_IB;
 		if(flow_spec->l2_id.ib_uc.qpn) {
-			spec_l2->ib.r_u_qpn = cpu_to_be32(flow_spec->l2_id.ib_uc.qpn);
+			spec_l2->ib.l3_qpn = cpu_to_be32(flow_spec->l2_id.ib_uc.qpn);
 			spec_l2->ib.qpn_msk = cpu_to_be32(0xffffff);
                     }
 		break;
@@ -2013,7 +2013,7 @@ static void *mlx4_ib_add(struct mlx4_dev
 	for (i = 0; i < ibdev->num_ports; ++i) {
 		if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) ==
 						IB_LINK_LAYER_ETHERNET) {
-			err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]);
+			err = mlx4_counter_alloc(ibdev->dev, i + 1, &ibdev->counters[i]);
 			if (err)
 				ibdev->counters[i] = -1;
 		} else
@@ -2112,7 +2112,7 @@ err_steer_qp_release:
 err_counter:
 	for (; i; --i)
 		if (ibdev->counters[i - 1] != -1)
-			mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+			mlx4_counter_free(ibdev->dev, i, ibdev->counters[i - 1]);
 
 err_map:
 	iounmap(ibdev->priv_uar.map);
@@ -2200,7 +2200,7 @@ static void mlx4_ib_remove(struct mlx4_d
 	iounmap(ibdev->priv_uar.map);
 	for (p = 0; p < ibdev->num_ports; ++p)
 		if (ibdev->counters[p] != -1)
-			mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
+			mlx4_counter_free(ibdev->dev, p + 1, ibdev->counters[p]);
 	mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
 		mlx4_CLOSE_PORT(dev, p);
 

Modified: head/sys/ofed/drivers/infiniband/hw/mlx4/qp.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/hw/mlx4/qp.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/infiniband/hw/mlx4/qp.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -2679,10 +2679,10 @@ static int mlx4_wq_overflow(struct mlx4_
 
 static __be32 convert_access(int acc)
 {
-	return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC)       : 0) |
-	       (acc & IB_ACCESS_REMOTE_WRITE  ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) |
-	       (acc & IB_ACCESS_REMOTE_READ   ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ)  : 0) |
-	       (acc & IB_ACCESS_LOCAL_WRITE   ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE)  : 0) |
+	return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC)		: 0) |
+	       (acc & IB_ACCESS_REMOTE_WRITE  ? cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE)	: 0) |
+	       (acc & IB_ACCESS_REMOTE_READ   ? cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ)	: 0) |
+	       (acc & IB_ACCESS_LOCAL_WRITE   ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE)  		: 0) |
 		cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
 }
 
@@ -2709,10 +2709,12 @@ static void set_fmr_seg(struct mlx4_wqe_
 
 static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
 {
-	iseg->flags	= 0;
-	iseg->mem_key	= cpu_to_be32(rkey);
-	iseg->guest_id	= 0;
-	iseg->pa	= 0;
+	iseg->mem_key = cpu_to_be32(rkey);
+
+	iseg->reserved1    = 0;
+	iseg->reserved2    = 0;
+	iseg->reserved3[0] = 0;
+	iseg->reserved3[1] = 0;
 }
 
 static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg,

Modified: head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -240,7 +240,7 @@ ipoib_ib_handle_rx_wc(struct ipoib_dev_p
 	 */
 	if (unlikely(!ipoib_alloc_rx_mb(priv, wr_id))) {
 		memcpy(&priv->rx_ring[wr_id], &saverx, sizeof(saverx));
-		dev->if_iqdrops++;
+		if_inc_counter(dev, IFCOUNTER_IQDROPS, 1);
 		goto repost;
 	}
 

Modified: head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -745,7 +745,7 @@ ipoib_vlan_start(struct ifnet *dev)
 		if (mb == NULL)
 			break;
 		m_freem(mb);
-		dev->if_oerrors++;
+		if_inc_counter(dev, IFCOUNTER_OERRORS, 1);
 	}
 }
 
@@ -1452,7 +1452,7 @@ ipoib_input(struct ifnet *ifp, struct mb
 			m->m_flags |= M_BCAST;
 		else
 			m->m_flags |= M_MCAST;
-		ifp->if_imcasts++;
+		if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1);
 	}
 
 	ipoib_demux(ifp, m, ntohs(eh->proto));

Modified: head/sys/ofed/drivers/net/mlx4/alloc.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/alloc.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/net/mlx4/alloc.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,7 +34,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/bitops.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 
@@ -70,9 +70,9 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap
 	return obj;
 }
 
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
+void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr)
 {
-	mlx4_bitmap_free_range(bitmap, obj, 1);
+	mlx4_bitmap_free_range(bitmap, obj, 1, use_rr);
 }
 
 static unsigned long find_aligned_range(unsigned long *bitmap,
@@ -148,11 +148,17 @@ u32 mlx4_bitmap_avail(struct mlx4_bitmap
 	return bitmap->avail;
 }
 
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
+			    int use_rr)
 {
 	obj &= bitmap->max + bitmap->reserved_top - 1;
 
 	spin_lock(&bitmap->lock);
+	if (!use_rr) {
+		bitmap->last = min(bitmap->last, obj);
+		bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
+				& bitmap->mask;
+	}
 	bitmap_clear(bitmap->table, obj, cnt);
 	bitmap->avail += cnt;
 	spin_unlock(&bitmap->lock);

Modified: head/sys/ofed/drivers/net/mlx4/catas.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/catas.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/net/mlx4/catas.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,10 +34,11 @@
 #include <linux/workqueue.h>
 #include <linux/module.h>
 
-#include "mlx4.h"
+#include <asm/byteorder.h>
 
-#define MLX4_CATAS_POLL_INTERVAL        (5 * HZ)
+#include "mlx4.h"
 
+#define 	MLX4_CATAS_POLL_INTERVAL	(5 * HZ)
 
 static DEFINE_SPINLOCK(catas_lock);
 
@@ -156,11 +157,13 @@ void mlx4_stop_catas_poll(struct mlx4_de
 
 	del_timer_sync(&priv->catas_err.timer);
 
-	if (priv->catas_err.map)
+	if (priv->catas_err.map) {
 		iounmap(priv->catas_err.map);
+		priv->catas_err.map = NULL;
+	}
 
 	spin_lock_irq(&catas_lock);
-	list_del(&priv->catas_err.list);
+	list_del_init(&priv->catas_err.list);
 	spin_unlock_irq(&catas_lock);
 }
 

Modified: head/sys/ofed/drivers/net/mlx4/cmd.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/cmd.c	Tue Sep 23 11:41:09 2014	(r272026)
+++ head/sys/ofed/drivers/net/mlx4/cmd.c	Tue Sep 23 12:37:01 2014	(r272027)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -34,14 +34,17 @@
 
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/errno.h>
 
 #include <linux/mlx4/cmd.h>
+#include <linux/mlx4/device.h>
 #include <linux/semaphore.h>
 #include <rdma/ib_smi.h>
 
 #include <asm/io.h>
+#include <linux/ktime.h>
 
 #include "mlx4.h"
 #include "fw.h"
@@ -110,6 +113,14 @@ enum {
 	GO_BIT_TIMEOUT_MSECS	= 10000
 };
 
+enum mlx4_vlan_transition {
+	MLX4_VLAN_TRANSITION_VST_VST = 0,
+	MLX4_VLAN_TRANSITION_VST_VGT = 1,
+	MLX4_VLAN_TRANSITION_VGT_VST = 2,
+	MLX4_VLAN_TRANSITION_VGT_VGT = 3,
+};
+
+
 struct mlx4_cmd_context {
 	struct completion	done;
 	int			result;
@@ -152,6 +163,131 @@ static int mlx4_status_to_errno(u8 statu
 	return trans_table[status];
 }
 
+static const char *cmd_to_str(u16 cmd)
+{
+	switch (cmd) {
+	case MLX4_CMD_SYS_EN:		return "SYS_EN";
+	case MLX4_CMD_SYS_DIS:		return "SYS_DIS";
+	case MLX4_CMD_MAP_FA:		return "MAP_FA";
+	case MLX4_CMD_UNMAP_FA:		return "UNMAP_FA";
+	case MLX4_CMD_RUN_FW:		return "RUN_FW";
+	case MLX4_CMD_MOD_STAT_CFG:	return "MOD_STAT_CFG";
+	case MLX4_CMD_QUERY_DEV_CAP:	return "QUERY_DEV_CAP";
+	case MLX4_CMD_QUERY_FW:		return "QUERY_FW";
+	case MLX4_CMD_ENABLE_LAM:	return "ENABLE_LAM";
+	case MLX4_CMD_DISABLE_LAM:	return "DISABLE_LAM";
+	case MLX4_CMD_QUERY_DDR:	return "QUERY_DDR";
+	case MLX4_CMD_QUERY_ADAPTER:	return "QUERY_ADAPTER";
+	case MLX4_CMD_INIT_HCA:		return "INIT_HCA";
+	case MLX4_CMD_CLOSE_HCA:	return "CLOSE_HCA";
+	case MLX4_CMD_INIT_PORT:	return "INIT_PORT";
+	case MLX4_CMD_CLOSE_PORT:	return "CLOSE_PORT";
+	case MLX4_CMD_QUERY_HCA:	return "QUERY_HCA";
+	case MLX4_CMD_QUERY_PORT:	return "QUERY_PORT";
+	case MLX4_CMD_SENSE_PORT:	return "SENSE_PORT";
+	case MLX4_CMD_HW_HEALTH_CHECK:  return "HW_HEALTH_CHECK";
+	case MLX4_CMD_SET_PORT:		return "SET_PORT";
+	case MLX4_CMD_SET_NODE:		return "SET_NODE";
+	case MLX4_CMD_QUERY_FUNC:	return "QUERY_FUNC";
+	case MLX4_CMD_MAP_ICM:		return "MAP_ICM";
+	case MLX4_CMD_UNMAP_ICM:	return "UNMAP_ICM";
+	case MLX4_CMD_MAP_ICM_AUX:	return "MAP_ICM_AUX";
+	case MLX4_CMD_UNMAP_ICM_AUX:	return "UNMAP_ICM_AUX";
+	case MLX4_CMD_SET_ICM_SIZE:	return "SET_ICM_SIZE";
+		/*master notify fw on finish for slave's flr*/
+	case MLX4_CMD_INFORM_FLR_DONE:	return "INFORM_FLR_DONE";
+	case MLX4_CMD_GET_OP_REQ:	return "GET_OP_REQ";
+
+		/* TPT commands */
+	case MLX4_CMD_SW2HW_MPT:	return "SW2HW_MPT";
+	case MLX4_CMD_QUERY_MPT:	return "QUERY_MPT";
+	case MLX4_CMD_HW2SW_MPT:	return "HW2SW_MPT";
+	case MLX4_CMD_READ_MTT:		return "READ_MTT";
+	case MLX4_CMD_WRITE_MTT:	return "WRITE_MTT";
+	case MLX4_CMD_SYNC_TPT:		return "SYNC_TPT";
+
+		/* EQ commands */
+	case MLX4_CMD_MAP_EQ:		return "MAP_EQ";
+	case MLX4_CMD_SW2HW_EQ:		return "SW2HW_EQ";
+	case MLX4_CMD_HW2SW_EQ:		return "HW2SW_EQ";
+	case MLX4_CMD_QUERY_EQ:		return "QUERY_EQ";
+
+		/* CQ commands */
+	case MLX4_CMD_SW2HW_CQ:		return "SW2HW_CQ";
+	case MLX4_CMD_HW2SW_CQ:		return "HW2SW_CQ";
+	case MLX4_CMD_QUERY_CQ:		return "QUERY_CQ:";
+	case MLX4_CMD_MODIFY_CQ:	return "MODIFY_CQ:";
+
+		/* SRQ commands */
+	case MLX4_CMD_SW2HW_SRQ:	return "SW2HW_SRQ";
+	case MLX4_CMD_HW2SW_SRQ:	return "HW2SW_SRQ";
+	case MLX4_CMD_QUERY_SRQ:	return "QUERY_SRQ";
+	case MLX4_CMD_ARM_SRQ:		return "ARM_SRQ";
+
+		/* QP/EE commands */
+	case MLX4_CMD_RST2INIT_QP:	return "RST2INIT_QP";
+	case MLX4_CMD_INIT2RTR_QP:	return "INIT2RTR_QP";
+	case MLX4_CMD_RTR2RTS_QP:	return "RTR2RTS_QP";
+	case MLX4_CMD_RTS2RTS_QP:	return "RTS2RTS_QP";
+	case MLX4_CMD_SQERR2RTS_QP:	return "SQERR2RTS_QP";
+	case MLX4_CMD_2ERR_QP:		return "2ERR_QP";
+	case MLX4_CMD_RTS2SQD_QP:	return "RTS2SQD_QP";
+	case MLX4_CMD_SQD2SQD_QP:	return "SQD2SQD_QP";
+	case MLX4_CMD_SQD2RTS_QP:	return "SQD2RTS_QP";
+	case MLX4_CMD_2RST_QP:		return "2RST_QP";
+	case MLX4_CMD_QUERY_QP:		return "QUERY_QP";
+	case MLX4_CMD_INIT2INIT_QP:	return "INIT2INIT_QP";
+	case MLX4_CMD_SUSPEND_QP:	return "SUSPEND_QP";
+	case MLX4_CMD_UNSUSPEND_QP:	return "UNSUSPEND_QP";
+		/* special QP and management commands */
+	case MLX4_CMD_CONF_SPECIAL_QP:	return "CONF_SPECIAL_QP";
+	case MLX4_CMD_MAD_IFC:		return "MAD_IFC";
+
+		/* multicast commands */
+	case MLX4_CMD_READ_MCG:		return "READ_MCG";
+	case MLX4_CMD_WRITE_MCG:	return "WRITE_MCG";
+	case MLX4_CMD_MGID_HASH:	return "MGID_HASH";
+
+		/* miscellaneous commands */
+	case MLX4_CMD_DIAG_RPRT:	return "DIAG_RPRT";
+	case MLX4_CMD_NOP:		return "NOP";
+	case MLX4_CMD_ACCESS_MEM:	return "ACCESS_MEM";
+	case MLX4_CMD_SET_VEP:		return "SET_VEP";
+
+		/* Ethernet specific commands */
+	case MLX4_CMD_SET_VLAN_FLTR:	return "SET_VLAN_FLTR";
+	case MLX4_CMD_SET_MCAST_FLTR:	return "SET_MCAST_FLTR";
+	case MLX4_CMD_DUMP_ETH_STATS:	return "DUMP_ETH_STATS";
+
+		/* Communication channel commands */
+	case MLX4_CMD_ARM_COMM_CHANNEL:	return "ARM_COMM_CHANNEL";
+	case MLX4_CMD_GEN_EQE:		return "GEN_EQE";
+
+		/* virtual commands */
+	case MLX4_CMD_ALLOC_RES:	return "ALLOC_RES";
+	case MLX4_CMD_FREE_RES:		return "FREE_RES";
+	case MLX4_CMD_MCAST_ATTACH:	return "MCAST_ATTACH";
+	case MLX4_CMD_UCAST_ATTACH:	return "UCAST_ATTACH";
+	case MLX4_CMD_PROMISC:		return "PROMISC";
+	case MLX4_CMD_QUERY_FUNC_CAP:	return "QUERY_FUNC_CAP";
+	case MLX4_CMD_QP_ATTACH:	return "QP_ATTACH";
+
+		/* debug commands */
+	case MLX4_CMD_QUERY_DEBUG_MSG:	return "QUERY_DEBUG_MSG";
+	case MLX4_CMD_SET_DEBUG_MSG:	return "SET_DEBUG_MSG";
+
+		/* statistics commands */
+	case MLX4_CMD_QUERY_IF_STAT:	return "QUERY_IF_STAT";
+	case MLX4_CMD_SET_IF_STAT:	return "SET_IF_STAT";
+
+		/* register/delete flow steering network rules */
+	case MLX4_QP_FLOW_STEERING_ATTACH:	return "QP_FLOW_STEERING_ATTACH";
+	case MLX4_QP_FLOW_STEERING_DETACH:	return "QP_FLOW_STEERING_DETACH";
+	case MLX4_FLOW_STEERING_IB_UC_QP_RANGE:	return "FLOW_STEERING_IB_UC_QP_RANGE";
+	default: return "OTHER";
+	}
+}
+
 static u8 mlx4_errno_to_status(int errno)
 {
 	switch (errno) {
@@ -244,6 +380,17 @@ static int mlx4_comm_cmd_wait(struct mlx
 
 	down(&cmd->event_sem);
 
+	end = msecs_to_jiffies(timeout) + jiffies;
+	while (comm_pending(dev) && time_before(jiffies, end))
+		cond_resched();
+	if (comm_pending(dev)) {
+		mlx4_warn(dev, "mlx4_comm_cmd_wait: Comm channel "
+			  "is not idle. My toggle is %d (op: 0x%x)\n",
+			  mlx4_priv(dev)->cmd.comm_toggle, op);
+		up(&cmd->event_sem);
+		return -EAGAIN;
+	}
+
 	spin_lock(&cmd->context_lock);
 	BUG_ON(cmd->free_head < 0);
 	context = &cmd->context[cmd->free_head];
@@ -255,12 +402,8 @@ static int mlx4_comm_cmd_wait(struct mlx
 
 	mlx4_comm_cmd_post(dev, op, param);
 
-	if (!wait_for_completion_timeout(&context->done,
-					 msecs_to_jiffies(timeout))) {
-		mlx4_warn(dev, "communication channel command 0x%x timed out\n", op);
-		err = -EBUSY;
-		goto out;
-	}
+	/* In slave, wait unconditionally for completion */
+	wait_for_completion(&context->done);
 
 	err = context->result;
 	if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) {
@@ -309,14 +452,29 @@ static int cmd_pending(struct mlx4_dev *
 		 !!(status & swab32(1 << HCR_T_BIT)));
 }
 
-static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param,
-			 u32 in_modifier, u8 op_modifier, u16 op, u16 token,
-			 int event)
+static int get_status(struct mlx4_dev *dev, u32 *status, int *go_bit,
+		      int *t_bit)
+{
+	if (pci_channel_offline(dev->pdev))
+		return -EIO;
+
+	*status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
+	*t_bit = !!(*status & swab32(1 << HCR_T_BIT));
+	*go_bit = !!(*status & swab32(1 << HCR_GO_BIT));
+
+	return 0;
+}
+
+static int mlx4_cmd_post(struct mlx4_dev *dev, struct timespec *ts1,
+			 u64 in_param, u64 out_param, u32 in_modifier,
+			 u8 op_modifier, u16 op, u16 token, int event)
 {
 	struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
 	u32 __iomem *hcr = cmd->hcr;
 	int ret = -EAGAIN;
 	unsigned long end;
+	int err, go_bit = 0, t_bit = 0;
+	u32 status = 0;
 
 	mutex_lock(&cmd->hcr_mutex);
 
@@ -363,6 +521,9 @@ static int mlx4_cmd_post(struct mlx4_dev
 	__raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4);
 	__raw_writel((__force u32) cpu_to_be32(token << 16),		  hcr + 5);
 
+	if (ts1)
+		ktime_get_ts(ts1);
+
 	/* __raw_writel may not order writes. */
 	wmb();
 
@@ -383,6 +544,15 @@ static int mlx4_cmd_post(struct mlx4_dev
 	ret = 0;
 
 out:
+	if (ret) {
+		err = get_status(dev, &status, &go_bit, &t_bit);
+		mlx4_warn(dev, "Could not post command %s (0x%x): ret=%d, "
+			  "in_param=0x%llx, in_mod=0x%x, op_mod=0x%x, "
+			  "get_status err=%d, status_reg=0x%x, go_bit=%d, "
+			  "t_bit=%d, toggle=0x%x\n", cmd_to_str(op), op, ret,
+			  (unsigned long long) in_param, in_modifier, op_modifier, err, status,
+			  go_bit, t_bit, cmd->toggle);
+	}
 	mutex_unlock(&cmd->hcr_mutex);
 	return ret;
 }
@@ -439,7 +609,7 @@ static int mlx4_slave_cmd(struct mlx4_de
 			ret = mlx4_status_to_errno(vhcr->status);
 		} else
 			mlx4_err(dev, "failed execution of VHCR_POST command"
-				 "opcode 0x%x\n", op);
+				 "opcode %s (0x%x)\n", cmd_to_str(op), op);
 	}
 
 	mutex_unlock(&priv->cmd.slave_cmd_mutex);
@@ -467,7 +637,7 @@ static int mlx4_cmd_poll(struct mlx4_dev
 		goto out;
 	}
 
-	err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0,
+	err = mlx4_cmd_post(dev, NULL, in_param, out_param ? *out_param : 0,
 			    in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0);
 	if (err)
 		goto out;
@@ -487,7 +657,8 @@ static int mlx4_cmd_poll(struct mlx4_dev
 	}
 
 	if (cmd_pending(dev)) {
-		mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", op);
+		mlx4_warn(dev, "command %s (0x%x) timed out (go bit not cleared)\n",
+			  cmd_to_str(op), op);
 		err = -ETIMEDOUT;
 		goto out;
 	}
@@ -502,8 +673,8 @@ static int mlx4_cmd_poll(struct mlx4_dev
 			   __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24;
 	err = mlx4_status_to_errno(stat);
 	if (err)
-		mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n",
-			 op, stat);
+		mlx4_err(dev, "command %s (0x%x) failed: fw status = 0x%x\n",
+			 cmd_to_str(op), op, stat);
 
 out:
 	up(&priv->cmd.poll_sem);
@@ -527,19 +698,6 @@ void mlx4_cmd_event(struct mlx4_dev *dev
 	complete(&context->done);
 }
 
-static int get_status(struct mlx4_dev *dev, u32 *status, int *go_bit,
-		      int *t_bit)
-{
-	if (pci_channel_offline(dev->pdev))
-		return -EIO;
-
-	*status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
-	*t_bit = !!(*status & swab32(1 << HCR_T_BIT));
-	*go_bit = !!(*status & swab32(1 << HCR_GO_BIT));
-
-	return 0;
-}
-
 static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
 			 int out_is_imm, u32 in_modifier, u8 op_modifier,
 			 u16 op, unsigned long timeout)
@@ -549,6 +707,12 @@ static int mlx4_cmd_wait(struct mlx4_dev
 	int err = 0;
 	int go_bit = 0, t_bit = 0, stat_err;
 	u32 status = 0;
+	struct timespec	ts1, ts2;
+	ktime_t t1, t2, delta;
+	s64 ds;
+
+	if (out_is_imm && !out_param)
+		return -EINVAL;
 
 	down(&cmd->event_sem);
 
@@ -561,29 +725,38 @@ static int mlx4_cmd_wait(struct mlx4_dev
 
 	init_completion(&context->done);
 
-	err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0,
+	err = mlx4_cmd_post(dev, &ts1, in_param, out_param ? *out_param : 0,
 			    in_modifier, op_modifier, op, context->token, 1);
-	if (err) {
-		mlx4_warn(dev, "command 0x%x could not be posted (%d)\n",
-			  op, err);
+	if (err)
 		goto out;
-	}
 
 	if (!wait_for_completion_timeout(&context->done,
 					 msecs_to_jiffies(timeout))) {
 		stat_err = get_status(dev, &status, &go_bit, &t_bit);
-		mlx4_warn(dev, "command 0x%x timed out: "
-			  "get_status err=%d, status=0x%x, go_bit=%d, "
-			  "t_bit=%d, toggle=0x%x\n", op, stat_err, status,
-			  go_bit, t_bit, mlx4_priv(dev)->cmd.toggle);
+		mlx4_warn(dev, "command %s (0x%x) timed out: in_param=0x%llx, "
+			  "in_mod=0x%x, op_mod=0x%x, get_status err=%d, "
+			  "status_reg=0x%x, go_bit=%d, t_bit=%d, toggle=0x%x\n"
+			  , cmd_to_str(op), op, (unsigned long long) in_param, in_modifier,
+			  op_modifier, stat_err, status, go_bit, t_bit,
+			  mlx4_priv(dev)->cmd.toggle);
 		err = -EBUSY;
 		goto out;
 	}
+	if (mlx4_debug_level & MLX4_DEBUG_MASK_CMD_TIME) {
+		ktime_get_ts(&ts2);
+		t1 = timespec_to_ktime(ts1);
+		t2 = timespec_to_ktime(ts2);
+		delta = ktime_sub(t2, t1);
+		ds = ktime_to_ns(delta);
+		pr_info("mlx4: fw exec time for %s is %lld nsec\n", cmd_to_str(op), (long long) ds);
+	}
 
 	err = context->result;
 	if (err) {
-		mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n",
-			 op, context->fw_status);
+		mlx4_err(dev, "command %s (0x%x) failed: in_param=0x%llx, "
+			 "in_mod=0x%x, op_mod=0x%x, fw status = 0x%x\n",
+			 cmd_to_str(op), op, (unsigned long long) in_param, in_modifier,
+			 op_modifier, context->fw_status);
 		goto out;
 	}
 
@@ -640,7 +813,7 @@ static int mlx4_ACCESS_MEM(struct mlx4_d
 	    (slave & ~0x7f) | (size & 0xff)) {
 		mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx "
 			      "master_addr:0x%llx slave_id:%d size:%d\n",
-			      (long long)slave_addr, (long long)master_addr, slave, size);
+			      (unsigned long long) slave_addr, (unsigned long long) master_addr, slave, size);
 		return -EINVAL;
 	}
 
@@ -813,6 +986,24 @@ static int mlx4_MAD_IFC_wrapper(struct m
 				    vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
 }
 
+static int MLX4_CMD_DIAG_RPRT_wrapper(struct mlx4_dev *dev, int slave,
+		     struct mlx4_vhcr *vhcr,
+		     struct mlx4_cmd_mailbox *inbox,
+		     struct mlx4_cmd_mailbox *outbox,
+		     struct mlx4_cmd_info *cmd)
+{
+	return -EPERM;
+}
+
+static int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+		     struct mlx4_vhcr *vhcr,
+		     struct mlx4_cmd_mailbox *inbox,
+		     struct mlx4_cmd_mailbox *outbox,
+		     struct mlx4_cmd_info *cmd)
+{
+	return -EPERM;
+}
+
 int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
 		     struct mlx4_vhcr *vhcr,
 		     struct mlx4_cmd_mailbox *inbox,
@@ -950,6 +1141,16 @@ static struct mlx4_cmd_info cmd_info[] =
 		.wrapper = NULL
 	},
 	{
+		.opcode = MLX4_CMD_DIAG_RPRT,
+		.has_inbox = false,
+		.has_outbox = false,
+		.out_is_imm = false,
+		.encode_slave_id = false,
+		.skip_err_print = true,
+		.verify = NULL,
+		.wrapper = MLX4_CMD_DIAG_RPRT_wrapper
+	},
+	{
 		.opcode = MLX4_CMD_NOP,
 		.has_inbox = false,
 		.has_outbox = false,
@@ -1247,6 +1448,16 @@ static struct mlx4_cmd_info cmd_info[] =
 		.wrapper = mlx4_GEN_QP_wrapper
 	},
 	{
+		.opcode = MLX4_CMD_UPDATE_QP,
+		.has_inbox = false,
+		.has_outbox = false,
+		.out_is_imm = false,
+		.encode_slave_id = false,
+		.skip_err_print = true,
+		.verify = NULL,
+		.wrapper = MLX4_CMD_UPDATE_QP_wrapper
+	},
+	{
 		.opcode = MLX4_CMD_CONF_SPECIAL_QP,
 		.has_inbox = false,
 		.has_outbox = false,
@@ -1348,6 +1559,17 @@ static struct mlx4_cmd_info cmd_info[] =
 		.verify = NULL,
 		.wrapper = mlx4_QP_FLOW_STEERING_DETACH_wrapper
 	},
+	/* wol commands */
+	{
+		.opcode = MLX4_CMD_MOD_STAT_CFG,
+		.has_inbox = false,
+		.has_outbox = false,
+		.out_is_imm = false,
+		.encode_slave_id = false,
+		.skip_err_print = true,
+		.verify = NULL,
+		.wrapper = mlx4_MOD_STAT_CFG_wrapper
+	},
 };
 
 static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
@@ -1401,8 +1623,8 @@ static int mlx4_master_process_vhcr(stru
 		}
 	}
 	if (!cmd) {
-		mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n",
-			 vhcr->op, slave);
+		mlx4_err(dev, "unparavirt command: %s (0x%x) accepted from slave:%d\n",
+			 cmd_to_str(vhcr->op), vhcr->op, slave);
 		vhcr_cmd->status = CMD_STAT_BAD_PARAM;
 		goto out_status;
 	}
@@ -1420,8 +1642,8 @@ static int mlx4_master_process_vhcr(stru
 		if (mlx4_ACCESS_MEM(dev, inbox->dma, slave,
 				    vhcr->in_param,
 				    MLX4_MAILBOX_SIZE, 1)) {
-			mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n",
-				 __func__, cmd->opcode);
+			mlx4_err(dev, "%s: Failed reading inbox for cmd %s (0x%x)\n",
+				 __func__, cmd_to_str(cmd->opcode), cmd->opcode);
 			vhcr_cmd->status = CMD_STAT_INTERNAL_ERR;
 			goto out_status;
 		}
@@ -1429,9 +1651,9 @@ static int mlx4_master_process_vhcr(stru
 
 	/* Apply permission and bound checks if applicable */
 	if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) {
-		mlx4_warn(dev, "Command:0x%x from slave: %d failed protection "
-			  "checks for resource_id:%d\n", vhcr->op, slave,
-			  vhcr->in_modifier);
+		mlx4_warn(dev, "Command %s (0x%x) from slave: %d failed protection "
+			  "checks for resource_id: %d\n", cmd_to_str(vhcr->op),
+			  vhcr->op, slave, vhcr->in_modifier);
 		vhcr_cmd->status = CMD_STAT_BAD_OP;
 		goto out_status;
 	}
@@ -1470,9 +1692,13 @@ static int mlx4_master_process_vhcr(stru
 	}
 
 	if (err) {
-		mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with"
-			  " error:%d, status %d\n",
-			  vhcr->op, slave, vhcr->errno, err);
+		if (!cmd->skip_err_print)
+			mlx4_warn(dev, "vhcr command %s (0x%x) slave:%d "
+				  "in_param 0x%llx in_mod=0x%x, op_mod=0x%x "
+				  "failed with error:%d, status %d\n",
+				  cmd_to_str(vhcr->op), vhcr->op, slave,
+				  (unsigned long long) vhcr->in_param, vhcr->in_modifier,
+				  vhcr->op_modifier, vhcr->errno, err);
 		vhcr_cmd->status = mlx4_errno_to_status(err);
 		goto out_status;
 	}
@@ -1487,7 +1713,7 @@ static int mlx4_master_process_vhcr(stru
 			/* If we failed to write back the outbox after the
 			 *command was successfully executed, we must fail this
 			 * slave, as it is now in undefined state */
-			mlx4_err(dev, "%s:Failed writing outbox\n", __func__);
+			mlx4_err(dev, "%s: Failed writing outbox\n", __func__);
 			goto out;
 		}
 	}
@@ -1516,6 +1742,75 @@ out:
 	return ret;
 }
 
+static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
+					    int slave, int port)
+{
+	struct mlx4_vport_oper_state *vp_oper;
+	struct mlx4_vport_state *vp_admin;
+	struct mlx4_vf_immed_vlan_work *work;
+	int err;
+	int admin_vlan_ix = NO_INDX;
+
+	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+	vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
+
+	if (vp_oper->state.default_vlan == vp_admin->default_vlan &&
+	    vp_oper->state.default_qos == vp_admin->default_qos)
+		return 0;
+
+	work = kzalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	if (vp_oper->state.default_vlan != vp_admin->default_vlan) {
+		if (MLX4_VGT != vp_admin->default_vlan) {
+			err = __mlx4_register_vlan(&priv->dev, port,
+						   vp_admin->default_vlan,
+						   &admin_vlan_ix);
+			if (err) {
+				mlx4_warn((&priv->dev),
+					  "No vlan resources slave %d, port %d\n",
+					  slave, port);
+				return err;
+			}
+		} else {
+			admin_vlan_ix = NO_INDX;
+		}
+		work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN;
+		mlx4_dbg((&(priv->dev)),
+			 "alloc vlan %d idx  %d slave %d port %d\n",
+			 (int)(vp_admin->default_vlan),
+			 admin_vlan_ix, slave, port);
+	}
+
+	/* save original vlan ix and vlan id */
+	work->orig_vlan_id = vp_oper->state.default_vlan;
+	work->orig_vlan_ix = vp_oper->vlan_idx;
+
+	/* handle new qos */
+	if (vp_oper->state.default_qos != vp_admin->default_qos)
+		work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS;
+
+	if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN)
+		vp_oper->vlan_idx = admin_vlan_ix;
+
+	vp_oper->state.default_vlan = vp_admin->default_vlan;
+	vp_oper->state.default_qos = vp_admin->default_qos;
+
+	/* iterate over QPs owned by this slave, using UPDATE_QP */
+	work->port = port;
+	work->slave = slave;
+	work->qos = vp_oper->state.default_qos;
+	work->vlan_id = vp_oper->state.default_vlan;
+	work->vlan_ix = vp_oper->vlan_idx;
+	work->priv = priv;
+	INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler);
+	queue_work(priv->mfunc.master.comm_wq, &work->work);
+
+	return 0;
+}
+
+
 static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
 {
 	int port, err;
@@ -1527,7 +1822,7 @@ static int mlx4_master_activate_admin_st
 		vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
 		vp_oper->state = *vp_admin;
 		if (MLX4_VGT != vp_admin->default_vlan) {
-			err = mlx4_register_vlan(&priv->dev, port,
+			err = __mlx4_register_vlan(&priv->dev, port,
 						 vp_admin->default_vlan, &(vp_oper->vlan_idx));
 			if (err) {
 				vp_oper->vlan_idx = NO_INDX;
@@ -1548,12 +1843,12 @@ static int mlx4_master_activate_admin_st
 				err = vp_oper->mac_idx;
 				vp_oper->mac_idx = NO_INDX;
 				mlx4_warn((&priv->dev),
-					  "No mac resorces slave %d, port %d\n",
+					  "No mac resources slave %d, port %d\n",
 					  slave, port);
 				return err;
 			}
 			mlx4_dbg((&(priv->dev)), "alloc mac %llx idx  %d slave %d port %d\n",
-				 (long long)vp_oper->state.mac, vp_oper->mac_idx, slave, port);
+				 (unsigned long long) vp_oper->state.mac, vp_oper->mac_idx, slave, port);
 		}
 	}
 	return 0;
@@ -1599,6 +1894,7 @@ static void mlx4_master_do_cmd(struct ml
 	if (cmd == MLX4_COMM_CMD_RESET) {
 		mlx4_warn(dev, "Received reset from slave:%d\n", slave);
 		slave_state[slave].active = false;
+		slave_state[slave].old_vlan_api = false;
 		mlx4_master_deactivate_admin_state(priv, slave);
 		for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
 				slave_state[slave].event_eq[i].eqn = -1;
@@ -1619,7 +1915,7 @@ static void mlx4_master_do_cmd(struct ml
 	/*command from slave in the middle of FLR*/
 	if (cmd != MLX4_COMM_CMD_RESET &&
 	    MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
-		mlx4_warn(dev, "slave:%d is Trying to run cmd(0x%x) "
+		mlx4_warn(dev, "slave:%d is Trying to run cmd (0x%x) "
 			  "in the middle of FLR\n", slave, cmd);
 		return;
 	}
@@ -1630,7 +1926,6 @@ static void mlx4_master_do_cmd(struct ml
 			goto reset_slave;
 		slave_state[slave].vhcr_dma = ((u64) param) << 48;
 		priv->mfunc.master.slave_state[slave].cookie = 0;
-		mutex_init(&priv->mfunc.master.gen_eqe_mutex[slave]);
 		break;
 	case MLX4_COMM_CMD_VHCR1:
 		if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0)
@@ -1658,7 +1953,7 @@ static void mlx4_master_do_cmd(struct ml
 
 		mutex_lock(&priv->cmd.slave_cmd_mutex);
 		if (mlx4_master_process_vhcr(dev, slave, NULL)) {
-			mlx4_err(dev, "Failed processing vhcr for slave:%d,"
+			mlx4_err(dev, "Failed processing vhcr for slave: %d,"
 				 " resetting slave.\n", slave);
 			mutex_unlock(&priv->cmd.slave_cmd_mutex);
 			goto reset_slave;
@@ -1666,7 +1961,7 @@ static void mlx4_master_do_cmd(struct ml
 		mutex_unlock(&priv->cmd.slave_cmd_mutex);
 		break;
 	default:
-		mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave);
+		mlx4_warn(dev, "Bad comm cmd: %d from slave: %d\n", cmd, slave);
 		goto reset_slave;
 	}
 	spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
@@ -1676,8 +1971,8 @@ static void mlx4_master_do_cmd(struct ml
 		is_going_down = 1;
 	spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
 	if (is_going_down) {
-		mlx4_warn(dev, "Slave is going down aborting command(%d)"
-			  " executing from slave:%d\n",
+		mlx4_warn(dev, "Slave is going down aborting command (%d)"
+			  " executing from slave: %d\n",
 			  cmd, slave);
 		return;
 	}
@@ -1696,8 +1991,6 @@ reset_slave:
 	spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
 	/*with slave in the middle of flr, no need to clean resources again.*/
 inform_slave_state:
-	memset(&slave_state[slave].event_eq, 0,
-	       sizeof(struct mlx4_slave_event_eq_info));
 	__raw_writel((__force u32) cpu_to_be32(reply),
 		     &priv->mfunc.comm[slave].slave_read);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list