devlink.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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. struct netlink_ext_ack *extack)
  150. {
  151. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  152. if (!ds->ops->devlink_param_get)
  153. return -EOPNOTSUPP;
  154. return ds->ops->devlink_param_get(ds, id, ctx);
  155. }
  156. EXPORT_SYMBOL_GPL(dsa_devlink_param_get);
  157. int dsa_devlink_param_set(struct devlink *dl, u32 id,
  158. struct devlink_param_gset_ctx *ctx,
  159. struct netlink_ext_ack *extack)
  160. {
  161. struct dsa_switch *ds = dsa_devlink_to_ds(dl);
  162. if (!ds->ops->devlink_param_set)
  163. return -EOPNOTSUPP;
  164. return ds->ops->devlink_param_set(ds, id, ctx);
  165. }
  166. EXPORT_SYMBOL_GPL(dsa_devlink_param_set);
  167. int dsa_devlink_params_register(struct dsa_switch *ds,
  168. const struct devlink_param *params,
  169. size_t params_count)
  170. {
  171. return devlink_params_register(ds->devlink, params, params_count);
  172. }
  173. EXPORT_SYMBOL_GPL(dsa_devlink_params_register);
  174. void dsa_devlink_params_unregister(struct dsa_switch *ds,
  175. const struct devlink_param *params,
  176. size_t params_count)
  177. {
  178. devlink_params_unregister(ds->devlink, params, params_count);
  179. }
  180. EXPORT_SYMBOL_GPL(dsa_devlink_params_unregister);
  181. int dsa_devlink_resource_register(struct dsa_switch *ds,
  182. const char *resource_name,
  183. u64 resource_size,
  184. u64 resource_id,
  185. u64 parent_resource_id,
  186. const struct devlink_resource_size_params *size_params)
  187. {
  188. int ret;
  189. devl_lock(ds->devlink);
  190. ret = devl_resource_register(ds->devlink, resource_name, resource_size,
  191. resource_id, parent_resource_id,
  192. size_params);
  193. devl_unlock(ds->devlink);
  194. return ret;
  195. }
  196. EXPORT_SYMBOL_GPL(dsa_devlink_resource_register);
  197. void dsa_devlink_resources_unregister(struct dsa_switch *ds)
  198. {
  199. devlink_resources_unregister(ds->devlink);
  200. }
  201. EXPORT_SYMBOL_GPL(dsa_devlink_resources_unregister);
  202. void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
  203. u64 resource_id,
  204. devlink_resource_occ_get_t *occ_get,
  205. void *occ_get_priv)
  206. {
  207. devl_lock(ds->devlink);
  208. devl_resource_occ_get_register(ds->devlink, resource_id, occ_get,
  209. occ_get_priv);
  210. devl_unlock(ds->devlink);
  211. }
  212. EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_register);
  213. void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
  214. u64 resource_id)
  215. {
  216. devl_lock(ds->devlink);
  217. devl_resource_occ_get_unregister(ds->devlink, resource_id);
  218. devl_unlock(ds->devlink);
  219. }
  220. EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_unregister);
  221. struct devlink_region *
  222. dsa_devlink_region_create(struct dsa_switch *ds,
  223. const struct devlink_region_ops *ops,
  224. u32 region_max_snapshots, u64 region_size)
  225. {
  226. return devlink_region_create(ds->devlink, ops, region_max_snapshots,
  227. region_size);
  228. }
  229. EXPORT_SYMBOL_GPL(dsa_devlink_region_create);
  230. struct devlink_region *
  231. dsa_devlink_port_region_create(struct dsa_switch *ds,
  232. int port,
  233. const struct devlink_port_region_ops *ops,
  234. u32 region_max_snapshots, u64 region_size)
  235. {
  236. struct dsa_port *dp = dsa_to_port(ds, port);
  237. return devlink_port_region_create(&dp->devlink_port, ops,
  238. region_max_snapshots,
  239. region_size);
  240. }
  241. EXPORT_SYMBOL_GPL(dsa_devlink_port_region_create);
  242. void dsa_devlink_region_destroy(struct devlink_region *region)
  243. {
  244. devlink_region_destroy(region);
  245. }
  246. EXPORT_SYMBOL_GPL(dsa_devlink_region_destroy);
  247. int dsa_port_devlink_setup(struct dsa_port *dp)
  248. {
  249. struct devlink_port *dlp = &dp->devlink_port;
  250. struct dsa_switch_tree *dst = dp->ds->dst;
  251. struct devlink_port_attrs attrs = {};
  252. struct devlink *dl = dp->ds->devlink;
  253. struct dsa_switch *ds = dp->ds;
  254. const unsigned char *id;
  255. unsigned char len;
  256. int err;
  257. memset(dlp, 0, sizeof(*dlp));
  258. devlink_port_init(dl, dlp);
  259. if (ds->ops->port_setup) {
  260. err = ds->ops->port_setup(ds, dp->index);
  261. if (err)
  262. return err;
  263. }
  264. id = (const unsigned char *)&dst->index;
  265. len = sizeof(dst->index);
  266. attrs.phys.port_number = dp->index;
  267. memcpy(attrs.switch_id.id, id, len);
  268. attrs.switch_id.id_len = len;
  269. switch (dp->type) {
  270. case DSA_PORT_TYPE_UNUSED:
  271. attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED;
  272. break;
  273. case DSA_PORT_TYPE_CPU:
  274. attrs.flavour = DEVLINK_PORT_FLAVOUR_CPU;
  275. break;
  276. case DSA_PORT_TYPE_DSA:
  277. attrs.flavour = DEVLINK_PORT_FLAVOUR_DSA;
  278. break;
  279. case DSA_PORT_TYPE_USER:
  280. attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
  281. break;
  282. }
  283. devlink_port_attrs_set(dlp, &attrs);
  284. err = devlink_port_register(dl, dlp, dp->index);
  285. if (err) {
  286. if (ds->ops->port_teardown)
  287. ds->ops->port_teardown(ds, dp->index);
  288. return err;
  289. }
  290. return 0;
  291. }
  292. void dsa_port_devlink_teardown(struct dsa_port *dp)
  293. {
  294. struct devlink_port *dlp = &dp->devlink_port;
  295. struct dsa_switch *ds = dp->ds;
  296. devlink_port_unregister(dlp);
  297. if (ds->ops->port_teardown)
  298. ds->ops->port_teardown(ds, dp->index);
  299. devlink_port_fini(dlp);
  300. }
  301. void dsa_switch_devlink_register(struct dsa_switch *ds)
  302. {
  303. devlink_register(ds->devlink);
  304. }
  305. void dsa_switch_devlink_unregister(struct dsa_switch *ds)
  306. {
  307. devlink_unregister(ds->devlink);
  308. }
  309. int dsa_switch_devlink_alloc(struct dsa_switch *ds)
  310. {
  311. struct dsa_devlink_priv *dl_priv;
  312. struct devlink *dl;
  313. /* Add the switch to devlink before calling setup, so that setup can
  314. * add dpipe tables
  315. */
  316. dl = devlink_alloc(&dsa_devlink_ops, sizeof(*dl_priv), ds->dev);
  317. if (!dl)
  318. return -ENOMEM;
  319. ds->devlink = dl;
  320. dl_priv = devlink_priv(ds->devlink);
  321. dl_priv->ds = ds;
  322. return 0;
  323. }
  324. void dsa_switch_devlink_free(struct dsa_switch *ds)
  325. {
  326. devlink_free(ds->devlink);
  327. ds->devlink = NULL;
  328. }