summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/rocker/rocker.c
diff options
context:
space:
mode:
authorScott Feldman <sfeldma@gmail.com>2015-06-12 21:24:40 -0700
committerDavid S. Miller <davem@davemloft.net>2015-06-15 16:04:21 -0700
commit4d81db4156caef7b223dde07e50db0144d12a192 (patch)
tree26fd99f00ba0c939dd4ecfb1a795e2158882f053 /drivers/net/ethernet/rocker/rocker.c
parenta07203108494d00efdd8f2fcbf9f2f4f63110e60 (diff)
rocker: fix neigh tbl index increment race
rocker->neigh_tbl_next_index is used to generate unique indices for neigh entries programmed into the device. The way new indices were generated was racy with the new prepare-commit transaction model. A simple fix here removes the race. The race was with two processes getting the same index, one process using prepare-commit, the other not: Proc A Proc B PREPARE phase get neigh_tbl_next_index NONE phase get neigh_tbl_next_index neigh_tbl_next_index++ COMMIT phase neigh_tbl_next_index++ Both A and B got the same index. The fix is to store and increment neigh_tbl_next_index in the PREPARE (or NONE) phase and use value in COMMIT phase: Proc A Proc B PREPARE phase get neigh_tbl_next_index neigh_tbl_next_index++ NONE phase get neigh_tbl_next_index neigh_tbl_next_index++ COMMIT phase // use value stashed in PREPARE phase Reported-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: Scott Feldman <sfeldma@gmail.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/rocker/rocker.c')
-rw-r--r--drivers/net/ethernet/rocker/rocker.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index c6a6e3c36d90..a9d15590743e 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -2901,10 +2901,10 @@ static void _rocker_neigh_add(struct rocker *rocker,
enum switchdev_trans trans,
struct rocker_neigh_tbl_entry *entry)
{
- entry->index = rocker->neigh_tbl_next_index;
+ if (trans != SWITCHDEV_TRANS_COMMIT)
+ entry->index = rocker->neigh_tbl_next_index++;
if (trans == SWITCHDEV_TRANS_PREPARE)
return;
- rocker->neigh_tbl_next_index++;
entry->ref_count++;
hash_add(rocker->neigh_tbl, &entry->entry,
be32_to_cpu(entry->ip_addr));