devlink.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * DSA devlink handling
  4. */
  5. #include <net/dsa.h>
  6. #include <net/devlink.h>
  7. #include "devlink.h"
  8. static int dsa_devlink_info_get(struct devlink *dl,
  9. struct devlink_info_req *req,
  10. struct netlink_ext_ack *extack)
  11. {
  12. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  13. if (ds->ops->devlink_info_get)
  14. return ds->ops->devlink_info_get(ds, req, extack);
  15. return -EOPNOTSUPP;
  16. }
  17. static int dsa_devlink_sb_pool_get(struct devlink *dl,
  18. unsigned int sb_index, u16 pool_index,
  19. struct devlink_sb_pool_info *pool_info)
  20. {
  21. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  22. if (!ds->ops->devlink_sb_pool_get)
  23. return -EOPNOTSUPP;
  24. return ds->ops->devlink_sb_pool_get(ds, sb_index, pool_index,
  25. pool_info);
  26. }
  27. static int dsa_devlink_sb_pool_set(struct devlink *dl, unsigned int sb_index,
  28. u16 pool_index, u32 size,
  29. enum devlink_sb_threshold_type threshold_type,
  30. struct netlink_ext_ack *extack)
  31. {
  32. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  33. if (!ds->ops->devlink_sb_pool_set)
  34. return -EOPNOTSUPP;
  35. return ds->ops->devlink_sb_pool_set(ds, sb_index, pool_index, size,
  36. threshold_type, extack);
  37. }
  38. static int dsa_devlink_sb_port_pool_get(struct devlink_port *dlp,
  39. unsigned int sb_index, u16 pool_index,
  40. u32 *p_threshold)
  41. {
  42. struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
  43. int port = dsa_devlink_port_to_port(dlp);
  44. if (!ds->ops->devlink_sb_port_pool_get)
  45. return -EOPNOTSUPP;
  46. return ds->ops->devlink_sb_port_pool_get(ds, port, sb_index,
  47. pool_index, p_threshold);
  48. }
  49. static int dsa_devlink_sb_port_pool_set(struct devlink_port *dlp,
  50. unsigned int sb_index, u16 pool_index,
  51. u32 threshold,
  52. struct netlink_ext_ack *extack)
  53. {
  54. struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
  55. int port = dsa_devlink_port_to_port(dlp);
  56. if (!ds->ops->devlink_sb_port_pool_set)
  57. return -EOPNOTSUPP;
  58. return ds->ops->devlink_sb_port_pool_set(ds, port, sb_index,
  59. pool_index, threshold, extack);
  60. }
  61. static int
  62. dsa_devlink_sb_tc_pool_bind_get(struct devlink_port *dlp,
  63. unsigned int sb_index, u16 tc_index,
  64. enum devlink_sb_pool_type pool_type,
  65. u16 *p_pool_index, u32 *p_threshold)
  66. {
  67. struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
  68. int port = dsa_devlink_port_to_port(dlp);
  69. if (!ds->ops->devlink_sb_tc_pool_bind_get)
  70. return -EOPNOTSUPP;
  71. return ds->ops->devlink_sb_tc_pool_bind_get(ds, port, sb_index,
  72. tc_index, pool_type,
  73. p_pool_index, p_threshold);
  74. }
  75. static int
  76. dsa_devlink_sb_tc_pool_bind_set(struct devlink_port *dlp,
  77. unsigned int sb_index, u16 tc_index,
  78. enum devlink_sb_pool_type pool_type,
  79. u16 pool_index, u32 threshold,
  80. struct netlink_ext_ack *extack)
  81. {
  82. struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
  83. int port = dsa_devlink_port_to_port(dlp);
  84. if (!ds->ops->devlink_sb_tc_pool_bind_set)
  85. return -EOPNOTSUPP;
  86. return ds->ops->devlink_sb_tc_pool_bind_set(ds, port, sb_index,
  87. tc_index, pool_type,
  88. pool_index, threshold,
  89. extack);
  90. }
  91. static int dsa_devlink_sb_occ_snapshot(struct devlink *dl,
  92. unsigned int sb_index)
  93. {
  94. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  95. if (!ds->ops->devlink_sb_occ_snapshot)
  96. return -EOPNOTSUPP;
  97. return ds->ops->devlink_sb_occ_snapshot(ds, sb_index);
  98. }
  99. static int dsa_devlink_sb_occ_max_clear(struct devlink *dl,
  100. unsigned int sb_index)
  101. {
  102. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  103. if (!ds->ops->devlink_sb_occ_max_clear)
  104. return -EOPNOTSUPP;
  105. return ds->ops->devlink_sb_occ_max_clear(ds, sb_index);
  106. }
  107. static int dsa_devlink_sb_occ_port_pool_get(struct devlink_port *dlp,
  108. unsigned int sb_index,
  109. u16 pool_index, u32 *p_cur,
  110. u32 *p_max)
  111. {
  112. struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
  113. int port = dsa_devlink_port_to_port(dlp);
  114. if (!ds->ops->devlink_sb_occ_port_pool_get)
  115. return -EOPNOTSUPP;
  116. return ds->ops->devlink_sb_occ_port_pool_get(ds, port, sb_index,
  117. pool_index, p_cur, p_max);
  118. }
  119. static int
  120. dsa_devlink_sb_occ_tc_port_bind_get(struct devlink_port *dlp,
  121. unsigned int sb_index, u16 tc_index,
  122. enum devlink_sb_pool_type pool_type,
  123. u32 *p_cur, u32 *p_max)
  124. {
  125. struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
  126. int port = dsa_devlink_port_to_port(dlp);
  127. if (!ds->ops->devlink_sb_occ_tc_port_bind_get)
  128. return -EOPNOTSUPP;
  129. return ds->ops->devlink_sb_occ_tc_port_bind_get(ds, port,
  130. sb_index, tc_index,
  131. pool_type, p_cur,
  132. p_max);
  133. }
  134. static const struct devlink_ops dsa_devlink_ops = {
  135. .info_get = dsa_devlink_info_get,
  136. .sb_pool_get = dsa_devlink_sb_pool_get,
  137. .sb_pool_set = dsa_devlink_sb_pool_set,
  138. .sb_port_pool_get = dsa_devlink_sb_port_pool_get,
  139. .sb_port_pool_set = dsa_devlink_sb_port_pool_set,
  140. .sb_tc_pool_bind_get = dsa_devlink_sb_tc_pool_bind_get,
  141. .sb_tc_pool_bind_set = dsa_devlink_sb_tc_pool_bind_set,
  142. .sb_occ_snapshot = dsa_devlink_sb_occ_snapshot,
  143. .sb_occ_max_clear = dsa_devlink_sb_occ_max_clear,
  144. .sb_occ_port_pool_get = dsa_devlink_sb_occ_port_pool_get,
  145. .sb_occ_tc_port_bind_get = dsa_devlink_sb_occ_tc_port_bind_get,
  146. };
  147. int dsa_devlink_param_get(struct devlink *dl, u32 id,
  148. struct devlink_param_gset_ctx *ctx)
  149. {
  150. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  151. if (!ds->ops->devlink_param_get)
  152. return -EOPNOTSUPP;
  153. return ds->ops->devlink_param_get(ds, id, ctx);
  154. }
  155. EXPORT_SYMBOL_GPL(dsa_devlink_param_get);
  156. int dsa_devlink_param_set(struct devlink *dl, u32 id,
  157. struct devlink_param_gset_ctx *ctx,
  158. struct netlink_ext_ack *extack)
  159. {
  160. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  161. if (!ds->ops->devlink_param_set)
  162. return -EOPNOTSUPP;
  163. return ds->ops->devlink_param_set(ds, id, ctx);
  164. }
  165. EXPORT_SYMBOL_GPL(dsa_devlink_param_set);
  166. int dsa_devlink_params_register(struct dsa_switch *ds,
  167. const struct devlink_param *params,
  168. size_t params_count)
  169. {
  170. return devlink_params_register(ds->devlink, params, params_count);
  171. }
  172. EXPORT_SYMBOL_GPL(dsa_devlink_params_register);
  173. void dsa_devlink_params_unregister(struct dsa_switch *ds,
  174. const struct devlink_param *params,
  175. size_t params_count)
  176. {
  177. devlink_params_unregister(ds->devlink, params, params_count);
  178. }
  179. EXPORT_SYMBOL_GPL(dsa_devlink_params_unregister);
  180. int dsa_devlink_resource_register(struct dsa_switch *ds,
  181. const char *resource_name,
  182. u64 resource_size,
  183. u64 resource_id,
  184. u64 parent_resource_id,
  185. const struct devlink_resource_size_params *size_params)
  186. {
  187. return devlink_resource_register(ds->devlink, resource_name,
  188. resource_size, resource_id,
  189. parent_resource_id,
  190. size_params);
  191. }
  192. EXPORT_SYMBOL_GPL(dsa_devlink_resource_register);
  193. void dsa_devlink_resources_unregister(struct dsa_switch *ds)
  194. {
  195. devlink_resources_unregister(ds->devlink);
  196. }
  197. EXPORT_SYMBOL_GPL(dsa_devlink_resources_unregister);
  198. void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
  199. u64 resource_id,
  200. devlink_resource_occ_get_t *occ_get,
  201. void *occ_get_priv)
  202. {
  203. return devlink_resource_occ_get_register(ds->devlink, resource_id,
  204. occ_get, occ_get_priv);
  205. }
  206. EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_register);
  207. void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
  208. u64 resource_id)
  209. {
  210. devlink_resource_occ_get_unregister(ds->devlink, resource_id);
  211. }
  212. EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_unregister);
  213. struct devlink_region *
  214. dsa_devlink_region_create(struct dsa_switch *ds,
  215. const struct devlink_region_ops *ops,
  216. u32 region_max_snapshots, u64 region_size)
  217. {
  218. return devlink_region_create(ds->devlink, ops, region_max_snapshots,
  219. region_size);
  220. }
  221. EXPORT_SYMBOL_GPL(dsa_devlink_region_create);
  222. struct devlink_region *
  223. dsa_devlink_port_region_create(struct dsa_switch *ds,
  224. int port,
  225. const struct devlink_port_region_ops *ops,
  226. u32 region_max_snapshots, u64 region_size)
  227. {
  228. struct dsa_port *dp = dsa_to_port(ds, port);
  229. return devlink_port_region_create(&dp->devlink_port, ops,
  230. region_max_snapshots,
  231. region_size);
  232. }
  233. EXPORT_SYMBOL_GPL(dsa_devlink_port_region_create);
  234. void dsa_devlink_region_destroy(struct devlink_region *region)
  235. {
  236. devlink_region_destroy(region);
  237. }
  238. EXPORT_SYMBOL_GPL(dsa_devlink_region_destroy);
  239. int dsa_port_devlink_setup(struct dsa_port *dp)
  240. {
  241. struct devlink_port *dlp = &dp->devlink_port;
  242. struct dsa_switch_tree *dst = dp->ds->dst;
  243. struct devlink_port_attrs attrs = {};
  244. struct devlink *dl = dp->ds->devlink;
  245. struct dsa_switch *ds = dp->ds;
  246. const unsigned char *id;
  247. unsigned char len;
  248. int err;
  249. memset(dlp, 0, sizeof(*dlp));
  250. devlink_port_init(dl, dlp);
  251. if (ds->ops->port_setup) {
  252. err = ds->ops->port_setup(ds, dp->index);
  253. if (err)
  254. return err;
  255. }
  256. id = (const unsigned char *)&dst->index;
  257. len = sizeof(dst->index);
  258. attrs.phys.port_number = dp->index;
  259. memcpy(attrs.switch_id.id, id, len);
  260. attrs.switch_id.id_len = len;
  261. switch (dp->type) {
  262. case DSA_PORT_TYPE_UNUSED:
  263. attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED;
  264. break;
  265. case DSA_PORT_TYPE_CPU:
  266. attrs.flavour = DEVLINK_PORT_FLAVOUR_CPU;
  267. break;
  268. case DSA_PORT_TYPE_DSA:
  269. attrs.flavour = DEVLINK_PORT_FLAVOUR_DSA;
  270. break;
  271. case DSA_PORT_TYPE_USER:
  272. attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
  273. break;
  274. }
  275. devlink_port_attrs_set(dlp, &attrs);
  276. err = devlink_port_register(dl, dlp, dp->index);
  277. if (err) {
  278. if (ds->ops->port_teardown)
  279. ds->ops->port_teardown(ds, dp->index);
  280. return err;
  281. }
  282. return 0;
  283. }
  284. void dsa_port_devlink_teardown(struct dsa_port *dp)
  285. {
  286. struct devlink_port *dlp = &dp->devlink_port;
  287. struct dsa_switch *ds = dp->ds;
  288. devlink_port_unregister(dlp);
  289. if (ds->ops->port_teardown)
  290. ds->ops->port_teardown(ds, dp->index);
  291. devlink_port_fini(dlp);
  292. }
  293. void dsa_switch_devlink_register(struct dsa_switch *ds)
  294. {
  295. devlink_register(ds->devlink);
  296. }
  297. void dsa_switch_devlink_unregister(struct dsa_switch *ds)
  298. {
  299. devlink_unregister(ds->devlink);
  300. }
  301. int dsa_switch_devlink_alloc(struct dsa_switch *ds)
  302. {
  303. struct dsa_devlink_priv *dl_priv;
  304. struct devlink *dl;
  305. /* Add the switch to devlink before calling setup, so that setup can
  306. * add dpipe tables
  307. */
  308. dl = devlink_alloc(&dsa_devlink_ops, sizeof(*dl_priv), ds->dev);
  309. if (!dl)
  310. return -ENOMEM;
  311. ds->devlink = dl;
  312. dl_priv = devlink_priv(ds->devlink);
  313. dl_priv->ds = ds;
  314. return 0;
  315. }
  316. void dsa_switch_devlink_free(struct dsa_switch *ds)
  317. {
  318. devlink_free(ds->devlink);
  319. ds->devlink = NULL;
  320. }