| .. | .. |
|---|
| 2 | 2 | /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */ |
|---|
| 3 | 3 | |
|---|
| 4 | 4 | #include <linux/kernel.h> |
|---|
| 5 | +#include <linux/mutex.h> |
|---|
| 5 | 6 | #include <linux/slab.h> |
|---|
| 6 | 7 | |
|---|
| 7 | 8 | #include "spectrum.h" |
|---|
| 8 | 9 | |
|---|
| 9 | 10 | struct mlxsw_sp_kvdl { |
|---|
| 10 | 11 | const struct mlxsw_sp_kvdl_ops *kvdl_ops; |
|---|
| 11 | | - unsigned long priv[0]; |
|---|
| 12 | + struct mutex kvdl_lock; /* Protects kvdl allocations */ |
|---|
| 13 | + unsigned long priv[]; |
|---|
| 12 | 14 | /* priv has to be always the last item */ |
|---|
| 13 | 15 | }; |
|---|
| 14 | 16 | |
|---|
| .. | .. |
|---|
| 22 | 24 | GFP_KERNEL); |
|---|
| 23 | 25 | if (!kvdl) |
|---|
| 24 | 26 | return -ENOMEM; |
|---|
| 27 | + mutex_init(&kvdl->kvdl_lock); |
|---|
| 25 | 28 | kvdl->kvdl_ops = kvdl_ops; |
|---|
| 26 | 29 | mlxsw_sp->kvdl = kvdl; |
|---|
| 27 | 30 | |
|---|
| .. | .. |
|---|
| 31 | 34 | return 0; |
|---|
| 32 | 35 | |
|---|
| 33 | 36 | err_init: |
|---|
| 37 | + mutex_destroy(&kvdl->kvdl_lock); |
|---|
| 34 | 38 | kfree(kvdl); |
|---|
| 35 | 39 | return err; |
|---|
| 36 | 40 | } |
|---|
| .. | .. |
|---|
| 40 | 44 | struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; |
|---|
| 41 | 45 | |
|---|
| 42 | 46 | kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv); |
|---|
| 47 | + mutex_destroy(&kvdl->kvdl_lock); |
|---|
| 43 | 48 | kfree(kvdl); |
|---|
| 44 | 49 | } |
|---|
| 45 | 50 | |
|---|
| .. | .. |
|---|
| 48 | 53 | unsigned int entry_count, u32 *p_entry_index) |
|---|
| 49 | 54 | { |
|---|
| 50 | 55 | struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; |
|---|
| 56 | + int err; |
|---|
| 51 | 57 | |
|---|
| 52 | | - return kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type, |
|---|
| 53 | | - entry_count, p_entry_index); |
|---|
| 58 | + mutex_lock(&kvdl->kvdl_lock); |
|---|
| 59 | + err = kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type, |
|---|
| 60 | + entry_count, p_entry_index); |
|---|
| 61 | + mutex_unlock(&kvdl->kvdl_lock); |
|---|
| 62 | + |
|---|
| 63 | + return err; |
|---|
| 54 | 64 | } |
|---|
| 55 | 65 | |
|---|
| 56 | 66 | void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, |
|---|
| .. | .. |
|---|
| 59 | 69 | { |
|---|
| 60 | 70 | struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; |
|---|
| 61 | 71 | |
|---|
| 72 | + mutex_lock(&kvdl->kvdl_lock); |
|---|
| 62 | 73 | kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type, |
|---|
| 63 | 74 | entry_count, entry_index); |
|---|
| 75 | + mutex_unlock(&kvdl->kvdl_lock); |
|---|
| 64 | 76 | } |
|---|
| 65 | 77 | |
|---|
| 66 | 78 | int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp, |
|---|