xref: /linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1d8782ec5SAmit Cohen // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2d8782ec5SAmit Cohen /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
3d8782ec5SAmit Cohen 
4d8782ec5SAmit Cohen #include <linux/refcount.h>
5d8782ec5SAmit Cohen #include <linux/idr.h>
6d8782ec5SAmit Cohen 
7d8782ec5SAmit Cohen #include "spectrum.h"
8d8782ec5SAmit Cohen #include "reg.h"
9d8782ec5SAmit Cohen 
10d8782ec5SAmit Cohen struct mlxsw_sp_pgt {
11d8782ec5SAmit Cohen 	struct idr pgt_idr;
12d8782ec5SAmit Cohen 	u16 end_index; /* Exclusive. */
13d8782ec5SAmit Cohen 	struct mutex lock; /* Protects PGT. */
14a1697d11SAmit Cohen 	bool smpe_index_valid;
15d8782ec5SAmit Cohen };
16d8782ec5SAmit Cohen 
17a3a7992bSAmit Cohen struct mlxsw_sp_pgt_entry {
18a3a7992bSAmit Cohen 	struct list_head ports_list;
19a3a7992bSAmit Cohen 	u16 index;
20a3a7992bSAmit Cohen 	u16 smpe_index;
21a3a7992bSAmit Cohen };
22a3a7992bSAmit Cohen 
23a3a7992bSAmit Cohen struct mlxsw_sp_pgt_entry_port {
24a3a7992bSAmit Cohen 	struct list_head list; /* Member of 'ports_list'. */
25a3a7992bSAmit Cohen 	u16 local_port;
26a3a7992bSAmit Cohen };
27a3a7992bSAmit Cohen 
mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp * mlxsw_sp,u16 * p_mid)28d8782ec5SAmit Cohen int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid)
29d8782ec5SAmit Cohen {
30d8782ec5SAmit Cohen 	int index, err = 0;
31d8782ec5SAmit Cohen 
32d8782ec5SAmit Cohen 	mutex_lock(&mlxsw_sp->pgt->lock);
33d8782ec5SAmit Cohen 	index = idr_alloc(&mlxsw_sp->pgt->pgt_idr, NULL, 0,
34d8782ec5SAmit Cohen 			  mlxsw_sp->pgt->end_index, GFP_KERNEL);
35d8782ec5SAmit Cohen 
36d8782ec5SAmit Cohen 	if (index < 0) {
37d8782ec5SAmit Cohen 		err = index;
38d8782ec5SAmit Cohen 		goto err_idr_alloc;
39d8782ec5SAmit Cohen 	}
40d8782ec5SAmit Cohen 
41d8782ec5SAmit Cohen 	*p_mid = index;
42d8782ec5SAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
43d8782ec5SAmit Cohen 	return 0;
44d8782ec5SAmit Cohen 
45d8782ec5SAmit Cohen err_idr_alloc:
46d8782ec5SAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
47d8782ec5SAmit Cohen 	return err;
48d8782ec5SAmit Cohen }
49d8782ec5SAmit Cohen 
mlxsw_sp_pgt_mid_free(struct mlxsw_sp * mlxsw_sp,u16 mid_base)50d8782ec5SAmit Cohen void mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base)
51d8782ec5SAmit Cohen {
52d8782ec5SAmit Cohen 	mutex_lock(&mlxsw_sp->pgt->lock);
53d8782ec5SAmit Cohen 	WARN_ON(idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base));
54d8782ec5SAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
55d8782ec5SAmit Cohen }
56d8782ec5SAmit Cohen 
mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp * mlxsw_sp,u16 * p_mid_base,u16 count)57*8c893abdSPetr Machata int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 *p_mid_base,
58*8c893abdSPetr Machata 				 u16 count)
59d8782ec5SAmit Cohen {
60*8c893abdSPetr Machata 	unsigned int mid_base;
61d8782ec5SAmit Cohen 	int i, err;
62d8782ec5SAmit Cohen 
63d8782ec5SAmit Cohen 	mutex_lock(&mlxsw_sp->pgt->lock);
64d8782ec5SAmit Cohen 
65*8c893abdSPetr Machata 	mid_base = idr_get_cursor(&mlxsw_sp->pgt->pgt_idr);
66d8782ec5SAmit Cohen 	for (i = 0; i < count; i++) {
67d8782ec5SAmit Cohen 		err = idr_alloc_cyclic(&mlxsw_sp->pgt->pgt_idr, NULL,
68d8782ec5SAmit Cohen 				       mid_base, mid_base + count, GFP_KERNEL);
69d8782ec5SAmit Cohen 		if (err < 0)
70d8782ec5SAmit Cohen 			goto err_idr_alloc_cyclic;
71d8782ec5SAmit Cohen 	}
72d8782ec5SAmit Cohen 
73d8782ec5SAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
74*8c893abdSPetr Machata 	*p_mid_base = mid_base;
75d8782ec5SAmit Cohen 	return 0;
76d8782ec5SAmit Cohen 
77d8782ec5SAmit Cohen err_idr_alloc_cyclic:
78d8782ec5SAmit Cohen 	for (i--; i >= 0; i--)
79d8782ec5SAmit Cohen 		idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base + i);
80d8782ec5SAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
81d8782ec5SAmit Cohen 	return err;
82d8782ec5SAmit Cohen }
83d8782ec5SAmit Cohen 
84d8782ec5SAmit Cohen void
mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp * mlxsw_sp,u16 mid_base,u16 count)85d8782ec5SAmit Cohen mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
86d8782ec5SAmit Cohen {
87d8782ec5SAmit Cohen 	struct idr *pgt_idr = &mlxsw_sp->pgt->pgt_idr;
88d8782ec5SAmit Cohen 	int i;
89d8782ec5SAmit Cohen 
90d8782ec5SAmit Cohen 	mutex_lock(&mlxsw_sp->pgt->lock);
91d8782ec5SAmit Cohen 
92d8782ec5SAmit Cohen 	for (i = 0; i < count; i++)
93d8782ec5SAmit Cohen 		WARN_ON_ONCE(idr_remove(pgt_idr, mid_base + i));
94d8782ec5SAmit Cohen 
95d8782ec5SAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
96d8782ec5SAmit Cohen }
97d8782ec5SAmit Cohen 
98a3a7992bSAmit Cohen static struct mlxsw_sp_pgt_entry_port *
mlxsw_sp_pgt_entry_port_lookup(struct mlxsw_sp_pgt_entry * pgt_entry,u16 local_port)99a3a7992bSAmit Cohen mlxsw_sp_pgt_entry_port_lookup(struct mlxsw_sp_pgt_entry *pgt_entry,
100a3a7992bSAmit Cohen 			       u16 local_port)
101a3a7992bSAmit Cohen {
102a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
103a3a7992bSAmit Cohen 
104a3a7992bSAmit Cohen 	list_for_each_entry(pgt_entry_port, &pgt_entry->ports_list, list) {
105a3a7992bSAmit Cohen 		if (pgt_entry_port->local_port == local_port)
106a3a7992bSAmit Cohen 			return pgt_entry_port;
107a3a7992bSAmit Cohen 	}
108a3a7992bSAmit Cohen 
109a3a7992bSAmit Cohen 	return NULL;
110a3a7992bSAmit Cohen }
111a3a7992bSAmit Cohen 
112a3a7992bSAmit Cohen static struct mlxsw_sp_pgt_entry *
mlxsw_sp_pgt_entry_create(struct mlxsw_sp_pgt * pgt,u16 mid,u16 smpe)113a3a7992bSAmit Cohen mlxsw_sp_pgt_entry_create(struct mlxsw_sp_pgt *pgt, u16 mid, u16 smpe)
114a3a7992bSAmit Cohen {
115a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry *pgt_entry;
116a3a7992bSAmit Cohen 	void *ret;
117a3a7992bSAmit Cohen 	int err;
118a3a7992bSAmit Cohen 
119a3a7992bSAmit Cohen 	pgt_entry = kzalloc(sizeof(*pgt_entry), GFP_KERNEL);
120a3a7992bSAmit Cohen 	if (!pgt_entry)
121a3a7992bSAmit Cohen 		return ERR_PTR(-ENOMEM);
122a3a7992bSAmit Cohen 
123a3a7992bSAmit Cohen 	ret = idr_replace(&pgt->pgt_idr, pgt_entry, mid);
124a3a7992bSAmit Cohen 	if (IS_ERR(ret)) {
125a3a7992bSAmit Cohen 		err = PTR_ERR(ret);
126a3a7992bSAmit Cohen 		goto err_idr_replace;
127a3a7992bSAmit Cohen 	}
128a3a7992bSAmit Cohen 
129a3a7992bSAmit Cohen 	INIT_LIST_HEAD(&pgt_entry->ports_list);
130a3a7992bSAmit Cohen 	pgt_entry->index = mid;
131a3a7992bSAmit Cohen 	pgt_entry->smpe_index = smpe;
132a3a7992bSAmit Cohen 	return pgt_entry;
133a3a7992bSAmit Cohen 
134a3a7992bSAmit Cohen err_idr_replace:
135a3a7992bSAmit Cohen 	kfree(pgt_entry);
136a3a7992bSAmit Cohen 	return ERR_PTR(err);
137a3a7992bSAmit Cohen }
138a3a7992bSAmit Cohen 
mlxsw_sp_pgt_entry_destroy(struct mlxsw_sp_pgt * pgt,struct mlxsw_sp_pgt_entry * pgt_entry)139a3a7992bSAmit Cohen static void mlxsw_sp_pgt_entry_destroy(struct mlxsw_sp_pgt *pgt,
140a3a7992bSAmit Cohen 				       struct mlxsw_sp_pgt_entry *pgt_entry)
141a3a7992bSAmit Cohen {
142a3a7992bSAmit Cohen 	WARN_ON(!list_empty(&pgt_entry->ports_list));
143a3a7992bSAmit Cohen 
144a3a7992bSAmit Cohen 	pgt_entry = idr_replace(&pgt->pgt_idr, NULL, pgt_entry->index);
145a3a7992bSAmit Cohen 	if (WARN_ON(IS_ERR(pgt_entry)))
146a3a7992bSAmit Cohen 		return;
147a3a7992bSAmit Cohen 
148a3a7992bSAmit Cohen 	kfree(pgt_entry);
149a3a7992bSAmit Cohen }
150a3a7992bSAmit Cohen 
151a3a7992bSAmit Cohen static struct mlxsw_sp_pgt_entry *
mlxsw_sp_pgt_entry_get(struct mlxsw_sp_pgt * pgt,u16 mid,u16 smpe)152a3a7992bSAmit Cohen mlxsw_sp_pgt_entry_get(struct mlxsw_sp_pgt *pgt, u16 mid, u16 smpe)
153a3a7992bSAmit Cohen {
154a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry *pgt_entry;
155a3a7992bSAmit Cohen 
156a3a7992bSAmit Cohen 	pgt_entry = idr_find(&pgt->pgt_idr, mid);
157a3a7992bSAmit Cohen 	if (pgt_entry)
158a3a7992bSAmit Cohen 		return pgt_entry;
159a3a7992bSAmit Cohen 
160a3a7992bSAmit Cohen 	return mlxsw_sp_pgt_entry_create(pgt, mid, smpe);
161a3a7992bSAmit Cohen }
162a3a7992bSAmit Cohen 
mlxsw_sp_pgt_entry_put(struct mlxsw_sp_pgt * pgt,u16 mid)163a3a7992bSAmit Cohen static void mlxsw_sp_pgt_entry_put(struct mlxsw_sp_pgt *pgt, u16 mid)
164a3a7992bSAmit Cohen {
165a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry *pgt_entry;
166a3a7992bSAmit Cohen 
167a3a7992bSAmit Cohen 	pgt_entry = idr_find(&pgt->pgt_idr, mid);
168a3a7992bSAmit Cohen 	if (WARN_ON(!pgt_entry))
169a3a7992bSAmit Cohen 		return;
170a3a7992bSAmit Cohen 
171a3a7992bSAmit Cohen 	if (list_empty(&pgt_entry->ports_list))
172a3a7992bSAmit Cohen 		mlxsw_sp_pgt_entry_destroy(pgt, pgt_entry);
173a3a7992bSAmit Cohen }
174a3a7992bSAmit Cohen 
mlxsw_sp_pgt_smid2_port_set(char * smid2_pl,u16 local_port,bool member)175a3a7992bSAmit Cohen static void mlxsw_sp_pgt_smid2_port_set(char *smid2_pl, u16 local_port,
176a3a7992bSAmit Cohen 					bool member)
177a3a7992bSAmit Cohen {
178a3a7992bSAmit Cohen 	mlxsw_reg_smid2_port_set(smid2_pl, local_port, member);
179a3a7992bSAmit Cohen 	mlxsw_reg_smid2_port_mask_set(smid2_pl, local_port, 1);
180a3a7992bSAmit Cohen }
181a3a7992bSAmit Cohen 
182a3a7992bSAmit Cohen static int
mlxsw_sp_pgt_entry_port_write(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_pgt_entry * pgt_entry,u16 local_port,bool member)183a3a7992bSAmit Cohen mlxsw_sp_pgt_entry_port_write(struct mlxsw_sp *mlxsw_sp,
184a3a7992bSAmit Cohen 			      const struct mlxsw_sp_pgt_entry *pgt_entry,
185a3a7992bSAmit Cohen 			      u16 local_port, bool member)
186a3a7992bSAmit Cohen {
187a3a7992bSAmit Cohen 	char *smid2_pl;
188a3a7992bSAmit Cohen 	int err;
189a3a7992bSAmit Cohen 
190a3a7992bSAmit Cohen 	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
191a3a7992bSAmit Cohen 	if (!smid2_pl)
192a3a7992bSAmit Cohen 		return -ENOMEM;
193a3a7992bSAmit Cohen 
19477b7f83dSAmit Cohen 	mlxsw_reg_smid2_pack(smid2_pl, pgt_entry->index, 0, 0,
19577b7f83dSAmit Cohen 			     mlxsw_sp->pgt->smpe_index_valid,
19677b7f83dSAmit Cohen 			     pgt_entry->smpe_index);
197a3a7992bSAmit Cohen 
198a3a7992bSAmit Cohen 	mlxsw_sp_pgt_smid2_port_set(smid2_pl, local_port, member);
199a3a7992bSAmit Cohen 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid2), smid2_pl);
200a3a7992bSAmit Cohen 
201a3a7992bSAmit Cohen 	kfree(smid2_pl);
202a3a7992bSAmit Cohen 
203a3a7992bSAmit Cohen 	return err;
204a3a7992bSAmit Cohen }
205a3a7992bSAmit Cohen 
206a3a7992bSAmit Cohen static struct mlxsw_sp_pgt_entry_port *
mlxsw_sp_pgt_entry_port_create(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_pgt_entry * pgt_entry,u16 local_port)207a3a7992bSAmit Cohen mlxsw_sp_pgt_entry_port_create(struct mlxsw_sp *mlxsw_sp,
208a3a7992bSAmit Cohen 			       struct mlxsw_sp_pgt_entry *pgt_entry,
209a3a7992bSAmit Cohen 			       u16 local_port)
210a3a7992bSAmit Cohen {
211a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
212a3a7992bSAmit Cohen 	int err;
213a3a7992bSAmit Cohen 
214a3a7992bSAmit Cohen 	pgt_entry_port = kzalloc(sizeof(*pgt_entry_port), GFP_KERNEL);
215a3a7992bSAmit Cohen 	if (!pgt_entry_port)
216a3a7992bSAmit Cohen 		return ERR_PTR(-ENOMEM);
217a3a7992bSAmit Cohen 
218a3a7992bSAmit Cohen 	err = mlxsw_sp_pgt_entry_port_write(mlxsw_sp, pgt_entry, local_port,
219a3a7992bSAmit Cohen 					    true);
220a3a7992bSAmit Cohen 	if (err)
221a3a7992bSAmit Cohen 		goto err_pgt_entry_port_write;
222a3a7992bSAmit Cohen 
223a3a7992bSAmit Cohen 	pgt_entry_port->local_port = local_port;
224a3a7992bSAmit Cohen 	list_add(&pgt_entry_port->list, &pgt_entry->ports_list);
225a3a7992bSAmit Cohen 
226a3a7992bSAmit Cohen 	return pgt_entry_port;
227a3a7992bSAmit Cohen 
228a3a7992bSAmit Cohen err_pgt_entry_port_write:
229a3a7992bSAmit Cohen 	kfree(pgt_entry_port);
230a3a7992bSAmit Cohen 	return ERR_PTR(err);
231a3a7992bSAmit Cohen }
232a3a7992bSAmit Cohen 
233a3a7992bSAmit Cohen static void
mlxsw_sp_pgt_entry_port_destroy(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_pgt_entry * pgt_entry,struct mlxsw_sp_pgt_entry_port * pgt_entry_port)234a3a7992bSAmit Cohen mlxsw_sp_pgt_entry_port_destroy(struct mlxsw_sp *mlxsw_sp,
235a3a7992bSAmit Cohen 				struct mlxsw_sp_pgt_entry *pgt_entry,
236a3a7992bSAmit Cohen 				struct mlxsw_sp_pgt_entry_port *pgt_entry_port)
237a3a7992bSAmit Cohen 
238a3a7992bSAmit Cohen {
239a3a7992bSAmit Cohen 	list_del(&pgt_entry_port->list);
240a3a7992bSAmit Cohen 	mlxsw_sp_pgt_entry_port_write(mlxsw_sp, pgt_entry,
241a3a7992bSAmit Cohen 				      pgt_entry_port->local_port, false);
242a3a7992bSAmit Cohen 	kfree(pgt_entry_port);
243a3a7992bSAmit Cohen }
244a3a7992bSAmit Cohen 
mlxsw_sp_pgt_entry_port_add(struct mlxsw_sp * mlxsw_sp,u16 mid,u16 smpe,u16 local_port)245a3a7992bSAmit Cohen static int mlxsw_sp_pgt_entry_port_add(struct mlxsw_sp *mlxsw_sp, u16 mid,
246a3a7992bSAmit Cohen 				       u16 smpe, u16 local_port)
247a3a7992bSAmit Cohen {
248a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
249a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry *pgt_entry;
250a3a7992bSAmit Cohen 	int err;
251a3a7992bSAmit Cohen 
252a3a7992bSAmit Cohen 	mutex_lock(&mlxsw_sp->pgt->lock);
253a3a7992bSAmit Cohen 
254a3a7992bSAmit Cohen 	pgt_entry = mlxsw_sp_pgt_entry_get(mlxsw_sp->pgt, mid, smpe);
255a3a7992bSAmit Cohen 	if (IS_ERR(pgt_entry)) {
256a3a7992bSAmit Cohen 		err = PTR_ERR(pgt_entry);
257a3a7992bSAmit Cohen 		goto err_pgt_entry_get;
258a3a7992bSAmit Cohen 	}
259a3a7992bSAmit Cohen 
260a3a7992bSAmit Cohen 	pgt_entry_port = mlxsw_sp_pgt_entry_port_create(mlxsw_sp, pgt_entry,
261a3a7992bSAmit Cohen 							local_port);
262a3a7992bSAmit Cohen 	if (IS_ERR(pgt_entry_port)) {
263a3a7992bSAmit Cohen 		err = PTR_ERR(pgt_entry_port);
264a3a7992bSAmit Cohen 		goto err_pgt_entry_port_get;
265a3a7992bSAmit Cohen 	}
266a3a7992bSAmit Cohen 
267a3a7992bSAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
268a3a7992bSAmit Cohen 	return 0;
269a3a7992bSAmit Cohen 
270a3a7992bSAmit Cohen err_pgt_entry_port_get:
271a3a7992bSAmit Cohen 	mlxsw_sp_pgt_entry_put(mlxsw_sp->pgt, mid);
272a3a7992bSAmit Cohen err_pgt_entry_get:
273a3a7992bSAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
274a3a7992bSAmit Cohen 	return err;
275a3a7992bSAmit Cohen }
276a3a7992bSAmit Cohen 
mlxsw_sp_pgt_entry_port_del(struct mlxsw_sp * mlxsw_sp,u16 mid,u16 smpe,u16 local_port)277a3a7992bSAmit Cohen static void mlxsw_sp_pgt_entry_port_del(struct mlxsw_sp *mlxsw_sp,
278a3a7992bSAmit Cohen 					u16 mid, u16 smpe, u16 local_port)
279a3a7992bSAmit Cohen {
280a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
281a3a7992bSAmit Cohen 	struct mlxsw_sp_pgt_entry *pgt_entry;
282a3a7992bSAmit Cohen 
283a3a7992bSAmit Cohen 	mutex_lock(&mlxsw_sp->pgt->lock);
284a3a7992bSAmit Cohen 
285a3a7992bSAmit Cohen 	pgt_entry = idr_find(&mlxsw_sp->pgt->pgt_idr, mid);
286a3a7992bSAmit Cohen 	if (!pgt_entry)
287a3a7992bSAmit Cohen 		goto out;
288a3a7992bSAmit Cohen 
289a3a7992bSAmit Cohen 	pgt_entry_port = mlxsw_sp_pgt_entry_port_lookup(pgt_entry, local_port);
290a3a7992bSAmit Cohen 	if (!pgt_entry_port)
291a3a7992bSAmit Cohen 		goto out;
292a3a7992bSAmit Cohen 
293a3a7992bSAmit Cohen 	mlxsw_sp_pgt_entry_port_destroy(mlxsw_sp, pgt_entry, pgt_entry_port);
294a3a7992bSAmit Cohen 	mlxsw_sp_pgt_entry_put(mlxsw_sp->pgt, mid);
295a3a7992bSAmit Cohen 
296a3a7992bSAmit Cohen out:
297a3a7992bSAmit Cohen 	mutex_unlock(&mlxsw_sp->pgt->lock);
298a3a7992bSAmit Cohen }
299a3a7992bSAmit Cohen 
mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp * mlxsw_sp,u16 mid,u16 smpe,u16 local_port,bool member)300a3a7992bSAmit Cohen int mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp *mlxsw_sp, u16 mid,
301a3a7992bSAmit Cohen 				u16 smpe, u16 local_port, bool member)
302a3a7992bSAmit Cohen {
303a3a7992bSAmit Cohen 	if (member)
304a3a7992bSAmit Cohen 		return mlxsw_sp_pgt_entry_port_add(mlxsw_sp, mid, smpe,
305a3a7992bSAmit Cohen 						   local_port);
306a3a7992bSAmit Cohen 
307a3a7992bSAmit Cohen 	mlxsw_sp_pgt_entry_port_del(mlxsw_sp, mid, smpe, local_port);
308a3a7992bSAmit Cohen 	return 0;
309a3a7992bSAmit Cohen }
310a3a7992bSAmit Cohen 
mlxsw_sp_pgt_init(struct mlxsw_sp * mlxsw_sp)311d8782ec5SAmit Cohen int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp)
312d8782ec5SAmit Cohen {
313d8782ec5SAmit Cohen 	struct mlxsw_sp_pgt *pgt;
314d8782ec5SAmit Cohen 
315d8782ec5SAmit Cohen 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, PGT_SIZE))
316d8782ec5SAmit Cohen 		return -EIO;
317d8782ec5SAmit Cohen 
318d8782ec5SAmit Cohen 	pgt = kzalloc(sizeof(*mlxsw_sp->pgt), GFP_KERNEL);
319d8782ec5SAmit Cohen 	if (!pgt)
320d8782ec5SAmit Cohen 		return -ENOMEM;
321d8782ec5SAmit Cohen 
322d8782ec5SAmit Cohen 	idr_init(&pgt->pgt_idr);
323d8782ec5SAmit Cohen 	pgt->end_index = MLXSW_CORE_RES_GET(mlxsw_sp->core, PGT_SIZE);
324d8782ec5SAmit Cohen 	mutex_init(&pgt->lock);
325a1697d11SAmit Cohen 	pgt->smpe_index_valid = mlxsw_sp->pgt_smpe_index_valid;
326d8782ec5SAmit Cohen 	mlxsw_sp->pgt = pgt;
327d8782ec5SAmit Cohen 	return 0;
328d8782ec5SAmit Cohen }
329d8782ec5SAmit Cohen 
mlxsw_sp_pgt_fini(struct mlxsw_sp * mlxsw_sp)330d8782ec5SAmit Cohen void mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp)
331d8782ec5SAmit Cohen {
332d8782ec5SAmit Cohen 	mutex_destroy(&mlxsw_sp->pgt->lock);
333d8782ec5SAmit Cohen 	WARN_ON(!idr_is_empty(&mlxsw_sp->pgt->pgt_idr));
334d8782ec5SAmit Cohen 	idr_destroy(&mlxsw_sp->pgt->pgt_idr);
335d8782ec5SAmit Cohen 	kfree(mlxsw_sp->pgt);
336d8782ec5SAmit Cohen }
337