162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/refcount.h>
562306a36Sopenharmony_ci#include <linux/idr.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "spectrum.h"
862306a36Sopenharmony_ci#include "reg.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistruct mlxsw_sp_pgt {
1162306a36Sopenharmony_ci	struct idr pgt_idr;
1262306a36Sopenharmony_ci	u16 end_index; /* Exclusive. */
1362306a36Sopenharmony_ci	struct mutex lock; /* Protects PGT. */
1462306a36Sopenharmony_ci	bool smpe_index_valid;
1562306a36Sopenharmony_ci};
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistruct mlxsw_sp_pgt_entry {
1862306a36Sopenharmony_ci	struct list_head ports_list;
1962306a36Sopenharmony_ci	u16 index;
2062306a36Sopenharmony_ci	u16 smpe_index;
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct mlxsw_sp_pgt_entry_port {
2462306a36Sopenharmony_ci	struct list_head list; /* Member of 'ports_list'. */
2562306a36Sopenharmony_ci	u16 local_port;
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciint mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	int index, err = 0;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	mutex_lock(&mlxsw_sp->pgt->lock);
3362306a36Sopenharmony_ci	index = idr_alloc(&mlxsw_sp->pgt->pgt_idr, NULL, 0,
3462306a36Sopenharmony_ci			  mlxsw_sp->pgt->end_index, GFP_KERNEL);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	if (index < 0) {
3762306a36Sopenharmony_ci		err = index;
3862306a36Sopenharmony_ci		goto err_idr_alloc;
3962306a36Sopenharmony_ci	}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	*p_mid = index;
4262306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
4362306a36Sopenharmony_ci	return 0;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cierr_idr_alloc:
4662306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
4762306a36Sopenharmony_ci	return err;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_civoid mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	mutex_lock(&mlxsw_sp->pgt->lock);
5362306a36Sopenharmony_ci	WARN_ON(idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base));
5462306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciint
5862306a36Sopenharmony_cimlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	unsigned int idr_cursor;
6162306a36Sopenharmony_ci	int i, err;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	mutex_lock(&mlxsw_sp->pgt->lock);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	/* This function is supposed to be called several times as part of
6662306a36Sopenharmony_ci	 * driver init, in specific order. Verify that the mid_index is the
6762306a36Sopenharmony_ci	 * first free index in the idr, to be able to free the indexes in case
6862306a36Sopenharmony_ci	 * of error.
6962306a36Sopenharmony_ci	 */
7062306a36Sopenharmony_ci	idr_cursor = idr_get_cursor(&mlxsw_sp->pgt->pgt_idr);
7162306a36Sopenharmony_ci	if (WARN_ON(idr_cursor != mid_base)) {
7262306a36Sopenharmony_ci		err = -EINVAL;
7362306a36Sopenharmony_ci		goto err_idr_cursor;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
7762306a36Sopenharmony_ci		err = idr_alloc_cyclic(&mlxsw_sp->pgt->pgt_idr, NULL,
7862306a36Sopenharmony_ci				       mid_base, mid_base + count, GFP_KERNEL);
7962306a36Sopenharmony_ci		if (err < 0)
8062306a36Sopenharmony_ci			goto err_idr_alloc_cyclic;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
8462306a36Sopenharmony_ci	return 0;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cierr_idr_alloc_cyclic:
8762306a36Sopenharmony_ci	for (i--; i >= 0; i--)
8862306a36Sopenharmony_ci		idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base + i);
8962306a36Sopenharmony_cierr_idr_cursor:
9062306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
9162306a36Sopenharmony_ci	return err;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_civoid
9562306a36Sopenharmony_cimlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	struct idr *pgt_idr = &mlxsw_sp->pgt->pgt_idr;
9862306a36Sopenharmony_ci	int i;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	mutex_lock(&mlxsw_sp->pgt->lock);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	for (i = 0; i < count; i++)
10362306a36Sopenharmony_ci		WARN_ON_ONCE(idr_remove(pgt_idr, mid_base + i));
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic struct mlxsw_sp_pgt_entry_port *
10962306a36Sopenharmony_cimlxsw_sp_pgt_entry_port_lookup(struct mlxsw_sp_pgt_entry *pgt_entry,
11062306a36Sopenharmony_ci			       u16 local_port)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	list_for_each_entry(pgt_entry_port, &pgt_entry->ports_list, list) {
11562306a36Sopenharmony_ci		if (pgt_entry_port->local_port == local_port)
11662306a36Sopenharmony_ci			return pgt_entry_port;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return NULL;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic struct mlxsw_sp_pgt_entry *
12362306a36Sopenharmony_cimlxsw_sp_pgt_entry_create(struct mlxsw_sp_pgt *pgt, u16 mid, u16 smpe)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry *pgt_entry;
12662306a36Sopenharmony_ci	void *ret;
12762306a36Sopenharmony_ci	int err;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	pgt_entry = kzalloc(sizeof(*pgt_entry), GFP_KERNEL);
13062306a36Sopenharmony_ci	if (!pgt_entry)
13162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	ret = idr_replace(&pgt->pgt_idr, pgt_entry, mid);
13462306a36Sopenharmony_ci	if (IS_ERR(ret)) {
13562306a36Sopenharmony_ci		err = PTR_ERR(ret);
13662306a36Sopenharmony_ci		goto err_idr_replace;
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	INIT_LIST_HEAD(&pgt_entry->ports_list);
14062306a36Sopenharmony_ci	pgt_entry->index = mid;
14162306a36Sopenharmony_ci	pgt_entry->smpe_index = smpe;
14262306a36Sopenharmony_ci	return pgt_entry;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cierr_idr_replace:
14562306a36Sopenharmony_ci	kfree(pgt_entry);
14662306a36Sopenharmony_ci	return ERR_PTR(err);
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic void mlxsw_sp_pgt_entry_destroy(struct mlxsw_sp_pgt *pgt,
15062306a36Sopenharmony_ci				       struct mlxsw_sp_pgt_entry *pgt_entry)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	WARN_ON(!list_empty(&pgt_entry->ports_list));
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	pgt_entry = idr_replace(&pgt->pgt_idr, NULL, pgt_entry->index);
15562306a36Sopenharmony_ci	if (WARN_ON(IS_ERR(pgt_entry)))
15662306a36Sopenharmony_ci		return;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	kfree(pgt_entry);
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic struct mlxsw_sp_pgt_entry *
16262306a36Sopenharmony_cimlxsw_sp_pgt_entry_get(struct mlxsw_sp_pgt *pgt, u16 mid, u16 smpe)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry *pgt_entry;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	pgt_entry = idr_find(&pgt->pgt_idr, mid);
16762306a36Sopenharmony_ci	if (pgt_entry)
16862306a36Sopenharmony_ci		return pgt_entry;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	return mlxsw_sp_pgt_entry_create(pgt, mid, smpe);
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic void mlxsw_sp_pgt_entry_put(struct mlxsw_sp_pgt *pgt, u16 mid)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry *pgt_entry;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	pgt_entry = idr_find(&pgt->pgt_idr, mid);
17862306a36Sopenharmony_ci	if (WARN_ON(!pgt_entry))
17962306a36Sopenharmony_ci		return;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (list_empty(&pgt_entry->ports_list))
18262306a36Sopenharmony_ci		mlxsw_sp_pgt_entry_destroy(pgt, pgt_entry);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic void mlxsw_sp_pgt_smid2_port_set(char *smid2_pl, u16 local_port,
18662306a36Sopenharmony_ci					bool member)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	mlxsw_reg_smid2_port_set(smid2_pl, local_port, member);
18962306a36Sopenharmony_ci	mlxsw_reg_smid2_port_mask_set(smid2_pl, local_port, 1);
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic int
19362306a36Sopenharmony_cimlxsw_sp_pgt_entry_port_write(struct mlxsw_sp *mlxsw_sp,
19462306a36Sopenharmony_ci			      const struct mlxsw_sp_pgt_entry *pgt_entry,
19562306a36Sopenharmony_ci			      u16 local_port, bool member)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	char *smid2_pl;
19862306a36Sopenharmony_ci	int err;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
20162306a36Sopenharmony_ci	if (!smid2_pl)
20262306a36Sopenharmony_ci		return -ENOMEM;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	mlxsw_reg_smid2_pack(smid2_pl, pgt_entry->index, 0, 0,
20562306a36Sopenharmony_ci			     mlxsw_sp->pgt->smpe_index_valid,
20662306a36Sopenharmony_ci			     pgt_entry->smpe_index);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	mlxsw_sp_pgt_smid2_port_set(smid2_pl, local_port, member);
20962306a36Sopenharmony_ci	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid2), smid2_pl);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	kfree(smid2_pl);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	return err;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic struct mlxsw_sp_pgt_entry_port *
21762306a36Sopenharmony_cimlxsw_sp_pgt_entry_port_create(struct mlxsw_sp *mlxsw_sp,
21862306a36Sopenharmony_ci			       struct mlxsw_sp_pgt_entry *pgt_entry,
21962306a36Sopenharmony_ci			       u16 local_port)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
22262306a36Sopenharmony_ci	int err;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	pgt_entry_port = kzalloc(sizeof(*pgt_entry_port), GFP_KERNEL);
22562306a36Sopenharmony_ci	if (!pgt_entry_port)
22662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	err = mlxsw_sp_pgt_entry_port_write(mlxsw_sp, pgt_entry, local_port,
22962306a36Sopenharmony_ci					    true);
23062306a36Sopenharmony_ci	if (err)
23162306a36Sopenharmony_ci		goto err_pgt_entry_port_write;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	pgt_entry_port->local_port = local_port;
23462306a36Sopenharmony_ci	list_add(&pgt_entry_port->list, &pgt_entry->ports_list);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return pgt_entry_port;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cierr_pgt_entry_port_write:
23962306a36Sopenharmony_ci	kfree(pgt_entry_port);
24062306a36Sopenharmony_ci	return ERR_PTR(err);
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic void
24462306a36Sopenharmony_cimlxsw_sp_pgt_entry_port_destroy(struct mlxsw_sp *mlxsw_sp,
24562306a36Sopenharmony_ci				struct mlxsw_sp_pgt_entry *pgt_entry,
24662306a36Sopenharmony_ci				struct mlxsw_sp_pgt_entry_port *pgt_entry_port)
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	list_del(&pgt_entry_port->list);
25062306a36Sopenharmony_ci	mlxsw_sp_pgt_entry_port_write(mlxsw_sp, pgt_entry,
25162306a36Sopenharmony_ci				      pgt_entry_port->local_port, false);
25262306a36Sopenharmony_ci	kfree(pgt_entry_port);
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic int mlxsw_sp_pgt_entry_port_add(struct mlxsw_sp *mlxsw_sp, u16 mid,
25662306a36Sopenharmony_ci				       u16 smpe, u16 local_port)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
25962306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry *pgt_entry;
26062306a36Sopenharmony_ci	int err;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	mutex_lock(&mlxsw_sp->pgt->lock);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	pgt_entry = mlxsw_sp_pgt_entry_get(mlxsw_sp->pgt, mid, smpe);
26562306a36Sopenharmony_ci	if (IS_ERR(pgt_entry)) {
26662306a36Sopenharmony_ci		err = PTR_ERR(pgt_entry);
26762306a36Sopenharmony_ci		goto err_pgt_entry_get;
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	pgt_entry_port = mlxsw_sp_pgt_entry_port_create(mlxsw_sp, pgt_entry,
27162306a36Sopenharmony_ci							local_port);
27262306a36Sopenharmony_ci	if (IS_ERR(pgt_entry_port)) {
27362306a36Sopenharmony_ci		err = PTR_ERR(pgt_entry_port);
27462306a36Sopenharmony_ci		goto err_pgt_entry_port_get;
27562306a36Sopenharmony_ci	}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
27862306a36Sopenharmony_ci	return 0;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cierr_pgt_entry_port_get:
28162306a36Sopenharmony_ci	mlxsw_sp_pgt_entry_put(mlxsw_sp->pgt, mid);
28262306a36Sopenharmony_cierr_pgt_entry_get:
28362306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
28462306a36Sopenharmony_ci	return err;
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistatic void mlxsw_sp_pgt_entry_port_del(struct mlxsw_sp *mlxsw_sp,
28862306a36Sopenharmony_ci					u16 mid, u16 smpe, u16 local_port)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
29162306a36Sopenharmony_ci	struct mlxsw_sp_pgt_entry *pgt_entry;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	mutex_lock(&mlxsw_sp->pgt->lock);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	pgt_entry = idr_find(&mlxsw_sp->pgt->pgt_idr, mid);
29662306a36Sopenharmony_ci	if (!pgt_entry)
29762306a36Sopenharmony_ci		goto out;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	pgt_entry_port = mlxsw_sp_pgt_entry_port_lookup(pgt_entry, local_port);
30062306a36Sopenharmony_ci	if (!pgt_entry_port)
30162306a36Sopenharmony_ci		goto out;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	mlxsw_sp_pgt_entry_port_destroy(mlxsw_sp, pgt_entry, pgt_entry_port);
30462306a36Sopenharmony_ci	mlxsw_sp_pgt_entry_put(mlxsw_sp->pgt, mid);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ciout:
30762306a36Sopenharmony_ci	mutex_unlock(&mlxsw_sp->pgt->lock);
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ciint mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp *mlxsw_sp, u16 mid,
31162306a36Sopenharmony_ci				u16 smpe, u16 local_port, bool member)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	if (member)
31462306a36Sopenharmony_ci		return mlxsw_sp_pgt_entry_port_add(mlxsw_sp, mid, smpe,
31562306a36Sopenharmony_ci						   local_port);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	mlxsw_sp_pgt_entry_port_del(mlxsw_sp, mid, smpe, local_port);
31862306a36Sopenharmony_ci	return 0;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ciint mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	struct mlxsw_sp_pgt *pgt;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, PGT_SIZE))
32662306a36Sopenharmony_ci		return -EIO;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	pgt = kzalloc(sizeof(*mlxsw_sp->pgt), GFP_KERNEL);
32962306a36Sopenharmony_ci	if (!pgt)
33062306a36Sopenharmony_ci		return -ENOMEM;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	idr_init(&pgt->pgt_idr);
33362306a36Sopenharmony_ci	pgt->end_index = MLXSW_CORE_RES_GET(mlxsw_sp->core, PGT_SIZE);
33462306a36Sopenharmony_ci	mutex_init(&pgt->lock);
33562306a36Sopenharmony_ci	pgt->smpe_index_valid = mlxsw_sp->pgt_smpe_index_valid;
33662306a36Sopenharmony_ci	mlxsw_sp->pgt = pgt;
33762306a36Sopenharmony_ci	return 0;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_civoid mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	mutex_destroy(&mlxsw_sp->pgt->lock);
34362306a36Sopenharmony_ci	WARN_ON(!idr_is_empty(&mlxsw_sp->pgt->pgt_idr));
34462306a36Sopenharmony_ci	idr_destroy(&mlxsw_sp->pgt->pgt_idr);
34562306a36Sopenharmony_ci	kfree(mlxsw_sp->pgt);
34662306a36Sopenharmony_ci}
347