1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
3  *
4  * This contains glue logic between the switchdev driver operations and the
5  * mscc_ocelot_switch_lib.
6  *
7  * Copyright (c) 2017, 2019 Microsemi Corporation
8  * Copyright 2020-2021 NXP Semiconductors
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 
18 static 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 
32 int 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 }
63 EXPORT_SYMBOL(ocelot_mrp_add);
64 
65 int 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 }
99 EXPORT_SYMBOL(ocelot_mrp_del);
100 
101 int 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 }
149 EXPORT_SYMBOL(ocelot_mrp_add_ring_role);
150 
151 int 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 }
175 EXPORT_SYMBOL(ocelot_mrp_del_ring_role);
176