forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c
....@@ -32,159 +32,116 @@
3232
3333 #include <linux/kernel.h>
3434 #include <linux/module.h>
35
+#include <linux/refcount.h>
3536 #include <linux/mlx5/driver.h>
37
+#include <net/vxlan.h>
3638 #include "mlx5_core.h"
3739 #include "vxlan.h"
3840
3941 struct mlx5_vxlan {
4042 struct mlx5_core_dev *mdev;
41
- spinlock_t lock; /* protect vxlan table */
4243 /* max_num_ports is usuallly 4, 16 buckets is more than enough */
4344 DECLARE_HASHTABLE(htable, 4);
44
- int num_ports;
4545 struct mutex sync_lock; /* sync add/del port HW operations */
4646 };
4747
4848 struct mlx5_vxlan_port {
4949 struct hlist_node hlist;
50
- atomic_t refcount;
5150 u16 udp_port;
5251 };
5352
54
-static inline u8 mlx5_vxlan_max_udp_ports(struct mlx5_core_dev *mdev)
55
-{
56
- return MLX5_CAP_ETH(mdev, max_vxlan_udp_ports) ?: 4;
57
-}
58
-
5953 static int mlx5_vxlan_core_add_port_cmd(struct mlx5_core_dev *mdev, u16 port)
6054 {
61
- u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
62
- u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0};
55
+ u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {};
6356
6457 MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
6558 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
6659 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
67
- return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
60
+ return mlx5_cmd_exec_in(mdev, add_vxlan_udp_dport, in);
6861 }
6962
7063 static int mlx5_vxlan_core_del_port_cmd(struct mlx5_core_dev *mdev, u16 port)
7164 {
72
- u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0};
73
- u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0};
65
+ u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {};
7466
7567 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
7668 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
7769 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
78
- return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
70
+ return mlx5_cmd_exec_in(mdev, delete_vxlan_udp_dport, in);
7971 }
8072
81
-static struct mlx5_vxlan_port*
82
-mlx5_vxlan_lookup_port_locked(struct mlx5_vxlan *vxlan, u16 port)
73
+bool mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port)
8374 {
8475 struct mlx5_vxlan_port *vxlanp;
85
-
86
- hash_for_each_possible(vxlan->htable, vxlanp, hlist, port) {
87
- if (vxlanp->udp_port == port)
88
- return vxlanp;
89
- }
90
-
91
- return NULL;
92
-}
93
-
94
-struct mlx5_vxlan_port *mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port)
95
-{
96
- struct mlx5_vxlan_port *vxlanp;
76
+ bool found = false;
9777
9878 if (!mlx5_vxlan_allowed(vxlan))
9979 return NULL;
10080
101
- spin_lock_bh(&vxlan->lock);
102
- vxlanp = mlx5_vxlan_lookup_port_locked(vxlan, port);
103
- spin_unlock_bh(&vxlan->lock);
81
+ rcu_read_lock();
82
+ hash_for_each_possible_rcu(vxlan->htable, vxlanp, hlist, port)
83
+ if (vxlanp->udp_port == port) {
84
+ found = true;
85
+ break;
86
+ }
87
+ rcu_read_unlock();
10488
105
- return vxlanp;
89
+ return found;
90
+}
91
+
92
+static struct mlx5_vxlan_port *vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port)
93
+{
94
+ struct mlx5_vxlan_port *vxlanp;
95
+
96
+ hash_for_each_possible(vxlan->htable, vxlanp, hlist, port)
97
+ if (vxlanp->udp_port == port)
98
+ return vxlanp;
99
+ return NULL;
106100 }
107101
108102 int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
109103 {
110104 struct mlx5_vxlan_port *vxlanp;
111
- int ret = -ENOSPC;
105
+ int ret;
112106
113
- vxlanp = mlx5_vxlan_lookup_port(vxlan, port);
114
- if (vxlanp) {
115
- atomic_inc(&vxlanp->refcount);
116
- return 0;
107
+ vxlanp = kzalloc(sizeof(*vxlanp), GFP_KERNEL);
108
+ if (!vxlanp)
109
+ return -ENOMEM;
110
+ vxlanp->udp_port = port;
111
+
112
+ ret = mlx5_vxlan_core_add_port_cmd(vxlan->mdev, port);
113
+ if (ret) {
114
+ kfree(vxlanp);
115
+ return ret;
117116 }
118117
119118 mutex_lock(&vxlan->sync_lock);
120
- if (vxlan->num_ports >= mlx5_vxlan_max_udp_ports(vxlan->mdev)) {
121
- mlx5_core_info(vxlan->mdev,
122
- "UDP port (%d) not offloaded, max number of UDP ports (%d) are already offloaded\n",
123
- port, mlx5_vxlan_max_udp_ports(vxlan->mdev));
124
- ret = -ENOSPC;
125
- goto unlock;
126
- }
127
-
128
- ret = mlx5_vxlan_core_add_port_cmd(vxlan->mdev, port);
129
- if (ret)
130
- goto unlock;
131
-
132
- vxlanp = kzalloc(sizeof(*vxlanp), GFP_KERNEL);
133
- if (!vxlanp) {
134
- ret = -ENOMEM;
135
- goto err_delete_port;
136
- }
137
-
138
- vxlanp->udp_port = port;
139
- atomic_set(&vxlanp->refcount, 1);
140
-
141
- spin_lock_bh(&vxlan->lock);
142
- hash_add(vxlan->htable, &vxlanp->hlist, port);
143
- spin_unlock_bh(&vxlan->lock);
144
-
145
- vxlan->num_ports++;
119
+ hash_add_rcu(vxlan->htable, &vxlanp->hlist, port);
146120 mutex_unlock(&vxlan->sync_lock);
121
+
147122 return 0;
148
-
149
-err_delete_port:
150
- mlx5_vxlan_core_del_port_cmd(vxlan->mdev, port);
151
-
152
-unlock:
153
- mutex_unlock(&vxlan->sync_lock);
154
- return ret;
155123 }
156124
157125 int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
158126 {
159127 struct mlx5_vxlan_port *vxlanp;
160
- bool remove = false;
161128 int ret = 0;
162129
163130 mutex_lock(&vxlan->sync_lock);
164131
165
- spin_lock_bh(&vxlan->lock);
166
- vxlanp = mlx5_vxlan_lookup_port_locked(vxlan, port);
167
- if (!vxlanp) {
132
+ vxlanp = vxlan_lookup_port(vxlan, port);
133
+ if (WARN_ON(!vxlanp)) {
168134 ret = -ENOENT;
169135 goto out_unlock;
170136 }
171137
172
- if (atomic_dec_and_test(&vxlanp->refcount)) {
173
- hash_del(&vxlanp->hlist);
174
- remove = true;
175
- }
138
+ hash_del_rcu(&vxlanp->hlist);
139
+ synchronize_rcu();
140
+ mlx5_vxlan_core_del_port_cmd(vxlan->mdev, port);
141
+ kfree(vxlanp);
176142
177143 out_unlock:
178
- spin_unlock_bh(&vxlan->lock);
179
-
180
- if (remove) {
181
- mlx5_vxlan_core_del_port_cmd(vxlan->mdev, port);
182
- kfree(vxlanp);
183
- vxlan->num_ports--;
184
- }
185
-
186144 mutex_unlock(&vxlan->sync_lock);
187
-
188145 return ret;
189146 }
190147
....@@ -201,16 +158,26 @@
201158
202159 vxlan->mdev = mdev;
203160 mutex_init(&vxlan->sync_lock);
204
- spin_lock_init(&vxlan->lock);
205161 hash_init(vxlan->htable);
206162
207
- /* Hardware adds 4789 by default */
208
- mlx5_vxlan_add_port(vxlan, 4789);
163
+ /* Hardware adds 4789 (IANA_VXLAN_UDP_PORT) by default */
164
+ mlx5_vxlan_add_port(vxlan, IANA_VXLAN_UDP_PORT);
209165
210166 return vxlan;
211167 }
212168
213169 void mlx5_vxlan_destroy(struct mlx5_vxlan *vxlan)
170
+{
171
+ if (!mlx5_vxlan_allowed(vxlan))
172
+ return;
173
+
174
+ mlx5_vxlan_del_port(vxlan, IANA_VXLAN_UDP_PORT);
175
+ WARN_ON(!hash_empty(vxlan->htable));
176
+
177
+ kfree(vxlan);
178
+}
179
+
180
+void mlx5_vxlan_reset_to_default(struct mlx5_vxlan *vxlan)
214181 {
215182 struct mlx5_vxlan_port *vxlanp;
216183 struct hlist_node *tmp;
....@@ -219,12 +186,12 @@
219186 if (!mlx5_vxlan_allowed(vxlan))
220187 return;
221188
222
- /* Lockless since we are the only hash table consumers*/
223189 hash_for_each_safe(vxlan->htable, bkt, tmp, vxlanp, hlist) {
224
- hash_del(&vxlanp->hlist);
225
- mlx5_vxlan_core_del_port_cmd(vxlan->mdev, vxlanp->udp_port);
226
- kfree(vxlanp);
190
+ /* Don't delete default UDP port added by the HW.
191
+ * Remove only user configured ports
192
+ */
193
+ if (vxlanp->udp_port == IANA_VXLAN_UDP_PORT)
194
+ continue;
195
+ mlx5_vxlan_del_port(vxlan, vxlanp->udp_port);
227196 }
228
-
229
- kfree(vxlan);
230197 }