spectrum_buffers.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
  3. * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
  4. * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the names of the copyright holders nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * Alternatively, this software may be distributed under the terms of the
  19. * GNU General Public License ("GPL") version 2 as published by the Free
  20. * Software Foundation.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <linux/kernel.h>
  35. #include <linux/types.h>
  36. #include "spectrum.h"
  37. #include "core.h"
  38. #include "port.h"
  39. #include "reg.h"
  40. struct mlxsw_sp_pb {
  41. u8 index;
  42. u16 size;
  43. };
  44. #define MLXSW_SP_PB(_index, _size) \
  45. { \
  46. .index = _index, \
  47. .size = _size, \
  48. }
  49. static const struct mlxsw_sp_pb mlxsw_sp_pbs[] = {
  50. MLXSW_SP_PB(0, 208),
  51. MLXSW_SP_PB(1, 208),
  52. MLXSW_SP_PB(2, 208),
  53. MLXSW_SP_PB(3, 208),
  54. MLXSW_SP_PB(4, 208),
  55. MLXSW_SP_PB(5, 208),
  56. MLXSW_SP_PB(6, 208),
  57. MLXSW_SP_PB(7, 208),
  58. MLXSW_SP_PB(9, 208),
  59. };
  60. #define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs)
  61. static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
  62. {
  63. char pbmc_pl[MLXSW_REG_PBMC_LEN];
  64. int i;
  65. mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port,
  66. 0xffff, 0xffff / 2);
  67. for (i = 0; i < MLXSW_SP_PBS_LEN; i++) {
  68. const struct mlxsw_sp_pb *pb;
  69. pb = &mlxsw_sp_pbs[i];
  70. mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pb->index, pb->size);
  71. }
  72. return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core,
  73. MLXSW_REG(pbmc), pbmc_pl);
  74. }
  75. #define MLXSW_SP_SB_BYTES_PER_CELL 96
  76. struct mlxsw_sp_sb_pool {
  77. u8 pool;
  78. enum mlxsw_reg_sbpr_dir dir;
  79. enum mlxsw_reg_sbpr_mode mode;
  80. u32 size;
  81. };
  82. #define MLXSW_SP_SB_POOL_INGRESS_SIZE \
  83. ((15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) / \
  84. MLXSW_SP_SB_BYTES_PER_CELL)
  85. #define MLXSW_SP_SB_POOL_EGRESS_SIZE \
  86. ((14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) / \
  87. MLXSW_SP_SB_BYTES_PER_CELL)
  88. #define MLXSW_SP_SB_POOL(_pool, _dir, _mode, _size) \
  89. { \
  90. .pool = _pool, \
  91. .dir = _dir, \
  92. .mode = _mode, \
  93. .size = _size, \
  94. }
  95. #define MLXSW_SP_SB_POOL_INGRESS(_pool, _size) \
  96. MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_INGRESS, \
  97. MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
  98. #define MLXSW_SP_SB_POOL_EGRESS(_pool, _size) \
  99. MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_EGRESS, \
  100. MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
  101. static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = {
  102. MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_SB_POOL_INGRESS_SIZE),
  103. MLXSW_SP_SB_POOL_INGRESS(1, 0),
  104. MLXSW_SP_SB_POOL_INGRESS(2, 0),
  105. MLXSW_SP_SB_POOL_INGRESS(3, 0),
  106. MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_SB_POOL_EGRESS_SIZE),
  107. MLXSW_SP_SB_POOL_EGRESS(1, 0),
  108. MLXSW_SP_SB_POOL_EGRESS(2, 0),
  109. MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_SB_POOL_EGRESS_SIZE),
  110. };
  111. #define MLXSW_SP_SB_POOLS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools)
  112. static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
  113. {
  114. char sbpr_pl[MLXSW_REG_SBPR_LEN];
  115. int i;
  116. int err;
  117. for (i = 0; i < MLXSW_SP_SB_POOLS_LEN; i++) {
  118. const struct mlxsw_sp_sb_pool *pool;
  119. pool = &mlxsw_sp_sb_pools[i];
  120. mlxsw_reg_sbpr_pack(sbpr_pl, pool->pool, pool->dir,
  121. pool->mode, pool->size);
  122. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
  123. if (err)
  124. return err;
  125. }
  126. return 0;
  127. }
  128. struct mlxsw_sp_sb_cm {
  129. union {
  130. u8 pg;
  131. u8 tc;
  132. } u;
  133. enum mlxsw_reg_sbcm_dir dir;
  134. u32 min_buff;
  135. u32 max_buff;
  136. u8 pool;
  137. };
  138. #define MLXSW_SP_SB_CM(_pg_tc, _dir, _min_buff, _max_buff, _pool) \
  139. { \
  140. .u.pg = _pg_tc, \
  141. .dir = _dir, \
  142. .min_buff = _min_buff, \
  143. .max_buff = _max_buff, \
  144. .pool = _pool, \
  145. }
  146. #define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff) \
  147. MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBCM_DIR_INGRESS, \
  148. _min_buff, _max_buff, 0)
  149. #define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff) \
  150. MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, \
  151. _min_buff, _max_buff, 0)
  152. #define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc) \
  153. MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, 104, 2, 3)
  154. static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = {
  155. MLXSW_SP_SB_CM_INGRESS(0, 10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8),
  156. MLXSW_SP_SB_CM_INGRESS(1, 0, 0),
  157. MLXSW_SP_SB_CM_INGRESS(2, 0, 0),
  158. MLXSW_SP_SB_CM_INGRESS(3, 0, 0),
  159. MLXSW_SP_SB_CM_INGRESS(4, 0, 0),
  160. MLXSW_SP_SB_CM_INGRESS(5, 0, 0),
  161. MLXSW_SP_SB_CM_INGRESS(6, 0, 0),
  162. MLXSW_SP_SB_CM_INGRESS(7, 0, 0),
  163. MLXSW_SP_SB_CM_INGRESS(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff),
  164. MLXSW_SP_SB_CM_EGRESS(0, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  165. MLXSW_SP_SB_CM_EGRESS(1, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  166. MLXSW_SP_SB_CM_EGRESS(2, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  167. MLXSW_SP_SB_CM_EGRESS(3, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  168. MLXSW_SP_SB_CM_EGRESS(4, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  169. MLXSW_SP_SB_CM_EGRESS(5, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  170. MLXSW_SP_SB_CM_EGRESS(6, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  171. MLXSW_SP_SB_CM_EGRESS(7, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
  172. MLXSW_SP_SB_CM_EGRESS(8, 0, 0),
  173. MLXSW_SP_SB_CM_EGRESS(9, 0, 0),
  174. MLXSW_SP_SB_CM_EGRESS(10, 0, 0),
  175. MLXSW_SP_SB_CM_EGRESS(11, 0, 0),
  176. MLXSW_SP_SB_CM_EGRESS(12, 0, 0),
  177. MLXSW_SP_SB_CM_EGRESS(13, 0, 0),
  178. MLXSW_SP_SB_CM_EGRESS(14, 0, 0),
  179. MLXSW_SP_SB_CM_EGRESS(15, 0, 0),
  180. MLXSW_SP_SB_CM_EGRESS(16, 1, 0xff),
  181. };
  182. #define MLXSW_SP_SB_CMS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms)
  183. static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = {
  184. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(0),
  185. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(1),
  186. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(2),
  187. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(3),
  188. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(4),
  189. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(5),
  190. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(6),
  191. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(7),
  192. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(8),
  193. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(9),
  194. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(10),
  195. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(11),
  196. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(12),
  197. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(13),
  198. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(14),
  199. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(15),
  200. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(16),
  201. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(17),
  202. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(18),
  203. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(19),
  204. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(20),
  205. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(21),
  206. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(22),
  207. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(23),
  208. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(24),
  209. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(25),
  210. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(26),
  211. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(27),
  212. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(28),
  213. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(29),
  214. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(30),
  215. MLXSW_SP_CPU_PORT_SB_CM_EGRESS(31),
  216. };
  217. #define MLXSW_SP_CPU_PORT_SB_MCS_LEN \
  218. ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms)
  219. static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
  220. const struct mlxsw_sp_sb_cm *cms,
  221. size_t cms_len)
  222. {
  223. char sbcm_pl[MLXSW_REG_SBCM_LEN];
  224. int i;
  225. int err;
  226. for (i = 0; i < cms_len; i++) {
  227. const struct mlxsw_sp_sb_cm *cm;
  228. cm = &cms[i];
  229. mlxsw_reg_sbcm_pack(sbcm_pl, local_port, cm->u.pg, cm->dir,
  230. cm->min_buff, cm->max_buff, cm->pool);
  231. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
  232. if (err)
  233. return err;
  234. }
  235. return 0;
  236. }
  237. static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port)
  238. {
  239. return mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
  240. mlxsw_sp_port->local_port, mlxsw_sp_sb_cms,
  241. MLXSW_SP_SB_CMS_LEN);
  242. }
  243. static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
  244. {
  245. return mlxsw_sp_sb_cms_init(mlxsw_sp, 0, mlxsw_sp_cpu_port_sb_cms,
  246. MLXSW_SP_CPU_PORT_SB_MCS_LEN);
  247. }
  248. struct mlxsw_sp_sb_pm {
  249. u8 pool;
  250. enum mlxsw_reg_sbpm_dir dir;
  251. u32 min_buff;
  252. u32 max_buff;
  253. };
  254. #define MLXSW_SP_SB_PM(_pool, _dir, _min_buff, _max_buff) \
  255. { \
  256. .pool = _pool, \
  257. .dir = _dir, \
  258. .min_buff = _min_buff, \
  259. .max_buff = _max_buff, \
  260. }
  261. #define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff) \
  262. MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_INGRESS, \
  263. _min_buff, _max_buff)
  264. #define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff) \
  265. MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_EGRESS, \
  266. _min_buff, _max_buff)
  267. static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
  268. MLXSW_SP_SB_PM_INGRESS(0, 0, 0xff),
  269. MLXSW_SP_SB_PM_INGRESS(1, 0, 0),
  270. MLXSW_SP_SB_PM_INGRESS(2, 0, 0),
  271. MLXSW_SP_SB_PM_INGRESS(3, 0, 0),
  272. MLXSW_SP_SB_PM_EGRESS(0, 0, 7),
  273. MLXSW_SP_SB_PM_EGRESS(1, 0, 0),
  274. MLXSW_SP_SB_PM_EGRESS(2, 0, 0),
  275. MLXSW_SP_SB_PM_EGRESS(3, 0, 0),
  276. };
  277. #define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms)
  278. static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
  279. {
  280. char sbpm_pl[MLXSW_REG_SBPM_LEN];
  281. int i;
  282. int err;
  283. for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) {
  284. const struct mlxsw_sp_sb_pm *pm;
  285. pm = &mlxsw_sp_sb_pms[i];
  286. mlxsw_reg_sbpm_pack(sbpm_pl, mlxsw_sp_port->local_port,
  287. pm->pool, pm->dir,
  288. pm->min_buff, pm->max_buff);
  289. err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core,
  290. MLXSW_REG(sbpm), sbpm_pl);
  291. if (err)
  292. return err;
  293. }
  294. return 0;
  295. }
  296. struct mlxsw_sp_sb_mm {
  297. u8 prio;
  298. u32 min_buff;
  299. u32 max_buff;
  300. u8 pool;
  301. };
  302. #define MLXSW_SP_SB_MM(_prio, _min_buff, _max_buff, _pool) \
  303. { \
  304. .prio = _prio, \
  305. .min_buff = _min_buff, \
  306. .max_buff = _max_buff, \
  307. .pool = _pool, \
  308. }
  309. static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = {
  310. MLXSW_SP_SB_MM(0, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  311. MLXSW_SP_SB_MM(1, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  312. MLXSW_SP_SB_MM(2, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  313. MLXSW_SP_SB_MM(3, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  314. MLXSW_SP_SB_MM(4, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  315. MLXSW_SP_SB_MM(5, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  316. MLXSW_SP_SB_MM(6, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  317. MLXSW_SP_SB_MM(7, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  318. MLXSW_SP_SB_MM(8, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  319. MLXSW_SP_SB_MM(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  320. MLXSW_SP_SB_MM(10, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  321. MLXSW_SP_SB_MM(11, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  322. MLXSW_SP_SB_MM(12, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  323. MLXSW_SP_SB_MM(13, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  324. MLXSW_SP_SB_MM(14, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
  325. };
  326. #define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms)
  327. static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp)
  328. {
  329. char sbmm_pl[MLXSW_REG_SBMM_LEN];
  330. int i;
  331. int err;
  332. for (i = 0; i < MLXSW_SP_SB_MMS_LEN; i++) {
  333. const struct mlxsw_sp_sb_mm *mc;
  334. mc = &mlxsw_sp_sb_mms[i];
  335. mlxsw_reg_sbmm_pack(sbmm_pl, mc->prio, mc->min_buff,
  336. mc->max_buff, mc->pool);
  337. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl);
  338. if (err)
  339. return err;
  340. }
  341. return 0;
  342. }
  343. int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
  344. {
  345. int err;
  346. err = mlxsw_sp_sb_pools_init(mlxsw_sp);
  347. if (err)
  348. return err;
  349. err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp);
  350. if (err)
  351. return err;
  352. err = mlxsw_sp_sb_mms_init(mlxsw_sp);
  353. return err;
  354. }
  355. int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port)
  356. {
  357. int err;
  358. err = mlxsw_sp_port_pb_init(mlxsw_sp_port);
  359. if (err)
  360. return err;
  361. err = mlxsw_sp_port_sb_cms_init(mlxsw_sp_port);
  362. if (err)
  363. return err;
  364. err = mlxsw_sp_port_sb_pms_init(mlxsw_sp_port);
  365. return err;
  366. }