[PATCH] IB/rxe: Make counters thread safe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Current rxe device counters are not thread safe.
When multiple QPs are used, they can be racy.
Make them thread safe by making it per cpu.

Fixes: 0b1e5b99a48b ("IB/rxe: Add port protocol stats")
Signed-off-by: Parav Pandit <parav@xxxxxxxxxxxx>
---
 drivers/infiniband/sw/rxe/rxe.c             | 17 +++++++++++++++++
 drivers/infiniband/sw/rxe/rxe_hw_counters.c | 17 +++++++++++++++--
 drivers/infiniband/sw/rxe/rxe_verbs.h       | 14 ++++++++++----
 3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
index 383e65c..722aca9 100644
--- a/drivers/infiniband/sw/rxe/rxe.c
+++ b/drivers/infiniband/sw/rxe/rxe.c
@@ -39,6 +39,17 @@
 MODULE_DESCRIPTION("Soft RDMA transport");
 MODULE_LICENSE("Dual BSD/GPL");
 
+static int rxe_init_stats(struct rxe_dev *rxe)
+{
+	rxe->pcpu_stats = alloc_percpu(struct rxe_stats);
+	return rxe->pcpu_stats ? 0 : -ENOMEM;
+}
+
+static void rxe_cleanup_stats(struct rxe_dev *rxe)
+{
+	free_percpu(rxe->pcpu_stats);
+}
+
 /* free resources for all ports on a device */
 static void rxe_cleanup_ports(struct rxe_dev *rxe)
 {
@@ -64,6 +75,7 @@ static void rxe_cleanup(struct rxe_dev *rxe)
 	rxe_pool_cleanup(&rxe->mc_elem_pool);
 
 	rxe_cleanup_ports(rxe);
+	rxe_cleanup_stats(rxe);
 
 	crypto_free_shash(rxe->tfm);
 }
@@ -267,6 +279,10 @@ static int rxe_init(struct rxe_dev *rxe)
 	/* init default device parameters */
 	rxe_init_device_param(rxe);
 
+	err = rxe_init_stats(rxe);
+	if (err)
+		return err;
+
 	err = rxe_init_ports(rxe);
 	if (err)
 		goto err1;
@@ -288,6 +304,7 @@ static int rxe_init(struct rxe_dev *rxe)
 err2:
 	rxe_cleanup_ports(rxe);
 err1:
+	rxe_cleanup_stats(rxe);
 	return err;
 }
 
diff --git a/drivers/infiniband/sw/rxe/rxe_hw_counters.c b/drivers/infiniband/sw/rxe/rxe_hw_counters.c
index 6aeb7a1..0fb567a 100644
--- a/drivers/infiniband/sw/rxe/rxe_hw_counters.c
+++ b/drivers/infiniband/sw/rxe/rxe_hw_counters.c
@@ -48,6 +48,19 @@
 	[RXE_CNT_SEND_ERR]            =  "send_err",
 };
 
+static u64 rxe_stats_read_by_index(const struct rxe_dev *dev, int index)
+{
+	struct rxe_stats *stats;
+	u64 sum = 0;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		stats = per_cpu_ptr(dev->pcpu_stats, cpu);
+		sum += stats->counters[index];
+	}
+	return sum;
+}
+
 int rxe_ib_get_hw_stats(struct ib_device *ibdev,
 			struct rdma_hw_stats *stats,
 			u8 port, int index)
@@ -58,8 +71,8 @@ int rxe_ib_get_hw_stats(struct ib_device *ibdev,
 	if (!port || !stats)
 		return -EINVAL;
 
-	for (cnt = 0; cnt  < ARRAY_SIZE(rxe_counter_name); cnt++)
-		stats->value[cnt] = dev->stats_counters[cnt];
+	for (cnt = 0; cnt < ARRAY_SIZE(rxe_counter_name); cnt++)
+		stats->value[cnt] = rxe_stats_read_by_index(dev, cnt);
 
 	return ARRAY_SIZE(rxe_counter_name);
 }
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index 82e670d..7daff30 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -380,6 +380,10 @@ struct rxe_port {
 	u32			qp_gsi_index;
 };
 
+struct rxe_stats {
+	u64	counters[RXE_NUM_OF_COUNTERS];
+};
+
 struct rxe_dev {
 	struct ib_device	ib_dev;
 	struct ib_device_attr	attr;
@@ -409,16 +413,18 @@ struct rxe_dev {
 	spinlock_t		mmap_offset_lock; /* guard mmap_offset */
 	int			mmap_offset;
 
-	u64			stats_counters[RXE_NUM_OF_COUNTERS];
-
+	struct rxe_stats	__percpu *pcpu_stats;
 	struct rxe_port		port;
 	struct list_head	list;
 	struct crypto_shash	*tfm;
 };
 
-static inline void rxe_counter_inc(struct rxe_dev *rxe, enum rxe_counters cnt)
+static inline void rxe_counter_inc(struct rxe_dev *rxe, enum rxe_counters index)
 {
-	rxe->stats_counters[cnt]++;
+	struct rxe_stats *stats;
+
+	stats = this_cpu_ptr(rxe->pcpu_stats);
+	stats->counters[index]++;
 }
 
 static inline struct rxe_dev *to_rdev(struct ib_device *dev)
-- 
1.8.3.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux