Skip to content

Commit fedae6d

Browse files
committed
Merge branch 'devlink-resource'
Jiri Pirko says: ==================== devlink: Add support for resource abstraction Arkadi says: Many of the ASIC's internal resources are limited and are shared between several hardware procedures. For example, unified hash-based memory can be used for many lookup purposes, like FDB and LPM. In many cases the user can provide a partitioning scheme for such a resource in order to perform fine tuning for his application. In such cases performing driver reload is needed for the changes to take place, thus this patchset also adds support for hot reload. Such an abstraction can be coupled with devlink's dpipe interface, which models the ASIC's pipeline as a graph of match/action tables. By modeling the hardware resource object, and by coupling it to several dpipe tables, further visibility can be achieved in order to debug ASIC-wide issues. The proposed interface will provide the user the ability to understand the limitations of the hardware, and receive notification regarding its occupancy. Furthermore, monitoring the resource occupancy can be done in real-time and can be useful in many cases. --- v2->v3 - Mix/Max/Gran attributes. - Add resource consumption per table. - Change basic resource unit to 'entry'. - ABI documentation. v1->v2 - Add resource size attribute. - Fix split bug. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents d98c8cc + f261708 commit fedae6d

File tree

12 files changed

+1213
-134
lines changed

12 files changed

+1213
-134
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
What: /kvd/
2+
Date: 08-Jan-2018
3+
KernelVersion: v4.16
4+
Contact: mlxsw@mellanox.com
5+
Description: The main database in the Spectrum device is a centralized
6+
KVD database used for many of the tables used to configure
7+
the chip including L2 FDB, L3 LPM, ECMP and more. The KVD
8+
is divided into two sections, the first is hash-based table
9+
and the second is a linear access table. The division
10+
between the linear and hash-based sections is static and
11+
require reload before the changes take effect.
12+
13+
What: /kvd/linear
14+
Date: 08-Jan-2018
15+
KernelVersion: v4.16
16+
Contact: mlxsw@mellanox.com
17+
Description: The linear section of the KVD is managed by software as a
18+
flat memory accessed using an index.
19+
20+
What: /kvd/hash_single
21+
Date: 08-Jan-2018
22+
KernelVersion: v4.16
23+
Contact: mlxsw@mellanox.com
24+
Description: The hash based section of the KVD is managed by the switch
25+
device. Used in case the key size is smaller or equal to
26+
64bit.
27+
28+
What: /kvd/hash_double
29+
Date: 08-Jan-2018
30+
KernelVersion: v4.16
31+
Contact: mlxsw@mellanox.com
32+
Description: The hash based section of the KVD is managed by the switch
33+
device. Used in case the key is larger than 64 bit.

drivers/net/ethernet/mellanox/mlxsw/core.c

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ struct mlxsw_core {
113113
struct mlxsw_thermal *thermal;
114114
struct mlxsw_core_port *ports;
115115
unsigned int max_ports;
116+
bool reload_fail;
116117
unsigned long driver_priv[0];
117118
/* driver_priv has to be always the last item */
118119
};
@@ -962,7 +963,28 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
962963
pool_type, p_cur, p_max);
963964
}
964965

966+
static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink)
967+
{
968+
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
969+
const struct mlxsw_bus *mlxsw_bus = mlxsw_core->bus;
970+
int err;
971+
972+
if (!mlxsw_bus->reset)
973+
return -EOPNOTSUPP;
974+
975+
mlxsw_core_bus_device_unregister(mlxsw_core, true);
976+
mlxsw_bus->reset(mlxsw_core->bus_priv);
977+
err = mlxsw_core_bus_device_register(mlxsw_core->bus_info,
978+
mlxsw_core->bus,
979+
mlxsw_core->bus_priv, true,
980+
devlink);
981+
if (err)
982+
mlxsw_core->reload_fail = true;
983+
return err;
984+
}
985+
965986
static const struct devlink_ops mlxsw_devlink_ops = {
987+
.reload = mlxsw_devlink_core_bus_device_reload,
966988
.port_type_set = mlxsw_devlink_port_type_set,
967989
.port_split = mlxsw_devlink_port_split,
968990
.port_unsplit = mlxsw_devlink_port_unsplit,
@@ -980,23 +1002,26 @@ static const struct devlink_ops mlxsw_devlink_ops = {
9801002

9811003
int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
9821004
const struct mlxsw_bus *mlxsw_bus,
983-
void *bus_priv)
1005+
void *bus_priv, bool reload,
1006+
struct devlink *devlink)
9841007
{
9851008
const char *device_kind = mlxsw_bus_info->device_kind;
9861009
struct mlxsw_core *mlxsw_core;
9871010
struct mlxsw_driver *mlxsw_driver;
988-
struct devlink *devlink;
9891011
size_t alloc_size;
9901012
int err;
9911013

9921014
mlxsw_driver = mlxsw_core_driver_get(device_kind);
9931015
if (!mlxsw_driver)
9941016
return -EINVAL;
995-
alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size;
996-
devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size);
997-
if (!devlink) {
998-
err = -ENOMEM;
999-
goto err_devlink_alloc;
1017+
1018+
if (!reload) {
1019+
alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size;
1020+
devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size);
1021+
if (!devlink) {
1022+
err = -ENOMEM;
1023+
goto err_devlink_alloc;
1024+
}
10001025
}
10011026

10021027
mlxsw_core = devlink_priv(devlink);
@@ -1012,6 +1037,12 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10121037
if (err)
10131038
goto err_bus_init;
10141039

1040+
if (mlxsw_driver->resources_register && !reload) {
1041+
err = mlxsw_driver->resources_register(mlxsw_core);
1042+
if (err)
1043+
goto err_register_resources;
1044+
}
1045+
10151046
err = mlxsw_ports_init(mlxsw_core);
10161047
if (err)
10171048
goto err_ports_init;
@@ -1032,9 +1063,11 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10321063
if (err)
10331064
goto err_emad_init;
10341065

1035-
err = devlink_register(devlink, mlxsw_bus_info->dev);
1036-
if (err)
1037-
goto err_devlink_register;
1066+
if (!reload) {
1067+
err = devlink_register(devlink, mlxsw_bus_info->dev);
1068+
if (err)
1069+
goto err_devlink_register;
1070+
}
10381071

10391072
err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon);
10401073
if (err)
@@ -1057,7 +1090,8 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10571090
mlxsw_thermal_fini(mlxsw_core->thermal);
10581091
err_thermal_init:
10591092
err_hwmon_init:
1060-
devlink_unregister(devlink);
1093+
if (!reload)
1094+
devlink_unregister(devlink);
10611095
err_devlink_register:
10621096
mlxsw_emad_fini(mlxsw_core);
10631097
err_emad_init:
@@ -1067,26 +1101,40 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10671101
err_ports_init:
10681102
mlxsw_bus->fini(bus_priv);
10691103
err_bus_init:
1070-
devlink_free(devlink);
1104+
if (!reload)
1105+
devlink_resources_unregister(devlink, NULL);
1106+
err_register_resources:
1107+
if (!reload)
1108+
devlink_free(devlink);
10711109
err_devlink_alloc:
10721110
mlxsw_core_driver_put(device_kind);
10731111
return err;
10741112
}
10751113
EXPORT_SYMBOL(mlxsw_core_bus_device_register);
10761114

1077-
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
1115+
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
1116+
bool reload)
10781117
{
10791118
const char *device_kind = mlxsw_core->bus_info->device_kind;
10801119
struct devlink *devlink = priv_to_devlink(mlxsw_core);
10811120

1121+
if (mlxsw_core->reload_fail)
1122+
goto reload_fail;
1123+
10821124
if (mlxsw_core->driver->fini)
10831125
mlxsw_core->driver->fini(mlxsw_core);
10841126
mlxsw_thermal_fini(mlxsw_core->thermal);
1085-
devlink_unregister(devlink);
1127+
if (!reload)
1128+
devlink_unregister(devlink);
10861129
mlxsw_emad_fini(mlxsw_core);
10871130
kfree(mlxsw_core->lag.mapping);
10881131
mlxsw_ports_fini(mlxsw_core);
1132+
if (!reload)
1133+
devlink_resources_unregister(devlink, NULL);
10891134
mlxsw_core->bus->fini(mlxsw_core->bus_priv);
1135+
if (reload)
1136+
return;
1137+
reload_fail:
10901138
devlink_free(devlink);
10911139
mlxsw_core_driver_put(device_kind);
10921140
}
@@ -1791,6 +1839,22 @@ void mlxsw_core_flush_owq(void)
17911839
}
17921840
EXPORT_SYMBOL(mlxsw_core_flush_owq);
17931841

1842+
int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
1843+
const struct mlxsw_config_profile *profile,
1844+
u64 *p_single_size, u64 *p_double_size,
1845+
u64 *p_linear_size)
1846+
{
1847+
struct mlxsw_driver *driver = mlxsw_core->driver;
1848+
1849+
if (!driver->kvd_sizes_get)
1850+
return -EINVAL;
1851+
1852+
return driver->kvd_sizes_get(mlxsw_core, profile,
1853+
p_single_size, p_double_size,
1854+
p_linear_size);
1855+
}
1856+
EXPORT_SYMBOL(mlxsw_core_kvd_sizes_get);
1857+
17941858
static int __init mlxsw_core_module_init(void)
17951859
{
17961860
int err;

drivers/net/ethernet/mellanox/mlxsw/core.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver);
6666

6767
int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
6868
const struct mlxsw_bus *mlxsw_bus,
69-
void *bus_priv);
70-
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core);
69+
void *bus_priv, bool reload,
70+
struct devlink *devlink);
71+
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, bool reload);
7172

7273
struct mlxsw_tx_info {
7374
u8 local_port;
@@ -308,10 +309,20 @@ struct mlxsw_driver {
308309
u32 *p_cur, u32 *p_max);
309310
void (*txhdr_construct)(struct sk_buff *skb,
310311
const struct mlxsw_tx_info *tx_info);
312+
int (*resources_register)(struct mlxsw_core *mlxsw_core);
313+
int (*kvd_sizes_get)(struct mlxsw_core *mlxsw_core,
314+
const struct mlxsw_config_profile *profile,
315+
u64 *p_single_size, u64 *p_double_size,
316+
u64 *p_linear_size);
311317
u8 txhdr_len;
312318
const struct mlxsw_config_profile *profile;
313319
};
314320

321+
int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
322+
const struct mlxsw_config_profile *profile,
323+
u64 *p_single_size, u64 *p_double_size,
324+
u64 *p_linear_size);
325+
315326
bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
316327
enum mlxsw_res_id res_id);
317328

@@ -332,6 +343,7 @@ struct mlxsw_bus {
332343
const struct mlxsw_config_profile *profile,
333344
struct mlxsw_res *res);
334345
void (*fini)(void *bus_priv);
346+
void (*reset)(void *bus_priv);
335347
bool (*skb_transmit_busy)(void *bus_priv,
336348
const struct mlxsw_tx_info *tx_info);
337349
int (*skb_transmit)(void *bus_priv, struct sk_buff *skb,

drivers/net/ethernet/mellanox/mlxsw/i2c.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,8 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
539539
mlxsw_i2c->dev = &client->dev;
540540

541541
err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
542-
&mlxsw_i2c_bus, mlxsw_i2c);
542+
&mlxsw_i2c_bus, mlxsw_i2c, false,
543+
NULL);
543544
if (err) {
544545
dev_err(&client->dev, "Fail to register core bus\n");
545546
return err;
@@ -557,7 +558,7 @@ static int mlxsw_i2c_remove(struct i2c_client *client)
557558
{
558559
struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
559560

560-
mlxsw_core_bus_device_unregister(mlxsw_i2c->core);
561+
mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false);
561562
mutex_destroy(&mlxsw_i2c->cmd.lock);
562563

563564
return 0;

0 commit comments

Comments
 (0)