aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorEli Cohen <eli@mellanox.com>2012-10-17 12:42:59 -0400
committerRoland Dreier <roland@purestorage.com>2012-10-18 13:29:02 -0400
commitbef83ed92caca45a394344a14b0234aea977da6e (patch)
tree8a9e4ffe42d5cd520b5d8df7bb5129a3645939c0 /drivers/infiniband
parent2c75d2ccb6e5ffb96ce8624ef4c1f7ba5bd96499 (diff)
IB/mlx4: Synchronize cleanup of MCGs in MCG paravirtualization
A client re-register event invokes cleanup of all MCGs. This is required to protect against misbehaved guests leading to corruption of join/leave database. However, since cleaning up the MCGs is a heavy operation, it is pushed to a work queue for further processing. Client re-register is also propagated to ULPs (e.g IPoIB). However, since the cleanup is performed in a workqueue, the ULP could leave and re-join groups before the cleanup occurs. In this case, when the cleanup takes place, it prunes the (newly-joined) MCGs and the ULP is left without actual MCGs while believing it joined them. Fix this by setting the flushing flag before invoking the cleanup task and clearing it after flushing is complete. Signed-off-by: Eli Cohen <eli@mellanox.com> Reviewed-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/mlx4/mcg.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
index 44ff480f79f5..25b2cdff00f8 100644
--- a/drivers/infiniband/hw/mlx4/mcg.c
+++ b/drivers/infiniband/hw/mlx4/mcg.c
@@ -1075,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
1075 unsigned long end; 1075 unsigned long end;
1076 int count; 1076 int count;
1077 1077
1078 if (ctx->flushing)
1079 return;
1080
1081 ctx->flushing = 1;
1082 for (i = 0; i < MAX_VFS; ++i) 1078 for (i = 0; i < MAX_VFS; ++i)
1083 clean_vf_mcast(ctx, i); 1079 clean_vf_mcast(ctx, i);
1084 1080
@@ -1108,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
1108 force_clean_group(group); 1104 force_clean_group(group);
1109 } 1105 }
1110 mutex_unlock(&ctx->mcg_table_lock); 1106 mutex_unlock(&ctx->mcg_table_lock);
1111
1112 if (!destroy_wq)
1113 ctx->flushing = 0;
1114} 1107}
1115 1108
1116struct clean_work { 1109struct clean_work {
@@ -1124,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work)
1124 struct clean_work *cw = container_of(work, struct clean_work, work); 1117 struct clean_work *cw = container_of(work, struct clean_work, work);
1125 1118
1126 _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq); 1119 _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq);
1120 cw->ctx->flushing = 0;
1127 kfree(cw); 1121 kfree(cw);
1128} 1122}
1129 1123
@@ -1131,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
1131{ 1125{
1132 struct clean_work *work; 1126 struct clean_work *work;
1133 1127
1128 if (ctx->flushing)
1129 return;
1130
1131 ctx->flushing = 1;
1132
1134 if (destroy_wq) { 1133 if (destroy_wq) {
1135 _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq); 1134 _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq);
1135 ctx->flushing = 0;
1136 return; 1136 return;
1137 } 1137 }
1138 1138
1139 work = kmalloc(sizeof *work, GFP_KERNEL); 1139 work = kmalloc(sizeof *work, GFP_KERNEL);
1140 if (!work) { 1140 if (!work) {
1141 ctx->flushing = 0;
1141 mcg_warn("failed allocating work for cleanup\n"); 1142 mcg_warn("failed allocating work for cleanup\n");
1142 return; 1143 return;
1143 } 1144 }