1
2
3
4
5
6
7
8
9
10
11#include <linux/if_bridge.h>
12#include <linux/mrp_bridge.h>
13#include <soc/mscc/ocelot_vcap.h>
14#include <uapi/linux/mrp_bridge.h>
15#include "ocelot.h"
16#include "ocelot_vcap.h"
17
18static int ocelot_mrp_del_vcap(struct ocelot *ocelot, int port)
19{
20 struct ocelot_vcap_block *block_vcap_is2;
21 struct ocelot_vcap_filter *filter;
22
23 block_vcap_is2 = &ocelot->block[VCAP_IS2];
24 filter = ocelot_vcap_block_find_filter_by_id(block_vcap_is2, port,
25 false);
26 if (!filter)
27 return 0;
28
29 return ocelot_vcap_filter_del(ocelot, filter);
30}
31
32int ocelot_mrp_add(struct ocelot *ocelot, int port,
33 const struct switchdev_obj_mrp *mrp)
34{
35 struct ocelot_port *ocelot_port = ocelot->ports[port];
36 struct ocelot_port_private *priv;
37 struct net_device *dev;
38
39 if (!ocelot_port)
40 return -EOPNOTSUPP;
41
42 priv = container_of(ocelot_port, struct ocelot_port_private, port);
43 dev = priv->dev;
44
45 if (mrp->p_port != dev && mrp->s_port != dev)
46 return 0;
47
48 if (ocelot->mrp_ring_id != 0 &&
49 ocelot->mrp_s_port &&
50 ocelot->mrp_p_port)
51 return -EINVAL;
52
53 if (mrp->p_port == dev)
54 ocelot->mrp_p_port = dev;
55
56 if (mrp->s_port == dev)
57 ocelot->mrp_s_port = dev;
58
59 ocelot->mrp_ring_id = mrp->ring_id;
60
61 return 0;
62}
63EXPORT_SYMBOL(ocelot_mrp_add);
64
65int ocelot_mrp_del(struct ocelot *ocelot, int port,
66 const struct switchdev_obj_mrp *mrp)
67{
68 struct ocelot_port *ocelot_port = ocelot->ports[port];
69 struct ocelot_port_private *priv;
70 struct net_device *dev;
71
72 if (!ocelot_port)
73 return -EOPNOTSUPP;
74
75 priv = container_of(ocelot_port, struct ocelot_port_private, port);
76 dev = priv->dev;
77
78 if (ocelot->mrp_p_port != dev && ocelot->mrp_s_port != dev)
79 return 0;
80
81 if (ocelot->mrp_ring_id == 0 &&
82 !ocelot->mrp_s_port &&
83 !ocelot->mrp_p_port)
84 return -EINVAL;
85
86 if (ocelot_mrp_del_vcap(ocelot, priv->chip_port))
87 return -EINVAL;
88
89 if (ocelot->mrp_p_port == dev)
90 ocelot->mrp_p_port = NULL;
91
92 if (ocelot->mrp_s_port == dev)
93 ocelot->mrp_s_port = NULL;
94
95 ocelot->mrp_ring_id = 0;
96
97 return 0;
98}
99EXPORT_SYMBOL(ocelot_mrp_del);
100
101int ocelot_mrp_add_ring_role(struct ocelot *ocelot, int port,
102 const struct switchdev_obj_ring_role_mrp *mrp)
103{
104 struct ocelot_port *ocelot_port = ocelot->ports[port];
105 struct ocelot_vcap_filter *filter;
106 struct ocelot_port_private *priv;
107 struct net_device *dev;
108 int err;
109
110 if (!ocelot_port)
111 return -EOPNOTSUPP;
112
113 priv = container_of(ocelot_port, struct ocelot_port_private, port);
114 dev = priv->dev;
115
116 if (ocelot->mrp_ring_id != mrp->ring_id)
117 return -EINVAL;
118
119 if (!mrp->sw_backup)
120 return -EOPNOTSUPP;
121
122 if (ocelot->mrp_p_port != dev && ocelot->mrp_s_port != dev)
123 return 0;
124
125 filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
126 if (!filter)
127 return -ENOMEM;
128
129 filter->key_type = OCELOT_VCAP_KEY_ETYPE;
130 filter->prio = 1;
131 filter->id.cookie = priv->chip_port;
132 filter->id.tc_offload = false;
133 filter->block_id = VCAP_IS2;
134 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
135 filter->ingress_port_mask = BIT(priv->chip_port);
136 *(__be16 *)filter->key.etype.etype.value = htons(ETH_P_MRP);
137 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
138 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
139 filter->action.port_mask = 0x0;
140 filter->action.cpu_copy_ena = true;
141 filter->action.cpu_qu_num = OCELOT_MRP_CPUQ;
142
143 err = ocelot_vcap_filter_add(ocelot, filter, NULL);
144 if (err)
145 kfree(filter);
146
147 return err;
148}
149EXPORT_SYMBOL(ocelot_mrp_add_ring_role);
150
151int ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port,
152 const struct switchdev_obj_ring_role_mrp *mrp)
153{
154 struct ocelot_port *ocelot_port = ocelot->ports[port];
155 struct ocelot_port_private *priv;
156 struct net_device *dev;
157
158 if (!ocelot_port)
159 return -EOPNOTSUPP;
160
161 priv = container_of(ocelot_port, struct ocelot_port_private, port);
162 dev = priv->dev;
163
164 if (ocelot->mrp_ring_id != mrp->ring_id)
165 return -EINVAL;
166
167 if (!mrp->sw_backup)
168 return -EOPNOTSUPP;
169
170 if (ocelot->mrp_p_port != dev && ocelot->mrp_s_port != dev)
171 return 0;
172
173 return ocelot_mrp_del_vcap(ocelot, priv->chip_port);
174}
175EXPORT_SYMBOL(ocelot_mrp_del_ring_role);
176