1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
7 /* Since devlink regions have a fixed size and the static config has a variable
8 * size, we need to calculate the maximum possible static config size by
9 * creating a dummy config with all table entries populated to the max, and get
10 * its packed length. This is done dynamically as opposed to simply hardcoding
11 * a number, since currently not all static config tables are implemented, so
12 * we are avoiding a possible code desynchronization.
14 static size_t sja1105_static_config_get_max_size(struct sja1105_private
*priv
)
16 struct sja1105_static_config config
;
17 enum sja1105_blk_idx blk_idx
;
20 rc
= sja1105_static_config_init(&config
,
21 priv
->info
->static_ops
,
22 priv
->info
->device_id
);
26 for (blk_idx
= 0; blk_idx
< BLK_IDX_MAX
; blk_idx
++) {
27 struct sja1105_table
*table
= &config
.tables
[blk_idx
];
29 table
->entry_count
= table
->ops
->max_entry_count
;
32 return sja1105_static_config_get_length(&config
);
36 sja1105_region_static_config_snapshot(struct devlink
*dl
,
37 const struct devlink_region_ops
*ops
,
38 struct netlink_ext_ack
*extack
,
41 struct dsa_switch
*ds
= dsa_devlink_to_ds(dl
);
42 struct sja1105_private
*priv
= ds
->priv
;
45 len
= sja1105_static_config_get_length(&priv
->static_config
);
46 max_len
= sja1105_static_config_get_max_size(priv
);
48 *data
= kcalloc(max_len
, sizeof(u8
), GFP_KERNEL
);
52 return static_config_buf_prepare_for_upload(priv
, *data
, len
);
55 static struct devlink_region_ops sja1105_region_static_config_ops
= {
56 .name
= "static-config",
57 .snapshot
= sja1105_region_static_config_snapshot
,
61 enum sja1105_region_id
{
62 SJA1105_REGION_STATIC_CONFIG
= 0,
65 struct sja1105_region
{
66 const struct devlink_region_ops
*ops
;
67 size_t (*get_size
)(struct sja1105_private
*priv
);
70 static struct sja1105_region sja1105_regions
[] = {
71 [SJA1105_REGION_STATIC_CONFIG
] = {
72 .ops
= &sja1105_region_static_config_ops
,
73 .get_size
= sja1105_static_config_get_max_size
,
77 static int sja1105_setup_devlink_regions(struct dsa_switch
*ds
)
79 int i
, num_regions
= ARRAY_SIZE(sja1105_regions
);
80 struct sja1105_private
*priv
= ds
->priv
;
81 const struct devlink_region_ops
*ops
;
82 struct devlink_region
*region
;
85 priv
->regions
= kcalloc(num_regions
, sizeof(struct devlink_region
*),
90 for (i
= 0; i
< num_regions
; i
++) {
91 size
= sja1105_regions
[i
].get_size(priv
);
92 ops
= sja1105_regions
[i
].ops
;
94 region
= dsa_devlink_region_create(ds
, ops
, 1, size
);
97 dsa_devlink_region_destroy(priv
->regions
[i
]);
100 return PTR_ERR(region
);
103 priv
->regions
[i
] = region
;
109 static void sja1105_teardown_devlink_regions(struct dsa_switch
*ds
)
111 int i
, num_regions
= ARRAY_SIZE(sja1105_regions
);
112 struct sja1105_private
*priv
= ds
->priv
;
114 for (i
= 0; i
< num_regions
; i
++)
115 dsa_devlink_region_destroy(priv
->regions
[i
]);
117 kfree(priv
->regions
);
120 int sja1105_devlink_info_get(struct dsa_switch
*ds
,
121 struct devlink_info_req
*req
,
122 struct netlink_ext_ack
*extack
)
124 struct sja1105_private
*priv
= ds
->priv
;
126 return devlink_info_version_fixed_put(req
,
127 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID
,
131 int sja1105_devlink_setup(struct dsa_switch
*ds
)
133 return sja1105_setup_devlink_regions(ds
);
136 void sja1105_devlink_teardown(struct dsa_switch
*ds
)
138 sja1105_teardown_devlink_regions(ds
);