lan966x_dcb.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include "lan966x_main.h"
  3. enum lan966x_dcb_apptrust_values {
  4. LAN966X_DCB_APPTRUST_EMPTY,
  5. LAN966X_DCB_APPTRUST_DSCP,
  6. LAN966X_DCB_APPTRUST_PCP,
  7. LAN966X_DCB_APPTRUST_DSCP_PCP,
  8. __LAN966X_DCB_APPTRUST_MAX
  9. };
  10. static const struct lan966x_dcb_apptrust {
  11. u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1];
  12. int nselectors;
  13. } *lan966x_port_apptrust[NUM_PHYS_PORTS];
  14. static const char *lan966x_dcb_apptrust_names[__LAN966X_DCB_APPTRUST_MAX] = {
  15. [LAN966X_DCB_APPTRUST_EMPTY] = "empty",
  16. [LAN966X_DCB_APPTRUST_DSCP] = "dscp",
  17. [LAN966X_DCB_APPTRUST_PCP] = "pcp",
  18. [LAN966X_DCB_APPTRUST_DSCP_PCP] = "dscp pcp"
  19. };
  20. /* Lan966x supported apptrust policies */
  21. static const struct lan966x_dcb_apptrust
  22. lan966x_dcb_apptrust_policies[__LAN966X_DCB_APPTRUST_MAX] = {
  23. /* Empty *must* be first */
  24. [LAN966X_DCB_APPTRUST_EMPTY] = { { 0 }, 0 },
  25. [LAN966X_DCB_APPTRUST_DSCP] = { { IEEE_8021QAZ_APP_SEL_DSCP }, 1 },
  26. [LAN966X_DCB_APPTRUST_PCP] = { { DCB_APP_SEL_PCP }, 1 },
  27. [LAN966X_DCB_APPTRUST_DSCP_PCP] = { { IEEE_8021QAZ_APP_SEL_DSCP,
  28. DCB_APP_SEL_PCP }, 2 },
  29. };
  30. static bool lan966x_dcb_apptrust_contains(int portno, u8 selector)
  31. {
  32. const struct lan966x_dcb_apptrust *conf = lan966x_port_apptrust[portno];
  33. for (int i = 0; i < conf->nselectors; i++)
  34. if (conf->selectors[i] == selector)
  35. return true;
  36. return false;
  37. }
  38. static void lan966x_dcb_app_update(struct net_device *dev)
  39. {
  40. struct dcb_ieee_app_prio_map dscp_rewr_map = {0};
  41. struct dcb_rewr_prio_pcp_map pcp_rewr_map = {0};
  42. struct lan966x_port *port = netdev_priv(dev);
  43. struct lan966x_port_qos qos = {0};
  44. struct dcb_app app_itr;
  45. bool dscp_rewr = false;
  46. bool pcp_rewr = false;
  47. /* Get pcp ingress mapping */
  48. for (int i = 0; i < ARRAY_SIZE(qos.pcp.map); i++) {
  49. app_itr.selector = DCB_APP_SEL_PCP;
  50. app_itr.protocol = i;
  51. qos.pcp.map[i] = dcb_getapp(dev, &app_itr);
  52. }
  53. /* Get dscp ingress mapping */
  54. for (int i = 0; i < ARRAY_SIZE(qos.dscp.map); i++) {
  55. app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP;
  56. app_itr.protocol = i;
  57. qos.dscp.map[i] = dcb_getapp(dev, &app_itr);
  58. }
  59. /* Get default prio */
  60. qos.default_prio = dcb_ieee_getapp_default_prio_mask(dev);
  61. if (qos.default_prio)
  62. qos.default_prio = fls(qos.default_prio) - 1;
  63. /* Get pcp rewrite mapping */
  64. dcb_getrewr_prio_pcp_mask_map(dev, &pcp_rewr_map);
  65. for (int i = 0; i < ARRAY_SIZE(pcp_rewr_map.map); i++) {
  66. if (!pcp_rewr_map.map[i])
  67. continue;
  68. pcp_rewr = true;
  69. qos.pcp_rewr.map[i] = fls(pcp_rewr_map.map[i]) - 1;
  70. }
  71. /* Get dscp rewrite mapping */
  72. dcb_getrewr_prio_dscp_mask_map(dev, &dscp_rewr_map);
  73. for (int i = 0; i < ARRAY_SIZE(dscp_rewr_map.map); i++) {
  74. if (!dscp_rewr_map.map[i])
  75. continue;
  76. dscp_rewr = true;
  77. qos.dscp_rewr.map[i] = fls64(dscp_rewr_map.map[i]) - 1;
  78. }
  79. /* Enable use of pcp for queue classification */
  80. if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP)) {
  81. qos.pcp.enable = true;
  82. if (pcp_rewr)
  83. qos.pcp_rewr.enable = true;
  84. }
  85. /* Enable use of dscp for queue classification */
  86. if (lan966x_dcb_apptrust_contains(port->chip_port, IEEE_8021QAZ_APP_SEL_DSCP)) {
  87. qos.dscp.enable = true;
  88. if (dscp_rewr)
  89. qos.dscp_rewr.enable = true;
  90. }
  91. lan966x_port_qos_set(port, &qos);
  92. }
  93. /* DSCP mapping is global for all ports, so set and delete app entries are
  94. * replicated for each port.
  95. */
  96. static int lan966x_dcb_ieee_dscp_setdel(struct net_device *dev,
  97. struct dcb_app *app,
  98. int (*setdel)(struct net_device *,
  99. struct dcb_app *))
  100. {
  101. struct lan966x_port *port = netdev_priv(dev);
  102. struct lan966x *lan966x = port->lan966x;
  103. int err;
  104. for (int i = 0; i < NUM_PHYS_PORTS; i++) {
  105. port = lan966x->ports[i];
  106. if (!port)
  107. continue;
  108. err = setdel(port->dev, app);
  109. if (err)
  110. return err;
  111. }
  112. return 0;
  113. }
  114. static int lan966x_dcb_app_validate(struct net_device *dev,
  115. const struct dcb_app *app)
  116. {
  117. int err = 0;
  118. switch (app->selector) {
  119. /* Default priority checks */
  120. case IEEE_8021QAZ_APP_SEL_ETHERTYPE:
  121. if (app->protocol)
  122. err = -EINVAL;
  123. else if (app->priority >= NUM_PRIO_QUEUES)
  124. err = -ERANGE;
  125. break;
  126. /* Dscp checks */
  127. case IEEE_8021QAZ_APP_SEL_DSCP:
  128. if (app->protocol >= LAN966X_PORT_QOS_DSCP_COUNT)
  129. err = -EINVAL;
  130. else if (app->priority >= NUM_PRIO_QUEUES)
  131. err = -ERANGE;
  132. break;
  133. /* Pcp checks */
  134. case DCB_APP_SEL_PCP:
  135. if (app->protocol >= LAN966X_PORT_QOS_PCP_DEI_COUNT)
  136. err = -EINVAL;
  137. else if (app->priority >= NUM_PRIO_QUEUES)
  138. err = -ERANGE;
  139. break;
  140. default:
  141. err = -EINVAL;
  142. break;
  143. }
  144. if (err)
  145. netdev_err(dev, "Invalid entry: %d:%d\n", app->protocol,
  146. app->priority);
  147. return err;
  148. }
  149. static int lan966x_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app)
  150. {
  151. int err;
  152. if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
  153. err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp);
  154. else
  155. err = dcb_ieee_delapp(dev, app);
  156. if (err)
  157. return err;
  158. lan966x_dcb_app_update(dev);
  159. return 0;
  160. }
  161. static int lan966x_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app)
  162. {
  163. struct dcb_app app_itr;
  164. int err;
  165. u8 prio;
  166. err = lan966x_dcb_app_validate(dev, app);
  167. if (err)
  168. return err;
  169. /* Delete current mapping, if it exists */
  170. prio = dcb_getapp(dev, app);
  171. if (prio) {
  172. app_itr = *app;
  173. app_itr.priority = prio;
  174. lan966x_dcb_ieee_delapp(dev, &app_itr);
  175. }
  176. if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
  177. err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_setapp);
  178. else
  179. err = dcb_ieee_setapp(dev, app);
  180. if (err)
  181. return err;
  182. lan966x_dcb_app_update(dev);
  183. return 0;
  184. }
  185. static int lan966x_dcb_apptrust_validate(struct net_device *dev,
  186. u8 *selectors,
  187. int nselectors)
  188. {
  189. for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_policies); i++) {
  190. bool match;
  191. if (lan966x_dcb_apptrust_policies[i].nselectors != nselectors)
  192. continue;
  193. match = true;
  194. for (int j = 0; j < nselectors; j++) {
  195. if (lan966x_dcb_apptrust_policies[i].selectors[j] !=
  196. *(selectors + j)) {
  197. match = false;
  198. break;
  199. }
  200. }
  201. if (match)
  202. return i;
  203. }
  204. netdev_err(dev, "Valid apptrust configurations are:\n");
  205. for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_names); i++)
  206. pr_info("order: %s\n", lan966x_dcb_apptrust_names[i]);
  207. return -EOPNOTSUPP;
  208. }
  209. static int lan966x_dcb_setapptrust(struct net_device *dev,
  210. u8 *selectors,
  211. int nselectors)
  212. {
  213. struct lan966x_port *port = netdev_priv(dev);
  214. int idx;
  215. idx = lan966x_dcb_apptrust_validate(dev, selectors, nselectors);
  216. if (idx < 0)
  217. return idx;
  218. lan966x_port_apptrust[port->chip_port] = &lan966x_dcb_apptrust_policies[idx];
  219. lan966x_dcb_app_update(dev);
  220. return 0;
  221. }
  222. static int lan966x_dcb_getapptrust(struct net_device *dev, u8 *selectors,
  223. int *nselectors)
  224. {
  225. struct lan966x_port *port = netdev_priv(dev);
  226. const struct lan966x_dcb_apptrust *trust;
  227. trust = lan966x_port_apptrust[port->chip_port];
  228. memcpy(selectors, trust->selectors, trust->nselectors);
  229. *nselectors = trust->nselectors;
  230. return 0;
  231. }
  232. static int lan966x_dcb_delrewr(struct net_device *dev, struct dcb_app *app)
  233. {
  234. int err;
  235. if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
  236. err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_delrewr);
  237. else
  238. err = dcb_delrewr(dev, app);
  239. if (err < 0)
  240. return err;
  241. lan966x_dcb_app_update(dev);
  242. return 0;
  243. }
  244. static int lan966x_dcb_setrewr(struct net_device *dev, struct dcb_app *app)
  245. {
  246. struct dcb_app app_itr;
  247. u16 proto;
  248. int err;
  249. err = lan966x_dcb_app_validate(dev, app);
  250. if (err)
  251. goto out;
  252. /* Delete current mapping, if it exists. */
  253. proto = dcb_getrewr(dev, app);
  254. if (proto) {
  255. app_itr = *app;
  256. app_itr.protocol = proto;
  257. lan966x_dcb_delrewr(dev, &app_itr);
  258. }
  259. if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
  260. err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_setrewr);
  261. else
  262. err = dcb_setrewr(dev, app);
  263. if (err)
  264. goto out;
  265. lan966x_dcb_app_update(dev);
  266. out:
  267. return err;
  268. }
  269. static const struct dcbnl_rtnl_ops lan966x_dcbnl_ops = {
  270. .ieee_setapp = lan966x_dcb_ieee_setapp,
  271. .ieee_delapp = lan966x_dcb_ieee_delapp,
  272. .dcbnl_setapptrust = lan966x_dcb_setapptrust,
  273. .dcbnl_getapptrust = lan966x_dcb_getapptrust,
  274. .dcbnl_setrewr = lan966x_dcb_setrewr,
  275. .dcbnl_delrewr = lan966x_dcb_delrewr,
  276. };
  277. void lan966x_dcb_init(struct lan966x *lan966x)
  278. {
  279. for (int p = 0; p < lan966x->num_phys_ports; ++p) {
  280. struct lan966x_port *port;
  281. port = lan966x->ports[p];
  282. if (!port)
  283. continue;
  284. port->dev->dcbnl_ops = &lan966x_dcbnl_ops;
  285. lan966x_port_apptrust[port->chip_port] =
  286. &lan966x_dcb_apptrust_policies[LAN966X_DCB_APPTRUST_DSCP_PCP];
  287. /* Enable DSCP classification based on classified QoS class and
  288. * DP, for all DSCP values, for all ports.
  289. */
  290. lan966x_port_qos_dscp_rewr_mode_set(port,
  291. LAN966X_PORT_QOS_REWR_DSCP_ALL);
  292. }
  293. }