Index: linux/drivers/infiniband/hw/mlx4/main.c
===================================================================
--- linux.orig/drivers/infiniband/hw/mlx4/main.c
+++ linux/drivers/infiniband/hw/mlx4/main.c
@@ -2210,6 +2210,106 @@ static int mlx4_port_immutable(struct ib
 	return 0;
 }
 
+enum mlx4_diagnostic_counters {
+	MLX4_RQ_NUM_LLE,
+	MLX4_SQ_NUM_LLE,
+	MLX4_RQ_NUM_LQPOE,
+	MLX4_SQ_NUM_LQPOE,
+	MLX4_RQ_NUM_LPE,
+	MLX4_SQ_NUM_LPE,
+	MLX4_RQ_NUM_WRFE,
+	MLX4_SQ_NUM_WRFE,
+	MLX4_SQ_NUM_MWBE,
+	MLX4_SQ_NUM_BRE,
+	MLX4_RQ_NUM_LAE,
+	MLX4_SQ_NUM_RIRE,
+	MLX4_RQ_NUM_RIRE,
+	MLX4_SQ_NUM_RAE,
+	MLX4_RQ_NUM_RAE,
+	MLX4_SQ_NUM_ROE,
+	MLX4_SQ_NUM_TREE,
+	MLX4_SQ_NUM_RREE,
+	MLX4_RQ_NUM_RNR,
+	MLX4_SQ_NUM_RNR,
+	MLX4_RQ_NUM_OOS,
+	MLX4_SQ_NUM_OOS,
+	MLX4_RQ_NUM_MCE,
+	MLX4_RQ_NUM_UDSDPRD,
+	MLX4_RQ_NUM_UCSDPRD,
+	MLX4_NUM_CQOVF,
+	MLX4_NUM_EQOVF,
+	MLX4_NUM_BADDB,
+	MLX4_COUNTERS_NUM,
+};
+
+
+static char *mlx4_counter_names[] = {
+	"rq_num_lle",
+	"sq_num_lle",
+	"rq_num_lqpoe",
+	"sq_num_lqpoe",
+	"rq_num_lpe",
+	"sq_num_lpe",
+	"rq_num_wrfe",
+	"sq_num_wrfe",
+	"sq_num_mwbe",
+	"sq_num_bre",
+	"rq_num_lae",
+	"sq_num_rire",
+	"rq_num_rire",
+	"sq_num_rae",
+	"rq_num_rae",
+	"sq_num_roe",
+	"sq_num_tree",
+	"sq_num_rree",
+	"rq_num_rnr",
+	"sq_num_rnr",
+	"rq_num_oos",
+	"sq_num_oos",
+	"rq_num_mce",
+	"rq_num_udsdprd",
+	"rq_num_ucsdprd",
+	"num_cqovf",
+	"num_eqovf",
+	"num_baddb",
+	NULL
+};
+
+static int offsets[MLX4_COUNTERS_NUM] = {
+	0x00, 0x04, 0x08, 0x0C, 0x18, 0x1C, 0x20, 0x24,
+	0x2C, 0x34, 0x38, 0x44, 0x48, 0x4C, 0x50, 0x54,
+	0x5C, 0x64, 0x68, 0x6C, 0x100, 0x104, 0x108, 0x118,
+	0x120, 0x1A0, 0x1A4, 0x1A8 };
+
+static int mlx4_ib_show_stats(struct ib_device *ibdev,
+		struct rdma_protocol_stats *stats, u8 port)
+{
+	struct mlx4_ib_dev *dev;
+	int ret;
+
+	stats->name = mlx4_counter_names;
+	stats->dirname = "ib_stats";
+
+	/*
+	 * We should be checking for the port here and obtain
+	 * port specific counters if possible
+	 *
+	 *	if (port)
+	 *		{ Do port specific things }
+	 *
+	 */
+
+	dev = to_mdev(ibdev);
+	ret = mlx4_query_diag_counters(dev->dev, 2, offsets, stats->value,
+				       MLX4_COUNTERS_NUM);
+	if (ret) {
+		pr_err("%s: failed to read ib counters\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
 static void *mlx4_ib_add(struct mlx4_dev *dev)
 {
 	struct mlx4_ib_dev *ibdev;
@@ -2344,6 +2444,7 @@ static void *mlx4_ib_add(struct mlx4_dev
 	ibdev->ib_dev.process_mad	= mlx4_ib_process_mad;
 	ibdev->ib_dev.get_port_immutable = mlx4_port_immutable;
 	ibdev->ib_dev.disassociate_ucontext = mlx4_ib_disassociate_ucontext;
+	ibdev->ib_dev.get_protocol_stats = mlx4_ib_show_stats;
 
 	if (!mlx4_is_slave(ibdev->dev)) {
 		ibdev->ib_dev.alloc_fmr		= mlx4_ib_fmr_alloc;
Index: linux/drivers/net/ethernet/mellanox/mlx4/fw.c
===================================================================
--- linux.orig/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ linux/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -2453,6 +2453,41 @@ int mlx4_NOP(struct mlx4_dev *dev)
 			MLX4_CMD_NATIVE);
 }
 
+int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
+			     int *offsets, u64 *values,
+			     size_t array_len)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	u32 *outbox;
+	int ret;
+	int i;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	outbox = mailbox->buf;
+
+	ret = mlx4_cmd_box(dev, 0, mailbox->dma, 0, op_modifier,
+			   MLX4_CMD_DIAG_RPRT, MLX4_CMD_TIME_CLASS_A,
+			   MLX4_CMD_NATIVE);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < array_len; i++) {
+		if (offsets[i] > MLX4_MAILBOX_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		MLX4_GET(values[i], outbox, offsets[i]);
+	}
+
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mlx4_query_diag_counters);
+
 int mlx4_get_phys_port_id(struct mlx4_dev *dev)
 {
 	u8 port;
Index: linux/include/linux/mlx4/device.h
===================================================================
--- linux.orig/include/linux/mlx4/device.h
+++ linux/include/linux/mlx4/device.h
@@ -1369,6 +1369,8 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev
 		    u32 *lkey, u32 *rkey);
 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
 int mlx4_SYNC_TPT(struct mlx4_dev *dev);
+int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
+			     int *offsets, u64 *values, size_t array_len);
 int mlx4_test_interrupts(struct mlx4_dev *dev);
 u32 mlx4_get_eqs_per_port(struct mlx4_dev *dev, u8 port);
 bool mlx4_is_eq_vector_valid(struct mlx4_dev *dev, u8 port, int vector);
