br_mrp_switchdev.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <net/switchdev.h>
  3. #include "br_private_mrp.h"
  4. static enum br_mrp_hw_support
  5. br_mrp_switchdev_port_obj(struct net_bridge *br,
  6. const struct switchdev_obj *obj, bool add)
  7. {
  8. int err;
  9. if (add)
  10. err = switchdev_port_obj_add(br->dev, obj, NULL);
  11. else
  12. err = switchdev_port_obj_del(br->dev, obj);
  13. /* In case of success just return and notify the SW that doesn't need
  14. * to do anything
  15. */
  16. if (!err)
  17. return BR_MRP_HW;
  18. if (err != -EOPNOTSUPP)
  19. return BR_MRP_NONE;
  20. /* Continue with SW backup */
  21. return BR_MRP_SW;
  22. }
  23. int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
  24. {
  25. struct switchdev_obj_mrp mrp_obj = {
  26. .obj.orig_dev = br->dev,
  27. .obj.id = SWITCHDEV_OBJ_ID_MRP,
  28. .p_port = rtnl_dereference(mrp->p_port)->dev,
  29. .s_port = rtnl_dereference(mrp->s_port)->dev,
  30. .ring_id = mrp->ring_id,
  31. .prio = mrp->prio,
  32. };
  33. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  34. return 0;
  35. return switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
  36. }
  37. int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
  38. {
  39. struct switchdev_obj_mrp mrp_obj = {
  40. .obj.orig_dev = br->dev,
  41. .obj.id = SWITCHDEV_OBJ_ID_MRP,
  42. .p_port = NULL,
  43. .s_port = NULL,
  44. .ring_id = mrp->ring_id,
  45. };
  46. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  47. return 0;
  48. return switchdev_port_obj_del(br->dev, &mrp_obj.obj);
  49. }
  50. enum br_mrp_hw_support
  51. br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
  52. enum br_mrp_ring_role_type role)
  53. {
  54. struct switchdev_obj_ring_role_mrp mrp_role = {
  55. .obj.orig_dev = br->dev,
  56. .obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
  57. .ring_role = role,
  58. .ring_id = mrp->ring_id,
  59. .sw_backup = false,
  60. };
  61. enum br_mrp_hw_support support;
  62. int err;
  63. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  64. return BR_MRP_SW;
  65. support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
  66. role != BR_MRP_RING_ROLE_DISABLED);
  67. if (support != BR_MRP_SW)
  68. return support;
  69. /* If the driver can't configure to run completely the protocol in HW,
  70. * then try again to configure the HW so the SW can run the protocol.
  71. */
  72. mrp_role.sw_backup = true;
  73. if (role != BR_MRP_RING_ROLE_DISABLED)
  74. err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
  75. else
  76. err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
  77. if (!err)
  78. return BR_MRP_SW;
  79. return BR_MRP_NONE;
  80. }
  81. enum br_mrp_hw_support
  82. br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
  83. u32 interval, u8 max_miss, u32 period,
  84. bool monitor)
  85. {
  86. struct switchdev_obj_ring_test_mrp test = {
  87. .obj.orig_dev = br->dev,
  88. .obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
  89. .interval = interval,
  90. .max_miss = max_miss,
  91. .ring_id = mrp->ring_id,
  92. .period = period,
  93. .monitor = monitor,
  94. };
  95. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  96. return BR_MRP_SW;
  97. return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
  98. }
  99. int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
  100. struct br_mrp *mrp,
  101. enum br_mrp_ring_state_type state)
  102. {
  103. struct switchdev_obj_ring_state_mrp mrp_state = {
  104. .obj.orig_dev = br->dev,
  105. .obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
  106. .ring_state = state,
  107. .ring_id = mrp->ring_id,
  108. };
  109. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  110. return 0;
  111. return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
  112. }
  113. enum br_mrp_hw_support
  114. br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
  115. u16 in_id, u32 ring_id,
  116. enum br_mrp_in_role_type role)
  117. {
  118. struct switchdev_obj_in_role_mrp mrp_role = {
  119. .obj.orig_dev = br->dev,
  120. .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP,
  121. .in_role = role,
  122. .in_id = mrp->in_id,
  123. .ring_id = mrp->ring_id,
  124. .i_port = rtnl_dereference(mrp->i_port)->dev,
  125. .sw_backup = false,
  126. };
  127. enum br_mrp_hw_support support;
  128. int err;
  129. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  130. return BR_MRP_SW;
  131. support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
  132. role != BR_MRP_IN_ROLE_DISABLED);
  133. if (support != BR_MRP_NONE)
  134. return support;
  135. /* If the driver can't configure to run completely the protocol in HW,
  136. * then try again to configure the HW so the SW can run the protocol.
  137. */
  138. mrp_role.sw_backup = true;
  139. if (role != BR_MRP_IN_ROLE_DISABLED)
  140. err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
  141. else
  142. err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
  143. if (!err)
  144. return BR_MRP_SW;
  145. return BR_MRP_NONE;
  146. }
  147. int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
  148. enum br_mrp_in_state_type state)
  149. {
  150. struct switchdev_obj_in_state_mrp mrp_state = {
  151. .obj.orig_dev = br->dev,
  152. .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP,
  153. .in_state = state,
  154. .in_id = mrp->in_id,
  155. };
  156. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  157. return 0;
  158. return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
  159. }
  160. enum br_mrp_hw_support
  161. br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
  162. u32 interval, u8 max_miss, u32 period)
  163. {
  164. struct switchdev_obj_in_test_mrp test = {
  165. .obj.orig_dev = br->dev,
  166. .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP,
  167. .interval = interval,
  168. .max_miss = max_miss,
  169. .in_id = mrp->in_id,
  170. .period = period,
  171. };
  172. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  173. return BR_MRP_SW;
  174. return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
  175. }
  176. int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
  177. {
  178. struct switchdev_attr attr = {
  179. .orig_dev = p->dev,
  180. .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE,
  181. .u.stp_state = state,
  182. };
  183. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  184. return 0;
  185. return switchdev_port_attr_set(p->dev, &attr, NULL);
  186. }
  187. int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
  188. enum br_mrp_port_role_type role)
  189. {
  190. struct switchdev_attr attr = {
  191. .orig_dev = p->dev,
  192. .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
  193. .u.mrp_port_role = role,
  194. };
  195. if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  196. return 0;
  197. return switchdev_port_attr_set(p->dev, &attr, NULL);
  198. }