blob: 7da2dd1632b1d764b41d3234ca3033f2784d4010 [file] [log] [blame]
Alexandre Bellonia556c762018-05-14 22:04:57 +02001// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
Vladimir Oltean40d3f292021-02-14 00:37:56 +02007#include <linux/dsa/ocelot.h>
Alexandre Bellonia556c762018-05-14 22:04:57 +02008#include <linux/if_bridge.h>
Vladimir Oltean20968052020-09-30 01:27:26 +03009#include <soc/mscc/ocelot_vcap.h>
Alexandre Bellonia556c762018-05-14 22:04:57 +020010#include "ocelot.h"
Vladimir Oltean3c836542020-06-20 18:43:45 +030011#include "ocelot_vcap.h"
Alexandre Bellonia556c762018-05-14 22:04:57 +020012
Steen Hegelund639c1b22018-12-20 14:16:31 +010013#define TABLE_UPDATE_SLEEP_US 10
14#define TABLE_UPDATE_TIMEOUT_US 100000
15
Alexandre Bellonia556c762018-05-14 22:04:57 +020016struct ocelot_mact_entry {
17 u8 mac[ETH_ALEN];
18 u16 vid;
19 enum macaccess_entry_type type;
20};
21
Steen Hegelund639c1b22018-12-20 14:16:31 +010022static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot)
23{
24 return ocelot_read(ocelot, ANA_TABLES_MACACCESS);
25}
26
Alexandre Bellonia556c762018-05-14 22:04:57 +020027static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot)
28{
Steen Hegelund639c1b22018-12-20 14:16:31 +010029 u32 val;
Alexandre Bellonia556c762018-05-14 22:04:57 +020030
Steen Hegelund639c1b22018-12-20 14:16:31 +010031 return readx_poll_timeout(ocelot_mact_read_macaccess,
32 ocelot, val,
33 (val & ANA_TABLES_MACACCESS_MAC_TABLE_CMD_M) ==
34 MACACCESS_CMD_IDLE,
35 TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
Alexandre Bellonia556c762018-05-14 22:04:57 +020036}
37
38static void ocelot_mact_select(struct ocelot *ocelot,
39 const unsigned char mac[ETH_ALEN],
40 unsigned int vid)
41{
42 u32 macl = 0, mach = 0;
43
44 /* Set the MAC address to handle and the vlan associated in a format
45 * understood by the hardware.
46 */
47 mach |= vid << 16;
48 mach |= mac[0] << 8;
49 mach |= mac[1] << 0;
50 macl |= mac[2] << 24;
51 macl |= mac[3] << 16;
52 macl |= mac[4] << 8;
53 macl |= mac[5] << 0;
54
55 ocelot_write(ocelot, macl, ANA_TABLES_MACLDATA);
56 ocelot_write(ocelot, mach, ANA_TABLES_MACHDATA);
57
58}
59
Vladimir Oltean9c90eea2020-06-20 18:43:44 +030060int ocelot_mact_learn(struct ocelot *ocelot, int port,
61 const unsigned char mac[ETH_ALEN],
62 unsigned int vid, enum macaccess_entry_type type)
Alexandre Bellonia556c762018-05-14 22:04:57 +020063{
Alban Bedel584b7cf2021-01-19 15:06:38 +010064 u32 cmd = ANA_TABLES_MACACCESS_VALID |
65 ANA_TABLES_MACACCESS_DEST_IDX(port) |
66 ANA_TABLES_MACACCESS_ENTRYTYPE(type) |
67 ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN);
68 unsigned int mc_ports;
69
70 /* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */
71 if (type == ENTRYTYPE_MACv4)
72 mc_ports = (mac[1] << 8) | mac[2];
73 else if (type == ENTRYTYPE_MACv6)
74 mc_ports = (mac[0] << 8) | mac[1];
75 else
76 mc_ports = 0;
77
78 if (mc_ports & BIT(ocelot->num_phys_ports))
79 cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY;
80
Alexandre Bellonia556c762018-05-14 22:04:57 +020081 ocelot_mact_select(ocelot, mac, vid);
82
83 /* Issue a write command */
Alban Bedel584b7cf2021-01-19 15:06:38 +010084 ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS);
Alexandre Bellonia556c762018-05-14 22:04:57 +020085
86 return ocelot_mact_wait_for_completion(ocelot);
87}
Vladimir Oltean9c90eea2020-06-20 18:43:44 +030088EXPORT_SYMBOL(ocelot_mact_learn);
Alexandre Bellonia556c762018-05-14 22:04:57 +020089
Vladimir Oltean9c90eea2020-06-20 18:43:44 +030090int ocelot_mact_forget(struct ocelot *ocelot,
91 const unsigned char mac[ETH_ALEN], unsigned int vid)
Alexandre Bellonia556c762018-05-14 22:04:57 +020092{
93 ocelot_mact_select(ocelot, mac, vid);
94
95 /* Issue a forget command */
96 ocelot_write(ocelot,
97 ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET),
98 ANA_TABLES_MACACCESS);
99
100 return ocelot_mact_wait_for_completion(ocelot);
101}
Vladimir Oltean9c90eea2020-06-20 18:43:44 +0300102EXPORT_SYMBOL(ocelot_mact_forget);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200103
104static void ocelot_mact_init(struct ocelot *ocelot)
105{
106 /* Configure the learning mode entries attributes:
107 * - Do not copy the frame to the CPU extraction queues.
108 * - Use the vlan and mac_cpoy for dmac lookup.
109 */
110 ocelot_rmw(ocelot, 0,
111 ANA_AGENCTRL_LEARN_CPU_COPY | ANA_AGENCTRL_IGNORE_DMAC_FLAGS
112 | ANA_AGENCTRL_LEARN_FWD_KILL
113 | ANA_AGENCTRL_LEARN_IGNORE_VLAN,
114 ANA_AGENCTRL);
115
116 /* Clear the MAC table */
117 ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS);
118}
119
Vladimir Olteanf270dbf2019-11-09 15:02:52 +0200120static void ocelot_vcap_enable(struct ocelot *ocelot, int port)
Horatiu Vulturb5962292019-05-31 09:16:56 +0200121{
122 ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA |
123 ANA_PORT_VCAP_S2_CFG_S2_IP6_CFG(0xa),
Vladimir Olteanf270dbf2019-11-09 15:02:52 +0200124 ANA_PORT_VCAP_S2_CFG, port);
Xiaoliang Yang75944fd2020-10-02 15:02:23 +0300125
126 ocelot_write_gix(ocelot, ANA_PORT_VCAP_CFG_S1_ENA,
127 ANA_PORT_VCAP_CFG, port);
Xiaoliang Yang2f17c052020-10-02 15:02:24 +0300128
129 ocelot_rmw_gix(ocelot, REW_PORT_CFG_ES0_EN,
130 REW_PORT_CFG_ES0_EN,
131 REW_PORT_CFG, port);
Horatiu Vulturb5962292019-05-31 09:16:56 +0200132}
133
Steen Hegelund639c1b22018-12-20 14:16:31 +0100134static inline u32 ocelot_vlant_read_vlanaccess(struct ocelot *ocelot)
135{
136 return ocelot_read(ocelot, ANA_TABLES_VLANACCESS);
137}
138
Alexandre Bellonia556c762018-05-14 22:04:57 +0200139static inline int ocelot_vlant_wait_for_completion(struct ocelot *ocelot)
140{
Steen Hegelund639c1b22018-12-20 14:16:31 +0100141 u32 val;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200142
Steen Hegelund639c1b22018-12-20 14:16:31 +0100143 return readx_poll_timeout(ocelot_vlant_read_vlanaccess,
144 ocelot,
145 val,
146 (val & ANA_TABLES_VLANACCESS_VLAN_TBL_CMD_M) ==
147 ANA_TABLES_VLANACCESS_CMD_IDLE,
148 TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200149}
150
Antoine Tenart71425292018-06-26 14:28:49 +0200151static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask)
152{
153 /* Select the VID to configure */
154 ocelot_write(ocelot, ANA_TABLES_VLANTIDX_V_INDEX(vid),
155 ANA_TABLES_VLANTIDX);
156 /* Set the vlan port members mask and issue a write command */
157 ocelot_write(ocelot, ANA_TABLES_VLANACCESS_VLAN_PORT_MASK(mask) |
158 ANA_TABLES_VLANACCESS_CMD_WRITE,
159 ANA_TABLES_VLANACCESS);
160
161 return ocelot_vlant_wait_for_completion(ocelot);
162}
163
Vladimir Oltean2f0402f2020-10-31 12:29:15 +0200164static void ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
165 struct ocelot_vlan native_vlan)
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200166{
167 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300168 u32 val = 0;
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200169
Vladimir Olteane2b2e832020-10-31 12:29:13 +0200170 ocelot_port->native_vlan = native_vlan;
171
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200172 ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(native_vlan.vid),
Antoine Tenart71425292018-06-26 14:28:49 +0200173 REW_PORT_VLAN_CFG_PORT_VID_M,
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200174 REW_PORT_VLAN_CFG, port);
175
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300176 if (ocelot_port->vlan_aware) {
Vladimir Olteane2b2e832020-10-31 12:29:13 +0200177 if (native_vlan.valid)
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300178 /* Tag all frames except when VID == DEFAULT_VLAN */
179 val = REW_TAG_CFG_TAG_CFG(1);
180 else
181 /* Tag all frames */
182 val = REW_TAG_CFG_TAG_CFG(3);
183 } else {
184 /* Port tagging disabled. */
185 val = REW_TAG_CFG_TAG_CFG(0);
186 }
187 ocelot_rmw_gix(ocelot, val,
188 REW_TAG_CFG_TAG_CFG_M,
189 REW_TAG_CFG, port);
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200190}
191
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200192/* Default vlan to clasify for untagged frames (may be zero) */
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200193static void ocelot_port_set_pvid(struct ocelot *ocelot, int port,
194 struct ocelot_vlan pvid_vlan)
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200195{
196 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Olteanbe0576f2020-10-31 12:29:14 +0200197 u32 val = 0;
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200198
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200199 ocelot_port->pvid_vlan = pvid_vlan;
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200200
201 if (!ocelot_port->vlan_aware)
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200202 pvid_vlan.vid = 0;
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200203
204 ocelot_rmw_gix(ocelot,
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200205 ANA_PORT_VLAN_CFG_VLAN_VID(pvid_vlan.vid),
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200206 ANA_PORT_VLAN_CFG_VLAN_VID_M,
207 ANA_PORT_VLAN_CFG, port);
Vladimir Olteanbe0576f2020-10-31 12:29:14 +0200208
209 /* If there's no pvid, we should drop not only untagged traffic (which
210 * happens automatically), but also 802.1p traffic which gets
211 * classified to VLAN 0, but that is always in our RX filter, so it
212 * would get accepted were it not for this setting.
213 */
214 if (!pvid_vlan.valid && ocelot_port->vlan_aware)
215 val = ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
216 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
217
218 ocelot_rmw_gix(ocelot, val,
219 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
220 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
221 ANA_PORT_DROP_CFG, port);
Vladimir Oltean75e5a552020-10-31 12:29:10 +0200222}
223
Vladimir Oltean2e554a72020-10-03 01:06:46 +0300224int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200225 bool vlan_aware)
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300226{
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200227 struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1];
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300228 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200229 struct ocelot_vcap_filter *filter;
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300230 u32 val;
231
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200232 list_for_each_entry(filter, &block->rules, list) {
233 if (filter->ingress_port_mask & BIT(port) &&
234 filter->action.vid_replace_ena) {
235 dev_err(ocelot->dev,
236 "Cannot change VLAN state with vlan modify rules active\n");
237 return -EBUSY;
Vladimir Oltean70edfae2020-10-08 14:56:58 +0300238 }
Vladimir Oltean70edfae2020-10-08 14:56:58 +0300239 }
Vladimir Oltean2e554a72020-10-03 01:06:46 +0300240
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300241 ocelot_port->vlan_aware = vlan_aware;
242
243 if (vlan_aware)
244 val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
245 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
246 else
247 val = 0;
248 ocelot_rmw_gix(ocelot, val,
249 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
250 ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
251 ANA_PORT_VLAN_CFG, port);
252
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200253 ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan);
254 ocelot_port_set_native_vlan(ocelot, port, ocelot_port->native_vlan);
Vladimir Oltean2e554a72020-10-03 01:06:46 +0300255
256 return 0;
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300257}
258EXPORT_SYMBOL(ocelot_port_vlan_filtering);
259
Vladimir Oltean2f0402f2020-10-31 12:29:15 +0200260int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid,
261 bool untagged)
262{
263 struct ocelot_port *ocelot_port = ocelot->ports[port];
264
265 /* Deny changing the native VLAN, but always permit deleting it */
266 if (untagged && ocelot_port->native_vlan.vid != vid &&
267 ocelot_port->native_vlan.valid) {
268 dev_err(ocelot->dev,
269 "Port already has a native VLAN: %d\n",
270 ocelot_port->native_vlan.vid);
271 return -EBUSY;
272 }
273
274 return 0;
275}
276EXPORT_SYMBOL(ocelot_vlan_prepare);
277
Vladimir Oltean5e256362019-11-14 17:03:27 +0200278int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
279 bool untagged)
Antoine Tenart71425292018-06-26 14:28:49 +0200280{
Antoine Tenart71425292018-06-26 14:28:49 +0200281 int ret;
282
Antoine Tenart71425292018-06-26 14:28:49 +0200283 /* Make the port a member of the VLAN */
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200284 ocelot->vlan_mask[vid] |= BIT(port);
Antoine Tenart71425292018-06-26 14:28:49 +0200285 ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
286 if (ret)
287 return ret;
288
289 /* Default ingress vlan classification */
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200290 if (pvid) {
291 struct ocelot_vlan pvid_vlan;
292
293 pvid_vlan.vid = vid;
Vladimir Olteane2b2e832020-10-31 12:29:13 +0200294 pvid_vlan.valid = true;
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200295 ocelot_port_set_pvid(ocelot, port, pvid_vlan);
296 }
Antoine Tenart71425292018-06-26 14:28:49 +0200297
298 /* Untagged egress vlan clasification */
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200299 if (untagged) {
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200300 struct ocelot_vlan native_vlan;
301
302 native_vlan.vid = vid;
Vladimir Olteane2b2e832020-10-31 12:29:13 +0200303 native_vlan.valid = true;
Vladimir Oltean2f0402f2020-10-31 12:29:15 +0200304 ocelot_port_set_native_vlan(ocelot, port, native_vlan);
Vladimir Olteanb9cd75e2019-10-26 21:04:27 +0300305 }
Antoine Tenart71425292018-06-26 14:28:49 +0200306
Antoine Tenart71425292018-06-26 14:28:49 +0200307 return 0;
308}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200309EXPORT_SYMBOL(ocelot_vlan_add);
Antoine Tenart71425292018-06-26 14:28:49 +0200310
Vladimir Oltean5e256362019-11-14 17:03:27 +0200311int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
Vladimir Oltean98559342019-11-09 15:02:48 +0200312{
313 struct ocelot_port *ocelot_port = ocelot->ports[port];
314 int ret;
Antoine Tenart71425292018-06-26 14:28:49 +0200315
316 /* Stop the port from being a member of the vlan */
Vladimir Oltean97bb69e2019-11-09 15:02:47 +0200317 ocelot->vlan_mask[vid] &= ~BIT(port);
Antoine Tenart71425292018-06-26 14:28:49 +0200318 ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
319 if (ret)
320 return ret;
321
Vladimir Olteanbe0576f2020-10-31 12:29:14 +0200322 /* Ingress */
323 if (ocelot_port->pvid_vlan.vid == vid) {
324 struct ocelot_vlan pvid_vlan = {0};
325
326 ocelot_port_set_pvid(ocelot, port, pvid_vlan);
327 }
328
Antoine Tenart71425292018-06-26 14:28:49 +0200329 /* Egress */
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200330 if (ocelot_port->native_vlan.vid == vid) {
Vladimir Olteane2b2e832020-10-31 12:29:13 +0200331 struct ocelot_vlan native_vlan = {0};
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200332
Vladimir Olteanc3e58a752020-10-31 12:29:12 +0200333 ocelot_port_set_native_vlan(ocelot, port, native_vlan);
334 }
Antoine Tenart71425292018-06-26 14:28:49 +0200335
336 return 0;
337}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200338EXPORT_SYMBOL(ocelot_vlan_del);
Antoine Tenart71425292018-06-26 14:28:49 +0200339
Alexandre Bellonia556c762018-05-14 22:04:57 +0200340static void ocelot_vlan_init(struct ocelot *ocelot)
341{
Antoine Tenart71425292018-06-26 14:28:49 +0200342 u16 port, vid;
343
Alexandre Bellonia556c762018-05-14 22:04:57 +0200344 /* Clear VLAN table, by default all ports are members of all VLANs */
345 ocelot_write(ocelot, ANA_TABLES_VLANACCESS_CMD_INIT,
346 ANA_TABLES_VLANACCESS);
347 ocelot_vlant_wait_for_completion(ocelot);
Antoine Tenart71425292018-06-26 14:28:49 +0200348
349 /* Configure the port VLAN memberships */
350 for (vid = 1; vid < VLAN_N_VID; vid++) {
351 ocelot->vlan_mask[vid] = 0;
352 ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
353 }
354
355 /* Because VLAN filtering is enabled, we need VID 0 to get untagged
356 * traffic. It is added automatically if 8021q module is loaded, but
357 * we can't rely on it since module may be not loaded.
358 */
359 ocelot->vlan_mask[0] = GENMASK(ocelot->num_phys_ports - 1, 0);
360 ocelot_vlant_set_mask(ocelot, 0, ocelot->vlan_mask[0]);
361
Antoine Tenart71425292018-06-26 14:28:49 +0200362 /* Set vlan ingress filter mask to all ports but the CPU port by
363 * default.
364 */
Vladimir Oltean714d0ff2019-11-09 15:02:55 +0200365 ocelot_write(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
366 ANA_VLANMASK);
Antoine Tenart71425292018-06-26 14:28:49 +0200367
368 for (port = 0; port < ocelot->num_phys_ports; port++) {
369 ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);
370 ocelot_write_gix(ocelot, 0, REW_TAG_CFG, port);
371 }
Alexandre Bellonia556c762018-05-14 22:04:57 +0200372}
373
Vladimir Olteaneb4733d2021-02-08 19:36:27 +0200374static u32 ocelot_read_eq_avail(struct ocelot *ocelot, int port)
375{
376 return ocelot_read_rix(ocelot, QSYS_SW_STATUS, port);
377}
378
379int ocelot_port_flush(struct ocelot *ocelot, int port)
380{
381 int err, val;
382
383 /* Disable dequeuing from the egress queues */
384 ocelot_rmw_rix(ocelot, QSYS_PORT_MODE_DEQUEUE_DIS,
385 QSYS_PORT_MODE_DEQUEUE_DIS,
386 QSYS_PORT_MODE, port);
387
388 /* Disable flow control */
389 ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0);
390
391 /* Disable priority flow control */
392 ocelot_fields_write(ocelot, port,
393 QSYS_SWITCH_PORT_MODE_TX_PFC_ENA, 0);
394
395 /* Wait at least the time it takes to receive a frame of maximum length
396 * at the port.
397 * Worst-case delays for 10 kilobyte jumbo frames are:
398 * 8 ms on a 10M port
399 * 800 μs on a 100M port
400 * 80 μs on a 1G port
401 * 32 μs on a 2.5G port
402 */
403 usleep_range(8000, 10000);
404
405 /* Disable half duplex backpressure. */
406 ocelot_rmw_rix(ocelot, 0, SYS_FRONT_PORT_MODE_HDX_MODE,
407 SYS_FRONT_PORT_MODE, port);
408
409 /* Flush the queues associated with the port. */
410 ocelot_rmw_gix(ocelot, REW_PORT_CFG_FLUSH_ENA, REW_PORT_CFG_FLUSH_ENA,
411 REW_PORT_CFG, port);
412
413 /* Enable dequeuing from the egress queues. */
414 ocelot_rmw_rix(ocelot, 0, QSYS_PORT_MODE_DEQUEUE_DIS, QSYS_PORT_MODE,
415 port);
416
417 /* Wait until flushing is complete. */
418 err = read_poll_timeout(ocelot_read_eq_avail, val, !val,
419 100, 2000000, false, ocelot, port);
420
421 /* Clear flushing again. */
422 ocelot_rmw_gix(ocelot, 0, REW_PORT_CFG_FLUSH_ENA, REW_PORT_CFG, port);
423
424 return err;
425}
426EXPORT_SYMBOL(ocelot_port_flush);
427
Vladimir Oltean5e256362019-11-14 17:03:27 +0200428void ocelot_adjust_link(struct ocelot *ocelot, int port,
429 struct phy_device *phydev)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200430{
Vladimir Oltean26f4dba2019-11-09 15:02:59 +0200431 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Oltean5bc9d2e2019-11-14 17:03:22 +0200432 int speed, mode = 0;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200433
Vladimir Oltean26f4dba2019-11-09 15:02:59 +0200434 switch (phydev->speed) {
Alexandre Bellonia556c762018-05-14 22:04:57 +0200435 case SPEED_10:
436 speed = OCELOT_SPEED_10;
437 break;
438 case SPEED_100:
439 speed = OCELOT_SPEED_100;
440 break;
441 case SPEED_1000:
442 speed = OCELOT_SPEED_1000;
443 mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
444 break;
445 case SPEED_2500:
446 speed = OCELOT_SPEED_2500;
447 mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
448 break;
449 default:
Vladimir Oltean26f4dba2019-11-09 15:02:59 +0200450 dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
451 port, phydev->speed);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200452 return;
453 }
454
Vladimir Oltean26f4dba2019-11-09 15:02:59 +0200455 phy_print_status(phydev);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200456
Vladimir Oltean26f4dba2019-11-09 15:02:59 +0200457 if (!phydev->link)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200458 return;
459
460 /* Only full duplex supported for now */
Vladimir Oltean004d44f2019-11-09 15:02:53 +0200461 ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
Alexandre Bellonia556c762018-05-14 22:04:57 +0200462 mode, DEV_MAC_MODE_CFG);
463
Vladimir Oltean1ba8f652020-02-29 16:31:11 +0200464 /* Disable HDX fast control */
465 ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
466 DEV_PORT_MISC);
467
468 /* SGMII only for now */
469 ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
470 PCS1G_MODE_CFG);
471 ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
472
473 /* Enable PCS */
474 ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
475
476 /* No aneg on SGMII */
477 ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
478
479 /* No loopback */
480 ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200481
Alexandre Bellonia556c762018-05-14 22:04:57 +0200482 /* Enable MAC module */
Vladimir Oltean004d44f2019-11-09 15:02:53 +0200483 ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
Alexandre Bellonia556c762018-05-14 22:04:57 +0200484 DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
485
486 /* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of
Yixing Liu1f78ff42021-03-31 16:18:32 +0800487 * reset
488 */
Vladimir Oltean004d44f2019-11-09 15:02:53 +0200489 ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed),
Alexandre Bellonia556c762018-05-14 22:04:57 +0200490 DEV_CLOCK_CFG);
491
Alexandre Bellonia556c762018-05-14 22:04:57 +0200492 /* No PFC */
493 ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed),
Vladimir Oltean004d44f2019-11-09 15:02:53 +0200494 ANA_PFC_PFC_CFG, port);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200495
Alexandre Bellonia556c762018-05-14 22:04:57 +0200496 /* Core: Enable port for frame transfer */
Vladimir Oltean886e1382020-07-13 19:57:03 +0300497 ocelot_fields_write(ocelot, port,
498 QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200499
500 /* Flow control */
501 ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
502 SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
503 SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
504 SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
505 SYS_MAC_FC_CFG_FC_LINK_SPEED(speed),
Vladimir Oltean004d44f2019-11-09 15:02:53 +0200506 SYS_MAC_FC_CFG, port);
507 ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200508}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200509EXPORT_SYMBOL(ocelot_adjust_link);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200510
Vladimir Oltean5e256362019-11-14 17:03:27 +0200511void ocelot_port_enable(struct ocelot *ocelot, int port,
512 struct phy_device *phy)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200513{
Alexandre Bellonia556c762018-05-14 22:04:57 +0200514 /* Enable receiving frames on the port, and activate auto-learning of
515 * MAC addresses.
516 */
517 ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_LEARNAUTO |
518 ANA_PORT_PORT_CFG_RECV_ENA |
Vladimir Oltean004d44f2019-11-09 15:02:53 +0200519 ANA_PORT_PORT_CFG_PORTID_VAL(port),
520 ANA_PORT_PORT_CFG, port);
Vladimir Oltean889b8952019-11-09 15:02:57 +0200521}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200522EXPORT_SYMBOL(ocelot_port_enable);
Vladimir Oltean889b8952019-11-09 15:02:57 +0200523
Vladimir Oltean5e256362019-11-14 17:03:27 +0200524void ocelot_port_disable(struct ocelot *ocelot, int port)
Vladimir Oltean889b8952019-11-09 15:02:57 +0200525{
526 struct ocelot_port *ocelot_port = ocelot->ports[port];
527
528 ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
Vladimir Oltean886e1382020-07-13 19:57:03 +0300529 ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
Vladimir Oltean889b8952019-11-09 15:02:57 +0200530}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200531EXPORT_SYMBOL(ocelot_port_disable);
Vladimir Oltean889b8952019-11-09 15:02:57 +0200532
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300533void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
534 struct sk_buff *clone)
Yangbo Lu400928b2019-11-20 16:23:16 +0800535{
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300536 struct ocelot_port *ocelot_port = ocelot->ports[port];
Yangbo Lu400928b2019-11-20 16:23:16 +0800537
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300538 spin_lock(&ocelot_port->ts_id_lock);
Vladimir Oltean65652432020-09-18 04:07:24 +0300539
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300540 skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
Yangbo Luc4b364c2021-04-27 12:22:00 +0800541 /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
542 OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id;
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300543 ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
544 skb_queue_tail(&ocelot_port->tx_skbs, clone);
Vladimir Oltean65652432020-09-18 04:07:24 +0300545
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300546 spin_unlock(&ocelot_port->ts_id_lock);
Yangbo Lu400928b2019-11-20 16:23:16 +0800547}
548EXPORT_SYMBOL(ocelot_port_add_txtstamp_skb);
549
Yangbo Lue23a7b32019-11-20 16:23:15 +0800550static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
551 struct timespec64 *ts)
Antoine Tenart4e3b0462019-08-12 16:45:37 +0200552{
553 unsigned long flags;
554 u32 val;
555
556 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
557
558 /* Read current PTP time to get seconds */
559 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
560
561 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
562 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
563 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
564 ts->tv_sec = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
565
566 /* Read packet HW timestamp from FIFO */
567 val = ocelot_read(ocelot, SYS_PTP_TXSTAMP);
568 ts->tv_nsec = SYS_PTP_TXSTAMP_PTP_TXSTAMP(val);
569
570 /* Sec has incremented since the ts was registered */
571 if ((ts->tv_sec & 0x1) != !!(val & SYS_PTP_TXSTAMP_PTP_TXSTAMP_SEC))
572 ts->tv_sec--;
573
574 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
575}
Yangbo Lue23a7b32019-11-20 16:23:15 +0800576
577void ocelot_get_txtstamp(struct ocelot *ocelot)
578{
579 int budget = OCELOT_PTP_QUEUE_SZ;
580
581 while (budget--) {
Yangbo Lub049da12019-11-27 15:27:57 +0800582 struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
Yangbo Lue23a7b32019-11-20 16:23:15 +0800583 struct skb_shared_hwtstamps shhwtstamps;
Yangbo Lue23a7b32019-11-20 16:23:15 +0800584 struct ocelot_port *port;
585 struct timespec64 ts;
Yangbo Lub049da12019-11-27 15:27:57 +0800586 unsigned long flags;
Yangbo Lue23a7b32019-11-20 16:23:15 +0800587 u32 val, id, txport;
588
589 val = ocelot_read(ocelot, SYS_PTP_STATUS);
590
591 /* Check if a timestamp can be retrieved */
592 if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
593 break;
594
595 WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
596
597 /* Retrieve the ts ID and Tx port */
598 id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
599 txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
600
601 /* Retrieve its associated skb */
602 port = ocelot->ports[txport];
603
Yangbo Lub049da12019-11-27 15:27:57 +0800604 spin_lock_irqsave(&port->tx_skbs.lock, flags);
605
606 skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
Yangbo Luc4b364c2021-04-27 12:22:00 +0800607 if (OCELOT_SKB_CB(skb)->ts_id != id)
Yangbo Lue23a7b32019-11-20 16:23:15 +0800608 continue;
Yangbo Lub049da12019-11-27 15:27:57 +0800609 __skb_unlink(skb, &port->tx_skbs);
610 skb_match = skb;
Yangbo Lufc62c092019-11-27 15:27:56 +0800611 break;
Yangbo Lue23a7b32019-11-20 16:23:15 +0800612 }
613
Yangbo Lub049da12019-11-27 15:27:57 +0800614 spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
615
laurent brando5fd82202020-07-27 18:26:14 +0800616 /* Get the h/w timestamp */
617 ocelot_get_hwtimestamp(ocelot, &ts);
Yangbo Lue23a7b32019-11-20 16:23:15 +0800618
Yangbo Lub049da12019-11-27 15:27:57 +0800619 if (unlikely(!skb_match))
Yangbo Lue23a7b32019-11-20 16:23:15 +0800620 continue;
621
Yangbo Lue23a7b32019-11-20 16:23:15 +0800622 /* Set the timestamp into the skb */
623 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
624 shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
Vladimir Olteane2f9a8f2020-09-23 14:24:20 +0300625 skb_complete_tx_timestamp(skb_match, &shhwtstamps);
laurent brando5fd82202020-07-27 18:26:14 +0800626
627 /* Next ts */
628 ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
Yangbo Lue23a7b32019-11-20 16:23:15 +0800629 }
630}
631EXPORT_SYMBOL(ocelot_get_txtstamp);
Antoine Tenart4e3b0462019-08-12 16:45:37 +0200632
Vladimir Oltean924ee312021-02-14 00:37:59 +0200633static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh,
634 u32 *rval)
635{
636 u32 bytes_valid, val;
637
638 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
639 if (val == XTR_NOT_READY) {
640 if (ifh)
641 return -EIO;
642
643 do {
644 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
645 } while (val == XTR_NOT_READY);
646 }
647
648 switch (val) {
649 case XTR_ABORT:
650 return -EIO;
651 case XTR_EOF_0:
652 case XTR_EOF_1:
653 case XTR_EOF_2:
654 case XTR_EOF_3:
655 case XTR_PRUNED:
656 bytes_valid = XTR_VALID_BYTES(val);
657 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
658 if (val == XTR_ESCAPE)
659 *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
660 else
661 *rval = val;
662
663 return bytes_valid;
664 case XTR_ESCAPE:
665 *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
666
667 return 4;
668 default:
669 *rval = val;
670
671 return 4;
672 }
673}
674
675static int ocelot_xtr_poll_xfh(struct ocelot *ocelot, int grp, u32 *xfh)
676{
677 int i, err = 0;
678
679 for (i = 0; i < OCELOT_TAG_LEN / 4; i++) {
680 err = ocelot_rx_frame_word(ocelot, grp, true, &xfh[i]);
681 if (err != 4)
682 return (err < 0) ? err : -EIO;
683 }
684
685 return 0;
686}
687
688int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **nskb)
689{
690 struct skb_shared_hwtstamps *shhwtstamps;
Horatiu Vultur2ed2c5f2021-03-16 21:10:19 +0100691 u64 tod_in_ns, full_ts_in_ns;
Vladimir Oltean924ee312021-02-14 00:37:59 +0200692 u64 timestamp, src_port, len;
693 u32 xfh[OCELOT_TAG_LEN / 4];
694 struct net_device *dev;
695 struct timespec64 ts;
696 struct sk_buff *skb;
697 int sz, buf_len;
698 u32 val, *buf;
699 int err;
700
701 err = ocelot_xtr_poll_xfh(ocelot, grp, xfh);
702 if (err)
703 return err;
704
705 ocelot_xfh_get_src_port(xfh, &src_port);
706 ocelot_xfh_get_len(xfh, &len);
707 ocelot_xfh_get_rew_val(xfh, &timestamp);
708
709 if (WARN_ON(src_port >= ocelot->num_phys_ports))
710 return -EINVAL;
711
712 dev = ocelot->ops->port_to_netdev(ocelot, src_port);
713 if (!dev)
714 return -EINVAL;
715
716 skb = netdev_alloc_skb(dev, len);
717 if (unlikely(!skb)) {
718 netdev_err(dev, "Unable to allocate sk_buff\n");
719 return -ENOMEM;
720 }
721
722 buf_len = len - ETH_FCS_LEN;
723 buf = (u32 *)skb_put(skb, buf_len);
724
725 len = 0;
726 do {
727 sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
728 if (sz < 0) {
729 err = sz;
730 goto out_free_skb;
731 }
732 *buf++ = val;
733 len += sz;
734 } while (len < buf_len);
735
736 /* Read the FCS */
737 sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
738 if (sz < 0) {
739 err = sz;
740 goto out_free_skb;
741 }
742
743 /* Update the statistics if part of the FCS was read before */
744 len -= ETH_FCS_LEN - sz;
745
746 if (unlikely(dev->features & NETIF_F_RXFCS)) {
747 buf = (u32 *)skb_put(skb, ETH_FCS_LEN);
748 *buf = val;
749 }
750
751 if (ocelot->ptp) {
752 ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
753
754 tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec);
755 if ((tod_in_ns & 0xffffffff) < timestamp)
756 full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) |
757 timestamp;
758 else
759 full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) |
760 timestamp;
761
762 shhwtstamps = skb_hwtstamps(skb);
763 memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
764 shhwtstamps->hwtstamp = full_ts_in_ns;
765 }
766
767 /* Everything we see on an interface that is in the HW bridge
768 * has already been forwarded.
769 */
Vladimir Olteandf291e52021-03-19 01:36:36 +0200770 if (ocelot->ports[src_port]->bridge)
Vladimir Oltean924ee312021-02-14 00:37:59 +0200771 skb->offload_fwd_mark = 1;
772
773 skb->protocol = eth_type_trans(skb, dev);
Horatiu Vulturd8ea7ff2021-02-16 22:42:03 +0100774
Vladimir Oltean924ee312021-02-14 00:37:59 +0200775 *nskb = skb;
776
777 return 0;
778
779out_free_skb:
780 kfree_skb(skb);
781 return err;
782}
783EXPORT_SYMBOL(ocelot_xtr_poll_frame);
784
Vladimir Oltean137ffbc2021-02-14 00:37:54 +0200785bool ocelot_can_inject(struct ocelot *ocelot, int grp)
786{
787 u32 val = ocelot_read(ocelot, QS_INJ_STATUS);
788
789 if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))))
790 return false;
791 if (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp)))
792 return false;
793
794 return true;
795}
796EXPORT_SYMBOL(ocelot_can_inject);
797
798void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,
799 u32 rew_op, struct sk_buff *skb)
800{
Vladimir Oltean40d3f292021-02-14 00:37:56 +0200801 u32 ifh[OCELOT_TAG_LEN / 4] = {0};
Vladimir Oltean137ffbc2021-02-14 00:37:54 +0200802 unsigned int i, count, last;
803
804 ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
805 QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
806
Vladimir Oltean40d3f292021-02-14 00:37:56 +0200807 ocelot_ifh_set_bypass(ifh, 1);
Vladimir Oltean1f778d52021-02-15 15:31:43 +0200808 ocelot_ifh_set_dest(ifh, BIT_ULL(port));
Vladimir Oltean40d3f292021-02-14 00:37:56 +0200809 ocelot_ifh_set_tag_type(ifh, IFH_TAG_TYPE_C);
810 ocelot_ifh_set_vid(ifh, skb_vlan_tag_get(skb));
811 ocelot_ifh_set_rew_op(ifh, rew_op);
Vladimir Oltean137ffbc2021-02-14 00:37:54 +0200812
813 for (i = 0; i < OCELOT_TAG_LEN / 4; i++)
Vladimir Oltean40d3f292021-02-14 00:37:56 +0200814 ocelot_write_rix(ocelot, ifh[i], QS_INJ_WR, grp);
Vladimir Oltean137ffbc2021-02-14 00:37:54 +0200815
816 count = DIV_ROUND_UP(skb->len, 4);
817 last = skb->len % 4;
818 for (i = 0; i < count; i++)
819 ocelot_write_rix(ocelot, ((u32 *)skb->data)[i], QS_INJ_WR, grp);
820
821 /* Add padding */
822 while (i < (OCELOT_BUFFER_CELL_SZ / 4)) {
823 ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp);
824 i++;
825 }
826
827 /* Indicate EOF and valid bytes in last word */
828 ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
829 QS_INJ_CTRL_VLD_BYTES(skb->len < OCELOT_BUFFER_CELL_SZ ? 0 : last) |
830 QS_INJ_CTRL_EOF,
831 QS_INJ_CTRL, grp);
832
833 /* Add dummy CRC */
834 ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp);
835 skb_tx_timestamp(skb);
836
837 skb->dev->stats.tx_packets++;
838 skb->dev->stats.tx_bytes += skb->len;
839}
840EXPORT_SYMBOL(ocelot_port_inject_frame);
841
Vladimir Oltean0a6f17c2021-02-14 00:38:01 +0200842void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp)
843{
844 while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp))
845 ocelot_read_rix(ocelot, QS_XTR_RD, grp);
846}
847EXPORT_SYMBOL(ocelot_drain_cpu_queue);
848
Vladimir Oltean5e256362019-11-14 17:03:27 +0200849int ocelot_fdb_add(struct ocelot *ocelot, int port,
Vladimir Oltean87b0f982020-04-14 22:36:15 +0300850 const unsigned char *addr, u16 vid)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200851{
Vladimir Oltean471beb12020-06-21 14:46:00 +0300852 int pgid = port;
853
854 if (port == ocelot->npi)
855 pgid = PGID_CPU;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200856
Vladimir Oltean471beb12020-06-21 14:46:00 +0300857 return ocelot_mact_learn(ocelot, pgid, addr, vid, ENTRYTYPE_LOCKED);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200858}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200859EXPORT_SYMBOL(ocelot_fdb_add);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200860
Vladimir Oltean5e256362019-11-14 17:03:27 +0200861int ocelot_fdb_del(struct ocelot *ocelot, int port,
862 const unsigned char *addr, u16 vid)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200863{
Alexandre Bellonia556c762018-05-14 22:04:57 +0200864 return ocelot_mact_forget(ocelot, addr, vid);
865}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200866EXPORT_SYMBOL(ocelot_fdb_del);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200867
Vladimir Oltean9c90eea2020-06-20 18:43:44 +0300868int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
869 bool is_static, void *data)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200870{
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200871 struct ocelot_dump_ctx *dump = data;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200872 u32 portid = NETLINK_CB(dump->cb->skb).portid;
873 u32 seq = dump->cb->nlh->nlmsg_seq;
874 struct nlmsghdr *nlh;
875 struct ndmsg *ndm;
876
877 if (dump->idx < dump->cb->args[2])
878 goto skip;
879
880 nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
881 sizeof(*ndm), NLM_F_MULTI);
882 if (!nlh)
883 return -EMSGSIZE;
884
885 ndm = nlmsg_data(nlh);
886 ndm->ndm_family = AF_BRIDGE;
887 ndm->ndm_pad1 = 0;
888 ndm->ndm_pad2 = 0;
889 ndm->ndm_flags = NTF_SELF;
890 ndm->ndm_type = 0;
891 ndm->ndm_ifindex = dump->dev->ifindex;
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200892 ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200893
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200894 if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr))
Alexandre Bellonia556c762018-05-14 22:04:57 +0200895 goto nla_put_failure;
896
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200897 if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid))
Alexandre Bellonia556c762018-05-14 22:04:57 +0200898 goto nla_put_failure;
899
900 nlmsg_end(dump->skb, nlh);
901
902skip:
903 dump->idx++;
904 return 0;
905
906nla_put_failure:
907 nlmsg_cancel(dump->skb, nlh);
908 return -EMSGSIZE;
909}
Vladimir Oltean9c90eea2020-06-20 18:43:44 +0300910EXPORT_SYMBOL(ocelot_port_fdb_do_dump);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200911
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200912static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
913 struct ocelot_mact_entry *entry)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200914{
Alexandre Bellonia556c762018-05-14 22:04:57 +0200915 u32 val, dst, macl, mach;
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200916 char mac[ETH_ALEN];
Alexandre Bellonia556c762018-05-14 22:04:57 +0200917
918 /* Set row and column to read from */
919 ocelot_field_write(ocelot, ANA_TABLES_MACTINDX_M_INDEX, row);
920 ocelot_field_write(ocelot, ANA_TABLES_MACTINDX_BUCKET, col);
921
922 /* Issue a read command */
923 ocelot_write(ocelot,
924 ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
925 ANA_TABLES_MACACCESS);
926
927 if (ocelot_mact_wait_for_completion(ocelot))
928 return -ETIMEDOUT;
929
930 /* Read the entry flags */
931 val = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
932 if (!(val & ANA_TABLES_MACACCESS_VALID))
933 return -EINVAL;
934
935 /* If the entry read has another port configured as its destination,
936 * do not report it.
937 */
938 dst = (val & ANA_TABLES_MACACCESS_DEST_IDX_M) >> 3;
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200939 if (dst != port)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200940 return -EINVAL;
941
942 /* Get the entry's MAC address and VLAN id */
943 macl = ocelot_read(ocelot, ANA_TABLES_MACLDATA);
944 mach = ocelot_read(ocelot, ANA_TABLES_MACHDATA);
945
946 mac[0] = (mach >> 8) & 0xff;
947 mac[1] = (mach >> 0) & 0xff;
948 mac[2] = (macl >> 24) & 0xff;
949 mac[3] = (macl >> 16) & 0xff;
950 mac[4] = (macl >> 8) & 0xff;
951 mac[5] = (macl >> 0) & 0xff;
952
953 entry->vid = (mach >> 16) & 0xfff;
954 ether_addr_copy(entry->mac, mac);
955
956 return 0;
957}
958
Vladimir Oltean5e256362019-11-14 17:03:27 +0200959int ocelot_fdb_dump(struct ocelot *ocelot, int port,
960 dsa_fdb_dump_cb_t *cb, void *data)
Alexandre Bellonia556c762018-05-14 22:04:57 +0200961{
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200962 int i, j;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200963
Vladimir Oltean21ce7f32020-05-04 01:20:26 +0300964 /* Loop through all the mac tables entries. */
965 for (i = 0; i < ocelot->num_mact_rows; i++) {
Alexandre Bellonia556c762018-05-14 22:04:57 +0200966 for (j = 0; j < 4; j++) {
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200967 struct ocelot_mact_entry entry;
968 bool is_static;
969 int ret;
970
971 ret = ocelot_mact_read(ocelot, port, i, j, &entry);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200972 /* If the entry is invalid (wrong port, invalid...),
973 * skip it.
974 */
975 if (ret == -EINVAL)
976 continue;
977 else if (ret)
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200978 return ret;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200979
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200980 is_static = (entry.type == ENTRYTYPE_LOCKED);
981
982 ret = cb(entry.mac, entry.vid, is_static, data);
Alexandre Bellonia556c762018-05-14 22:04:57 +0200983 if (ret)
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200984 return ret;
Alexandre Bellonia556c762018-05-14 22:04:57 +0200985 }
986 }
987
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200988 return 0;
989}
Vladimir Oltean5e256362019-11-14 17:03:27 +0200990EXPORT_SYMBOL(ocelot_fdb_dump);
Vladimir Oltean531ee1a2019-11-09 15:02:49 +0200991
Yangbo Luf1459222019-11-20 16:23:14 +0800992int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
Antoine Tenart4e3b0462019-08-12 16:45:37 +0200993{
Antoine Tenart4e3b0462019-08-12 16:45:37 +0200994 return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
995 sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
996}
Yangbo Luf1459222019-11-20 16:23:14 +0800997EXPORT_SYMBOL(ocelot_hwstamp_get);
Antoine Tenart4e3b0462019-08-12 16:45:37 +0200998
Yangbo Luf1459222019-11-20 16:23:14 +0800999int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001000{
Vladimir Oltean306fd442019-11-09 15:02:50 +02001001 struct ocelot_port *ocelot_port = ocelot->ports[port];
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001002 struct hwtstamp_config cfg;
1003
1004 if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
1005 return -EFAULT;
1006
1007 /* reserved for future extensions */
1008 if (cfg.flags)
1009 return -EINVAL;
1010
1011 /* Tx type sanity check */
1012 switch (cfg.tx_type) {
1013 case HWTSTAMP_TX_ON:
Vladimir Oltean306fd442019-11-09 15:02:50 +02001014 ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001015 break;
1016 case HWTSTAMP_TX_ONESTEP_SYNC:
1017 /* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
1018 * need to update the origin time.
1019 */
Vladimir Oltean306fd442019-11-09 15:02:50 +02001020 ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001021 break;
1022 case HWTSTAMP_TX_OFF:
Vladimir Oltean306fd442019-11-09 15:02:50 +02001023 ocelot_port->ptp_cmd = 0;
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001024 break;
1025 default:
1026 return -ERANGE;
1027 }
1028
1029 mutex_lock(&ocelot->ptp_lock);
1030
1031 switch (cfg.rx_filter) {
1032 case HWTSTAMP_FILTER_NONE:
1033 break;
1034 case HWTSTAMP_FILTER_ALL:
1035 case HWTSTAMP_FILTER_SOME:
1036 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
1037 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
1038 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
1039 case HWTSTAMP_FILTER_NTP_ALL:
1040 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
1041 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
1042 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
1043 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1044 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1045 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1046 case HWTSTAMP_FILTER_PTP_V2_EVENT:
1047 case HWTSTAMP_FILTER_PTP_V2_SYNC:
1048 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
1049 cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
1050 break;
1051 default:
1052 mutex_unlock(&ocelot->ptp_lock);
1053 return -ERANGE;
1054 }
1055
1056 /* Commit back the result & save it */
1057 memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
1058 mutex_unlock(&ocelot->ptp_lock);
1059
1060 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
1061}
Yangbo Luf1459222019-11-20 16:23:14 +08001062EXPORT_SYMBOL(ocelot_hwstamp_set);
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001063
Vladimir Oltean5e256362019-11-14 17:03:27 +02001064void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001065{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001066 int i;
1067
1068 if (sset != ETH_SS_STATS)
1069 return;
1070
1071 for (i = 0; i < ocelot->num_stats; i++)
1072 memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name,
1073 ETH_GSTRING_LEN);
1074}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001075EXPORT_SYMBOL(ocelot_get_strings);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001076
Claudiu Manoil1e1caa92019-04-16 17:51:59 +03001077static void ocelot_update_stats(struct ocelot *ocelot)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001078{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001079 int i, j;
1080
1081 mutex_lock(&ocelot->stats_lock);
1082
1083 for (i = 0; i < ocelot->num_phys_ports; i++) {
1084 /* Configure the port to read the stats from */
1085 ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(i), SYS_STAT_CFG);
1086
1087 for (j = 0; j < ocelot->num_stats; j++) {
1088 u32 val;
1089 unsigned int idx = i * ocelot->num_stats + j;
1090
1091 val = ocelot_read_rix(ocelot, SYS_COUNT_RX_OCTETS,
1092 ocelot->stats_layout[j].offset);
1093
1094 if (val < (ocelot->stats[idx] & U32_MAX))
1095 ocelot->stats[idx] += (u64)1 << 32;
1096
1097 ocelot->stats[idx] = (ocelot->stats[idx] &
1098 ~(u64)U32_MAX) + val;
1099 }
1100 }
1101
Claudiu Manoil1e1caa92019-04-16 17:51:59 +03001102 mutex_unlock(&ocelot->stats_lock);
1103}
1104
1105static void ocelot_check_stats_work(struct work_struct *work)
1106{
1107 struct delayed_work *del_work = to_delayed_work(work);
1108 struct ocelot *ocelot = container_of(del_work, struct ocelot,
1109 stats_work);
1110
1111 ocelot_update_stats(ocelot);
1112
Alexandre Bellonia556c762018-05-14 22:04:57 +02001113 queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
1114 OCELOT_STATS_CHECK_DELAY);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001115}
1116
Vladimir Oltean5e256362019-11-14 17:03:27 +02001117void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001118{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001119 int i;
1120
1121 /* check and update now */
Claudiu Manoil1e1caa92019-04-16 17:51:59 +03001122 ocelot_update_stats(ocelot);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001123
1124 /* Copy all counters */
1125 for (i = 0; i < ocelot->num_stats; i++)
Vladimir Oltean004d44f2019-11-09 15:02:53 +02001126 *data++ = ocelot->stats[port * ocelot->num_stats + i];
Alexandre Bellonia556c762018-05-14 22:04:57 +02001127}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001128EXPORT_SYMBOL(ocelot_get_ethtool_stats);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001129
Vladimir Oltean5e256362019-11-14 17:03:27 +02001130int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
Vladimir Olteanc7282d32019-11-09 15:02:54 +02001131{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001132 if (sset != ETH_SS_STATS)
1133 return -EOPNOTSUPP;
Vladimir Olteanc7282d32019-11-09 15:02:54 +02001134
Alexandre Bellonia556c762018-05-14 22:04:57 +02001135 return ocelot->num_stats;
1136}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001137EXPORT_SYMBOL(ocelot_get_sset_count);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001138
Vladimir Oltean5e256362019-11-14 17:03:27 +02001139int ocelot_get_ts_info(struct ocelot *ocelot, int port,
1140 struct ethtool_ts_info *info)
Vladimir Olteanc7282d32019-11-09 15:02:54 +02001141{
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001142 info->phc_index = ocelot->ptp_clock ?
1143 ptp_clock_index(ocelot->ptp_clock) : -1;
Yangbo Lud2b09a82020-04-20 10:46:46 +08001144 if (info->phc_index == -1) {
1145 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
1146 SOF_TIMESTAMPING_RX_SOFTWARE |
1147 SOF_TIMESTAMPING_SOFTWARE;
1148 return 0;
1149 }
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001150 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
1151 SOF_TIMESTAMPING_RX_SOFTWARE |
1152 SOF_TIMESTAMPING_SOFTWARE |
1153 SOF_TIMESTAMPING_TX_HARDWARE |
1154 SOF_TIMESTAMPING_RX_HARDWARE |
1155 SOF_TIMESTAMPING_RAW_HARDWARE;
1156 info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
1157 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
1158 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
1159
1160 return 0;
1161}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001162EXPORT_SYMBOL(ocelot_get_ts_info);
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001163
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001164static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond,
1165 bool only_active_ports)
Vladimir Olteanb80af652021-02-06 00:02:14 +02001166{
1167 u32 mask = 0;
1168 int port;
1169
1170 for (port = 0; port < ocelot->num_phys_ports; port++) {
1171 struct ocelot_port *ocelot_port = ocelot->ports[port];
1172
1173 if (!ocelot_port)
1174 continue;
1175
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001176 if (ocelot_port->bond == bond) {
1177 if (only_active_ports && !ocelot_port->lag_tx_active)
1178 continue;
1179
Vladimir Olteanb80af652021-02-06 00:02:14 +02001180 mask |= BIT(port);
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001181 }
Vladimir Olteanb80af652021-02-06 00:02:14 +02001182 }
1183
1184 return mask;
1185}
1186
Vladimir Olteandf291e52021-03-19 01:36:36 +02001187static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot,
1188 struct net_device *bridge)
1189{
1190 u32 mask = 0;
1191 int port;
1192
1193 for (port = 0; port < ocelot->num_phys_ports; port++) {
1194 struct ocelot_port *ocelot_port = ocelot->ports[port];
1195
1196 if (!ocelot_port)
1197 continue;
1198
1199 if (ocelot_port->stp_state == BR_STATE_FORWARDING &&
1200 ocelot_port->bridge == bridge)
1201 mask |= BIT(port);
1202 }
1203
1204 return mask;
1205}
1206
Vladimir Olteane21268e2021-01-29 03:00:09 +02001207static u32 ocelot_get_dsa_8021q_cpu_mask(struct ocelot *ocelot)
Vladimir Oltean9b521252021-01-29 03:00:02 +02001208{
Vladimir Olteane21268e2021-01-29 03:00:09 +02001209 u32 mask = 0;
Vladimir Oltean9b521252021-01-29 03:00:02 +02001210 int port;
1211
Vladimir Olteane21268e2021-01-29 03:00:09 +02001212 for (port = 0; port < ocelot->num_phys_ports; port++) {
1213 struct ocelot_port *ocelot_port = ocelot->ports[port];
1214
1215 if (!ocelot_port)
1216 continue;
1217
1218 if (ocelot_port->is_dsa_8021q_cpu)
1219 mask |= BIT(port);
1220 }
1221
1222 return mask;
1223}
1224
1225void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
1226{
1227 unsigned long cpu_fwd_mask;
1228 int port;
1229
1230 /* If a DSA tag_8021q CPU exists, it needs to be included in the
1231 * regular forwarding path of the front ports regardless of whether
1232 * those are bridged or standalone.
1233 * If DSA tag_8021q is not used, this returns 0, which is fine because
1234 * the hardware-based CPU port module can be a destination for packets
1235 * even if it isn't part of PGID_SRC.
1236 */
1237 cpu_fwd_mask = ocelot_get_dsa_8021q_cpu_mask(ocelot);
1238
Vladimir Oltean9b521252021-01-29 03:00:02 +02001239 /* Apply FWD mask. The loop is needed to add/remove the current port as
1240 * a source for the other ports.
1241 */
1242 for (port = 0; port < ocelot->num_phys_ports; port++) {
Vladimir Olteane21268e2021-01-29 03:00:09 +02001243 struct ocelot_port *ocelot_port = ocelot->ports[port];
1244 unsigned long mask;
1245
1246 if (!ocelot_port) {
1247 /* Unused ports can't send anywhere */
1248 mask = 0;
1249 } else if (ocelot_port->is_dsa_8021q_cpu) {
1250 /* The DSA tag_8021q CPU ports need to be able to
1251 * forward packets to all other ports except for
1252 * themselves
1253 */
1254 mask = GENMASK(ocelot->num_phys_ports - 1, 0);
1255 mask &= ~cpu_fwd_mask;
Vladimir Olteandf291e52021-03-19 01:36:36 +02001256 } else if (ocelot_port->bridge) {
1257 struct net_device *bridge = ocelot_port->bridge;
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001258 struct net_device *bond = ocelot_port->bond;
Vladimir Oltean9b521252021-01-29 03:00:02 +02001259
Vladimir Olteandf291e52021-03-19 01:36:36 +02001260 mask = ocelot_get_bridge_fwd_mask(ocelot, bridge);
1261 mask &= ~BIT(port);
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001262 if (bond) {
1263 mask &= ~ocelot_get_bond_mask(ocelot, bond,
1264 false);
1265 }
Vladimir Oltean9b521252021-01-29 03:00:02 +02001266 } else {
Vladimir Olteane21268e2021-01-29 03:00:09 +02001267 /* Standalone ports forward only to DSA tag_8021q CPU
1268 * ports (if those exist), or to the hardware CPU port
1269 * module otherwise.
1270 */
1271 mask = cpu_fwd_mask;
Vladimir Oltean9b521252021-01-29 03:00:02 +02001272 }
Vladimir Olteane21268e2021-01-29 03:00:09 +02001273
1274 ocelot_write_rix(ocelot, mask, ANA_PGID_PGID, PGID_SRC + port);
Vladimir Oltean9b521252021-01-29 03:00:02 +02001275 }
1276}
Vladimir Olteane21268e2021-01-29 03:00:09 +02001277EXPORT_SYMBOL(ocelot_apply_bridge_fwd_mask);
Vladimir Oltean9b521252021-01-29 03:00:02 +02001278
Vladimir Oltean5e256362019-11-14 17:03:27 +02001279void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001280{
Vladimir Oltean421741e2021-02-12 17:15:59 +02001281 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Olteandf291e52021-03-19 01:36:36 +02001282 u32 learn_ena = 0;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001283
Vladimir Olteandf291e52021-03-19 01:36:36 +02001284 ocelot_port->stp_state = state;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001285
Vladimir Olteandf291e52021-03-19 01:36:36 +02001286 if ((state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING) &&
1287 ocelot_port->learn_ena)
1288 learn_ena = ANA_PORT_PORT_CFG_LEARN_ENA;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001289
Vladimir Olteandf291e52021-03-19 01:36:36 +02001290 ocelot_rmw_gix(ocelot, learn_ena, ANA_PORT_PORT_CFG_LEARN_ENA,
1291 ANA_PORT_PORT_CFG, port);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001292
Vladimir Oltean9b521252021-01-29 03:00:02 +02001293 ocelot_apply_bridge_fwd_mask(ocelot);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001294}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001295EXPORT_SYMBOL(ocelot_bridge_stp_state_set);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001296
Vladimir Oltean5e256362019-11-14 17:03:27 +02001297void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs)
Vladimir Oltean4bda1412019-11-09 15:02:51 +02001298{
Vladimir Olteanc0d7ecc2020-05-04 01:20:27 +03001299 unsigned int age_period = ANA_AUTOAGE_AGE_PERIOD(msecs / 2000);
1300
1301 /* Setting AGE_PERIOD to zero effectively disables automatic aging,
1302 * which is clearly not what our intention is. So avoid that.
1303 */
1304 if (!age_period)
1305 age_period = 1;
1306
1307 ocelot_rmw(ocelot, age_period, ANA_AUTOAGE_AGE_PERIOD_M, ANA_AUTOAGE);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001308}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001309EXPORT_SYMBOL(ocelot_set_ageing_time);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001310
Alexandre Bellonia556c762018-05-14 22:04:57 +02001311static struct ocelot_multicast *ocelot_multicast_get(struct ocelot *ocelot,
1312 const unsigned char *addr,
1313 u16 vid)
1314{
1315 struct ocelot_multicast *mc;
1316
1317 list_for_each_entry(mc, &ocelot->multicast, list) {
1318 if (ether_addr_equal(mc->addr, addr) && mc->vid == vid)
1319 return mc;
1320 }
1321
1322 return NULL;
1323}
1324
Vladimir Oltean9403c152020-06-21 14:46:03 +03001325static enum macaccess_entry_type ocelot_classify_mdb(const unsigned char *addr)
1326{
1327 if (addr[0] == 0x01 && addr[1] == 0x00 && addr[2] == 0x5e)
1328 return ENTRYTYPE_MACv4;
1329 if (addr[0] == 0x33 && addr[1] == 0x33)
1330 return ENTRYTYPE_MACv6;
Vladimir Oltean7c313142020-10-29 04:27:34 +02001331 return ENTRYTYPE_LOCKED;
Vladimir Oltean9403c152020-06-21 14:46:03 +03001332}
1333
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001334static struct ocelot_pgid *ocelot_pgid_alloc(struct ocelot *ocelot, int index,
1335 unsigned long ports)
Vladimir Oltean9403c152020-06-21 14:46:03 +03001336{
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001337 struct ocelot_pgid *pgid;
1338
1339 pgid = kzalloc(sizeof(*pgid), GFP_KERNEL);
1340 if (!pgid)
1341 return ERR_PTR(-ENOMEM);
1342
1343 pgid->ports = ports;
1344 pgid->index = index;
1345 refcount_set(&pgid->refcount, 1);
1346 list_add_tail(&pgid->list, &ocelot->pgids);
1347
1348 return pgid;
1349}
1350
1351static void ocelot_pgid_free(struct ocelot *ocelot, struct ocelot_pgid *pgid)
1352{
1353 if (!refcount_dec_and_test(&pgid->refcount))
1354 return;
1355
1356 list_del(&pgid->list);
1357 kfree(pgid);
1358}
1359
1360static struct ocelot_pgid *ocelot_mdb_get_pgid(struct ocelot *ocelot,
1361 const struct ocelot_multicast *mc)
1362{
1363 struct ocelot_pgid *pgid;
1364 int index;
Vladimir Oltean9403c152020-06-21 14:46:03 +03001365
1366 /* According to VSC7514 datasheet 3.9.1.5 IPv4 Multicast Entries and
1367 * 3.9.1.6 IPv6 Multicast Entries, "Instead of a lookup in the
1368 * destination mask table (PGID), the destination set is programmed as
1369 * part of the entry MAC address.", and the DEST_IDX is set to 0.
1370 */
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001371 if (mc->entry_type == ENTRYTYPE_MACv4 ||
1372 mc->entry_type == ENTRYTYPE_MACv6)
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001373 return ocelot_pgid_alloc(ocelot, 0, mc->ports);
Vladimir Oltean9403c152020-06-21 14:46:03 +03001374
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001375 list_for_each_entry(pgid, &ocelot->pgids, list) {
1376 /* When searching for a nonreserved multicast PGID, ignore the
1377 * dummy PGID of zero that we have for MACv4/MACv6 entries
1378 */
1379 if (pgid->index && pgid->ports == mc->ports) {
1380 refcount_inc(&pgid->refcount);
1381 return pgid;
1382 }
1383 }
1384
1385 /* Search for a free index in the nonreserved multicast PGID area */
1386 for_each_nonreserved_multicast_dest_pgid(ocelot, index) {
Vladimir Oltean9403c152020-06-21 14:46:03 +03001387 bool used = false;
1388
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001389 list_for_each_entry(pgid, &ocelot->pgids, list) {
1390 if (pgid->index == index) {
Vladimir Oltean9403c152020-06-21 14:46:03 +03001391 used = true;
1392 break;
1393 }
1394 }
1395
1396 if (!used)
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001397 return ocelot_pgid_alloc(ocelot, index, mc->ports);
Vladimir Oltean9403c152020-06-21 14:46:03 +03001398 }
1399
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001400 return ERR_PTR(-ENOSPC);
Vladimir Oltean9403c152020-06-21 14:46:03 +03001401}
1402
1403static void ocelot_encode_ports_to_mdb(unsigned char *addr,
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001404 struct ocelot_multicast *mc)
Vladimir Oltean9403c152020-06-21 14:46:03 +03001405{
Vladimir Olteanebbd8602020-10-29 04:27:35 +02001406 ether_addr_copy(addr, mc->addr);
Vladimir Oltean9403c152020-06-21 14:46:03 +03001407
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001408 if (mc->entry_type == ENTRYTYPE_MACv4) {
Vladimir Oltean9403c152020-06-21 14:46:03 +03001409 addr[0] = 0;
1410 addr[1] = mc->ports >> 8;
1411 addr[2] = mc->ports & 0xff;
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001412 } else if (mc->entry_type == ENTRYTYPE_MACv6) {
Vladimir Oltean9403c152020-06-21 14:46:03 +03001413 addr[0] = mc->ports >> 8;
1414 addr[1] = mc->ports & 0xff;
1415 }
1416}
1417
Vladimir Oltean209edf92020-06-21 14:46:01 +03001418int ocelot_port_mdb_add(struct ocelot *ocelot, int port,
1419 const struct switchdev_obj_port_mdb *mdb)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001420{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001421 unsigned char addr[ETH_ALEN];
Vladimir Oltean004d44f2019-11-09 15:02:53 +02001422 struct ocelot_multicast *mc;
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001423 struct ocelot_pgid *pgid;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001424 u16 vid = mdb->vid;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001425
Vladimir Oltean471beb12020-06-21 14:46:00 +03001426 if (port == ocelot->npi)
1427 port = ocelot->num_phys_ports;
1428
Alexandre Bellonia556c762018-05-14 22:04:57 +02001429 mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
1430 if (!mc) {
Vladimir Oltean728e69a2020-10-29 04:27:36 +02001431 /* New entry */
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001432 mc = devm_kzalloc(ocelot->dev, sizeof(*mc), GFP_KERNEL);
1433 if (!mc)
1434 return -ENOMEM;
1435
1436 mc->entry_type = ocelot_classify_mdb(mdb->addr);
1437 ether_addr_copy(mc->addr, mdb->addr);
1438 mc->vid = vid;
1439
Alexandre Bellonia556c762018-05-14 22:04:57 +02001440 list_add_tail(&mc->list, &ocelot->multicast);
Vladimir Oltean728e69a2020-10-29 04:27:36 +02001441 } else {
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001442 /* Existing entry. Clean up the current port mask from
1443 * hardware now, because we'll be modifying it.
1444 */
1445 ocelot_pgid_free(ocelot, mc->pgid);
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001446 ocelot_encode_ports_to_mdb(addr, mc);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001447 ocelot_mact_forget(ocelot, addr, vid);
1448 }
1449
Vladimir Oltean004d44f2019-11-09 15:02:53 +02001450 mc->ports |= BIT(port);
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001451
1452 pgid = ocelot_mdb_get_pgid(ocelot, mc);
1453 if (IS_ERR(pgid)) {
1454 dev_err(ocelot->dev,
1455 "Cannot allocate PGID for mdb %pM vid %d\n",
1456 mc->addr, mc->vid);
1457 devm_kfree(ocelot->dev, mc);
1458 return PTR_ERR(pgid);
1459 }
1460 mc->pgid = pgid;
1461
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001462 ocelot_encode_ports_to_mdb(addr, mc);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001463
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001464 if (mc->entry_type != ENTRYTYPE_MACv4 &&
1465 mc->entry_type != ENTRYTYPE_MACv6)
1466 ocelot_write_rix(ocelot, pgid->ports, ANA_PGID_PGID,
1467 pgid->index);
1468
1469 return ocelot_mact_learn(ocelot, pgid->index, addr, vid,
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001470 mc->entry_type);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001471}
Vladimir Oltean209edf92020-06-21 14:46:01 +03001472EXPORT_SYMBOL(ocelot_port_mdb_add);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001473
Vladimir Oltean209edf92020-06-21 14:46:01 +03001474int ocelot_port_mdb_del(struct ocelot *ocelot, int port,
1475 const struct switchdev_obj_port_mdb *mdb)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001476{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001477 unsigned char addr[ETH_ALEN];
Vladimir Oltean004d44f2019-11-09 15:02:53 +02001478 struct ocelot_multicast *mc;
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001479 struct ocelot_pgid *pgid;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001480 u16 vid = mdb->vid;
1481
Vladimir Oltean471beb12020-06-21 14:46:00 +03001482 if (port == ocelot->npi)
1483 port = ocelot->num_phys_ports;
1484
Alexandre Bellonia556c762018-05-14 22:04:57 +02001485 mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
1486 if (!mc)
1487 return -ENOENT;
1488
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001489 ocelot_encode_ports_to_mdb(addr, mc);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001490 ocelot_mact_forget(ocelot, addr, vid);
1491
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001492 ocelot_pgid_free(ocelot, mc->pgid);
Vladimir Oltean004d44f2019-11-09 15:02:53 +02001493 mc->ports &= ~BIT(port);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001494 if (!mc->ports) {
1495 list_del(&mc->list);
1496 devm_kfree(ocelot->dev, mc);
1497 return 0;
1498 }
1499
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001500 /* We have a PGID with fewer ports now */
1501 pgid = ocelot_mdb_get_pgid(ocelot, mc);
1502 if (IS_ERR(pgid))
1503 return PTR_ERR(pgid);
1504 mc->pgid = pgid;
1505
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001506 ocelot_encode_ports_to_mdb(addr, mc);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001507
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001508 if (mc->entry_type != ENTRYTYPE_MACv4 &&
1509 mc->entry_type != ENTRYTYPE_MACv6)
1510 ocelot_write_rix(ocelot, pgid->ports, ANA_PGID_PGID,
1511 pgid->index);
1512
1513 return ocelot_mact_learn(ocelot, pgid->index, addr, vid,
Vladimir Olteanbb8d53f2020-10-29 04:27:37 +02001514 mc->entry_type);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001515}
Vladimir Oltean209edf92020-06-21 14:46:01 +03001516EXPORT_SYMBOL(ocelot_port_mdb_del);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001517
Vladimir Olteane4bd44e2021-03-23 01:51:52 +02001518void ocelot_port_bridge_join(struct ocelot *ocelot, int port,
1519 struct net_device *bridge)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001520{
Vladimir Olteandf291e52021-03-19 01:36:36 +02001521 struct ocelot_port *ocelot_port = ocelot->ports[port];
Alexandre Bellonia556c762018-05-14 22:04:57 +02001522
Vladimir Olteandf291e52021-03-19 01:36:36 +02001523 ocelot_port->bridge = bridge;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001524
Vladimir Olteane4bd44e2021-03-23 01:51:52 +02001525 ocelot_apply_bridge_fwd_mask(ocelot);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001526}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001527EXPORT_SYMBOL(ocelot_port_bridge_join);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001528
Vladimir Olteane4bd44e2021-03-23 01:51:52 +02001529void ocelot_port_bridge_leave(struct ocelot *ocelot, int port,
1530 struct net_device *bridge)
Alexandre Bellonia556c762018-05-14 22:04:57 +02001531{
Vladimir Olteandf291e52021-03-19 01:36:36 +02001532 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Olteanc3e58a752020-10-31 12:29:12 +02001533 struct ocelot_vlan pvid = {0}, native_vlan = {0};
Vladimir Oltean2e554a72020-10-03 01:06:46 +03001534
Vladimir Olteandf291e52021-03-19 01:36:36 +02001535 ocelot_port->bridge = NULL;
Antoine Tenart71425292018-06-26 14:28:49 +02001536
Vladimir Olteanc3e58a752020-10-31 12:29:12 +02001537 ocelot_port_set_pvid(ocelot, port, pvid);
Vladimir Oltean2f0402f2020-10-31 12:29:15 +02001538 ocelot_port_set_native_vlan(ocelot, port, native_vlan);
Vladimir Olteane4bd44e2021-03-23 01:51:52 +02001539 ocelot_apply_bridge_fwd_mask(ocelot);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001540}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001541EXPORT_SYMBOL(ocelot_port_bridge_leave);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001542
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001543static void ocelot_set_aggr_pgids(struct ocelot *ocelot)
1544{
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001545 unsigned long visited = GENMASK(ocelot->num_phys_ports - 1, 0);
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001546 int i, port, lag;
1547
1548 /* Reset destination and aggregation PGIDS */
Vladimir Oltean96b029b2020-06-21 14:46:02 +03001549 for_each_unicast_dest_pgid(ocelot, port)
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001550 ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, port);
1551
Vladimir Oltean96b029b2020-06-21 14:46:02 +03001552 for_each_aggr_pgid(ocelot, i)
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001553 ocelot_write_rix(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
1554 ANA_PGID_PGID, i);
1555
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001556 /* The visited ports bitmask holds the list of ports offloading any
1557 * bonding interface. Initially we mark all these ports as unvisited,
1558 * then every time we visit a port in this bitmask, we know that it is
1559 * the lowest numbered port, i.e. the one whose logical ID == physical
1560 * port ID == LAG ID. So we mark as visited all further ports in the
1561 * bitmask that are offloading the same bonding interface. This way,
1562 * we set up the aggregation PGIDs only once per bonding interface.
1563 */
1564 for (port = 0; port < ocelot->num_phys_ports; port++) {
1565 struct ocelot_port *ocelot_port = ocelot->ports[port];
1566
1567 if (!ocelot_port || !ocelot_port->bond)
1568 continue;
1569
1570 visited &= ~BIT(port);
1571 }
1572
1573 /* Now, set PGIDs for each active LAG */
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001574 for (lag = 0; lag < ocelot->num_phys_ports; lag++) {
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001575 struct net_device *bond = ocelot->ports[lag]->bond;
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001576 int num_active_ports = 0;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001577 unsigned long bond_mask;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001578 u8 aggr_idx[16];
1579
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001580 if (!bond || (visited & BIT(lag)))
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001581 continue;
1582
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001583 bond_mask = ocelot_get_bond_mask(ocelot, bond, true);
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001584
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001585 for_each_set_bit(port, &bond_mask, ocelot->num_phys_ports) {
1586 // Destination mask
1587 ocelot_write_rix(ocelot, bond_mask,
1588 ANA_PGID_PGID, port);
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001589 aggr_idx[num_active_ports++] = port;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001590 }
1591
Vladimir Oltean96b029b2020-06-21 14:46:02 +03001592 for_each_aggr_pgid(ocelot, i) {
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001593 u32 ac;
1594
1595 ac = ocelot_read_rix(ocelot, ANA_PGID_PGID, i);
1596 ac &= ~bond_mask;
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001597 /* Don't do division by zero if there was no active
1598 * port. Just make all aggregation codes zero.
1599 */
1600 if (num_active_ports)
1601 ac |= BIT(aggr_idx[i % num_active_ports]);
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001602 ocelot_write_rix(ocelot, ac, ANA_PGID_PGID, i);
1603 }
Vladimir Oltean528d3f12021-02-06 00:02:17 +02001604
1605 /* Mark all ports in the same LAG as visited to avoid applying
1606 * the same config again.
1607 */
1608 for (port = lag; port < ocelot->num_phys_ports; port++) {
1609 struct ocelot_port *ocelot_port = ocelot->ports[port];
1610
1611 if (!ocelot_port)
1612 continue;
1613
1614 if (ocelot_port->bond == bond)
1615 visited |= BIT(port);
1616 }
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001617 }
1618}
1619
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001620/* When offloading a bonding interface, the switch ports configured under the
1621 * same bond must have the same logical port ID, equal to the physical port ID
1622 * of the lowest numbered physical port in that bond. Otherwise, in standalone/
1623 * bridged mode, each port has a logical port ID equal to its physical port ID.
1624 */
1625static void ocelot_setup_logical_port_ids(struct ocelot *ocelot)
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001626{
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001627 int port;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001628
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001629 for (port = 0; port < ocelot->num_phys_ports; port++) {
1630 struct ocelot_port *ocelot_port = ocelot->ports[port];
1631 struct net_device *bond;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001632
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001633 if (!ocelot_port)
1634 continue;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001635
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001636 bond = ocelot_port->bond;
1637 if (bond) {
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001638 int lag = __ffs(ocelot_get_bond_mask(ocelot, bond,
1639 false));
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001640
1641 ocelot_rmw_gix(ocelot,
1642 ANA_PORT_PORT_CFG_PORTID_VAL(lag),
1643 ANA_PORT_PORT_CFG_PORTID_VAL_M,
1644 ANA_PORT_PORT_CFG, port);
1645 } else {
1646 ocelot_rmw_gix(ocelot,
1647 ANA_PORT_PORT_CFG_PORTID_VAL(port),
1648 ANA_PORT_PORT_CFG_PORTID_VAL_M,
1649 ANA_PORT_PORT_CFG, port);
1650 }
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001651 }
1652}
1653
Vladimir Oltean9c90eea2020-06-20 18:43:44 +03001654int ocelot_port_lag_join(struct ocelot *ocelot, int port,
Vladimir Oltean583cbbe2021-02-06 00:02:12 +02001655 struct net_device *bond,
1656 struct netdev_lag_upper_info *info)
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001657{
Vladimir Oltean583cbbe2021-02-06 00:02:12 +02001658 if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
1659 return -EOPNOTSUPP;
1660
Vladimir Olteanb80af652021-02-06 00:02:14 +02001661 ocelot->ports[port]->bond = bond;
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001662
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001663 ocelot_setup_logical_port_ids(ocelot);
Vladimir Oltean9b521252021-01-29 03:00:02 +02001664 ocelot_apply_bridge_fwd_mask(ocelot);
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001665 ocelot_set_aggr_pgids(ocelot);
1666
1667 return 0;
1668}
Vladimir Oltean9c90eea2020-06-20 18:43:44 +03001669EXPORT_SYMBOL(ocelot_port_lag_join);
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001670
Vladimir Oltean9c90eea2020-06-20 18:43:44 +03001671void ocelot_port_lag_leave(struct ocelot *ocelot, int port,
1672 struct net_device *bond)
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001673{
Vladimir Olteanb80af652021-02-06 00:02:14 +02001674 ocelot->ports[port]->bond = NULL;
1675
Vladimir Oltean2527f2e2021-02-06 00:02:16 +02001676 ocelot_setup_logical_port_ids(ocelot);
Vladimir Oltean9b521252021-01-29 03:00:02 +02001677 ocelot_apply_bridge_fwd_mask(ocelot);
Alexandre Bellonidc96ee32018-06-26 14:28:48 +02001678 ocelot_set_aggr_pgids(ocelot);
1679}
Vladimir Oltean9c90eea2020-06-20 18:43:44 +03001680EXPORT_SYMBOL(ocelot_port_lag_leave);
Petr Machata0e332c82018-11-22 23:30:11 +00001681
Vladimir Oltean23ca3b72021-02-06 00:02:19 +02001682void ocelot_port_lag_change(struct ocelot *ocelot, int port, bool lag_tx_active)
1683{
1684 struct ocelot_port *ocelot_port = ocelot->ports[port];
1685
1686 ocelot_port->lag_tx_active = lag_tx_active;
1687
1688 /* Rebalance the LAGs */
1689 ocelot_set_aggr_pgids(ocelot);
1690}
1691EXPORT_SYMBOL(ocelot_port_lag_change);
1692
Vladimir Olteana8015de2020-03-10 03:28:18 +02001693/* Configure the maximum SDU (L2 payload) on RX to the value specified in @sdu.
1694 * The length of VLAN tags is accounted for automatically via DEV_MAC_TAGS_CFG.
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001695 * In the special case that it's the NPI port that we're configuring, the
1696 * length of the tag and optional prefix needs to be accounted for privately,
1697 * in order to be able to sustain communication at the requested @sdu.
Vladimir Olteana8015de2020-03-10 03:28:18 +02001698 */
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001699void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
Vladimir Oltean31350d72019-11-09 15:02:56 +02001700{
1701 struct ocelot_port *ocelot_port = ocelot->ports[port];
Vladimir Olteana8015de2020-03-10 03:28:18 +02001702 int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
Vladimir Olteane8e6e732020-07-13 19:57:05 +03001703 int pause_start, pause_stop;
Vladimir Oltean601e9842020-10-05 12:09:11 +03001704 int atop, atop_tot;
Vladimir Oltean31350d72019-11-09 15:02:56 +02001705
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001706 if (port == ocelot->npi) {
1707 maxlen += OCELOT_TAG_LEN;
1708
Vladimir Olteancacea622021-01-29 03:00:03 +02001709 if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_SHORT)
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001710 maxlen += OCELOT_SHORT_PREFIX_LEN;
Vladimir Olteancacea622021-01-29 03:00:03 +02001711 else if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_LONG)
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001712 maxlen += OCELOT_LONG_PREFIX_LEN;
1713 }
1714
Vladimir Olteana8015de2020-03-10 03:28:18 +02001715 ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);
Vladimir Olteanfa914e92019-11-14 17:03:23 +02001716
Vladimir Olteane8e6e732020-07-13 19:57:05 +03001717 /* Set Pause watermark hysteresis */
1718 pause_start = 6 * maxlen / OCELOT_BUFFER_CELL_SZ;
1719 pause_stop = 4 * maxlen / OCELOT_BUFFER_CELL_SZ;
Maxim Kochetkov541132f2020-07-13 19:57:07 +03001720 ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_START,
1721 pause_start);
1722 ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_STOP,
1723 pause_stop);
Vladimir Olteanfa914e92019-11-14 17:03:23 +02001724
Vladimir Oltean601e9842020-10-05 12:09:11 +03001725 /* Tail dropping watermarks */
Vladimir Olteanf6fe01d2021-01-15 04:11:11 +02001726 atop_tot = (ocelot->packet_buffer_size - 9 * maxlen) /
Vladimir Olteana8015de2020-03-10 03:28:18 +02001727 OCELOT_BUFFER_CELL_SZ;
Vladimir Oltean601e9842020-10-05 12:09:11 +03001728 atop = (9 * maxlen) / OCELOT_BUFFER_CELL_SZ;
1729 ocelot_write_rix(ocelot, ocelot->ops->wm_enc(atop), SYS_ATOP, port);
1730 ocelot_write(ocelot, ocelot->ops->wm_enc(atop_tot), SYS_ATOP_TOT_CFG);
Vladimir Olteanfa914e92019-11-14 17:03:23 +02001731}
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001732EXPORT_SYMBOL(ocelot_port_set_maxlen);
1733
1734int ocelot_get_max_mtu(struct ocelot *ocelot, int port)
1735{
1736 int max_mtu = 65535 - ETH_HLEN - ETH_FCS_LEN;
1737
1738 if (port == ocelot->npi) {
1739 max_mtu -= OCELOT_TAG_LEN;
1740
Vladimir Olteancacea622021-01-29 03:00:03 +02001741 if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_SHORT)
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001742 max_mtu -= OCELOT_SHORT_PREFIX_LEN;
Vladimir Olteancacea622021-01-29 03:00:03 +02001743 else if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_LONG)
Vladimir Oltean0b912fc2020-03-27 21:55:47 +02001744 max_mtu -= OCELOT_LONG_PREFIX_LEN;
1745 }
1746
1747 return max_mtu;
1748}
1749EXPORT_SYMBOL(ocelot_get_max_mtu);
Vladimir Olteanfa914e92019-11-14 17:03:23 +02001750
Vladimir Oltean421741e2021-02-12 17:15:59 +02001751static void ocelot_port_set_learning(struct ocelot *ocelot, int port,
1752 bool enabled)
1753{
1754 struct ocelot_port *ocelot_port = ocelot->ports[port];
1755 u32 val = 0;
1756
1757 if (enabled)
1758 val = ANA_PORT_PORT_CFG_LEARN_ENA;
1759
1760 ocelot_rmw_gix(ocelot, val, ANA_PORT_PORT_CFG_LEARN_ENA,
1761 ANA_PORT_PORT_CFG, port);
1762
1763 ocelot_port->learn_ena = enabled;
1764}
1765
1766static void ocelot_port_set_ucast_flood(struct ocelot *ocelot, int port,
1767 bool enabled)
1768{
1769 u32 val = 0;
1770
1771 if (enabled)
1772 val = BIT(port);
1773
1774 ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_UC);
1775}
1776
1777static void ocelot_port_set_mcast_flood(struct ocelot *ocelot, int port,
1778 bool enabled)
1779{
1780 u32 val = 0;
1781
1782 if (enabled)
1783 val = BIT(port);
1784
1785 ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MC);
1786}
1787
1788static void ocelot_port_set_bcast_flood(struct ocelot *ocelot, int port,
1789 bool enabled)
1790{
1791 u32 val = 0;
1792
1793 if (enabled)
1794 val = BIT(port);
1795
1796 ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_BC);
1797}
1798
1799int ocelot_port_pre_bridge_flags(struct ocelot *ocelot, int port,
1800 struct switchdev_brport_flags flags)
1801{
1802 if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
1803 BR_BCAST_FLOOD))
1804 return -EINVAL;
1805
1806 return 0;
1807}
1808EXPORT_SYMBOL(ocelot_port_pre_bridge_flags);
1809
1810void ocelot_port_bridge_flags(struct ocelot *ocelot, int port,
1811 struct switchdev_brport_flags flags)
1812{
1813 if (flags.mask & BR_LEARNING)
1814 ocelot_port_set_learning(ocelot, port,
1815 !!(flags.val & BR_LEARNING));
1816
1817 if (flags.mask & BR_FLOOD)
1818 ocelot_port_set_ucast_flood(ocelot, port,
1819 !!(flags.val & BR_FLOOD));
1820
1821 if (flags.mask & BR_MCAST_FLOOD)
1822 ocelot_port_set_mcast_flood(ocelot, port,
1823 !!(flags.val & BR_MCAST_FLOOD));
1824
1825 if (flags.mask & BR_BCAST_FLOOD)
1826 ocelot_port_set_bcast_flood(ocelot, port,
1827 !!(flags.val & BR_BCAST_FLOOD));
1828}
1829EXPORT_SYMBOL(ocelot_port_bridge_flags);
1830
Vladimir Oltean5e256362019-11-14 17:03:27 +02001831void ocelot_init_port(struct ocelot *ocelot, int port)
Vladimir Olteanfa914e92019-11-14 17:03:23 +02001832{
1833 struct ocelot_port *ocelot_port = ocelot->ports[port];
1834
Yangbo Lub049da12019-11-27 15:27:57 +08001835 skb_queue_head_init(&ocelot_port->tx_skbs);
Vladimir Oltean65652432020-09-18 04:07:24 +03001836 spin_lock_init(&ocelot_port->ts_id_lock);
Vladimir Oltean31350d72019-11-09 15:02:56 +02001837
1838 /* Basic L2 initialization */
1839
Vladimir Oltean5bc9d2e2019-11-14 17:03:22 +02001840 /* Set MAC IFG Gaps
1841 * FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 0
1842 * !FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 5
1843 */
1844 ocelot_port_writel(ocelot_port, DEV_MAC_IFG_CFG_TX_IFG(5),
1845 DEV_MAC_IFG_CFG);
1846
1847 /* Load seed (0) and set MAC HDX late collision */
1848 ocelot_port_writel(ocelot_port, DEV_MAC_HDX_CFG_LATE_COL_POS(67) |
1849 DEV_MAC_HDX_CFG_SEED_LOAD,
1850 DEV_MAC_HDX_CFG);
1851 mdelay(1);
1852 ocelot_port_writel(ocelot_port, DEV_MAC_HDX_CFG_LATE_COL_POS(67),
1853 DEV_MAC_HDX_CFG);
1854
1855 /* Set Max Length and maximum tags allowed */
Vladimir Olteana8015de2020-03-10 03:28:18 +02001856 ocelot_port_set_maxlen(ocelot, port, ETH_DATA_LEN);
Vladimir Oltean5bc9d2e2019-11-14 17:03:22 +02001857 ocelot_port_writel(ocelot_port, DEV_MAC_TAGS_CFG_TAG_ID(ETH_P_8021AD) |
1858 DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
Vladimir Olteana8015de2020-03-10 03:28:18 +02001859 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA |
Vladimir Oltean5bc9d2e2019-11-14 17:03:22 +02001860 DEV_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA,
1861 DEV_MAC_TAGS_CFG);
1862
1863 /* Set SMAC of Pause frame (00:00:00:00:00:00) */
1864 ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_HIGH_CFG);
1865 ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG);
1866
Vladimir Olteane8e6e732020-07-13 19:57:05 +03001867 /* Enable transmission of pause frames */
Maxim Kochetkov541132f2020-07-13 19:57:07 +03001868 ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1);
Vladimir Olteane8e6e732020-07-13 19:57:05 +03001869
Vladimir Oltean31350d72019-11-09 15:02:56 +02001870 /* Drop frames with multicast source address */
1871 ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
1872 ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
1873 ANA_PORT_DROP_CFG, port);
1874
1875 /* Set default VLAN and tag type to 8021Q. */
1876 ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q),
1877 REW_PORT_VLAN_CFG_PORT_TPID_M,
1878 REW_PORT_VLAN_CFG, port);
1879
Vladimir Oltean421741e2021-02-12 17:15:59 +02001880 /* Disable source address learning for standalone mode */
1881 ocelot_port_set_learning(ocelot, port, false);
1882
Vladimir Oltean31350d72019-11-09 15:02:56 +02001883 /* Enable vcap lookups */
1884 ocelot_vcap_enable(ocelot, port);
1885}
Vladimir Oltean5e256362019-11-14 17:03:27 +02001886EXPORT_SYMBOL(ocelot_init_port);
Vladimir Oltean31350d72019-11-09 15:02:56 +02001887
Vladimir Oltean2d44b092020-09-26 22:32:01 +03001888/* Configure and enable the CPU port module, which is a set of queues
1889 * accessible through register MMIO, frame DMA or Ethernet (in case
1890 * NPI mode is used).
Vladimir Oltean69df5782020-02-29 16:50:02 +02001891 */
Vladimir Oltean2d44b092020-09-26 22:32:01 +03001892static void ocelot_cpu_port_init(struct ocelot *ocelot)
Vladimir Oltean21468192019-11-09 15:03:00 +02001893{
Vladimir Oltean69df5782020-02-29 16:50:02 +02001894 int cpu = ocelot->num_phys_ports;
1895
1896 /* The unicast destination PGID for the CPU port module is unused */
Vladimir Oltean21468192019-11-09 15:03:00 +02001897 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
Vladimir Oltean69df5782020-02-29 16:50:02 +02001898 /* Instead set up a multicast destination PGID for traffic copied to
1899 * the CPU. Whitelisted MAC addresses like the port netdevice MAC
1900 * addresses will be copied to the CPU via this PGID.
1901 */
Vladimir Oltean21468192019-11-09 15:03:00 +02001902 ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
1903 ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
1904 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
1905 ANA_PORT_PORT_CFG, cpu);
1906
Vladimir Oltean69df5782020-02-29 16:50:02 +02001907 /* Enable CPU port module */
Vladimir Oltean886e1382020-07-13 19:57:03 +03001908 ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
Vladimir Oltean69df5782020-02-29 16:50:02 +02001909 /* CPU port Injection/Extraction configuration */
Vladimir Oltean886e1382020-07-13 19:57:03 +03001910 ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
Vladimir Olteancacea622021-01-29 03:00:03 +02001911 OCELOT_TAG_PREFIX_NONE);
Vladimir Oltean886e1382020-07-13 19:57:03 +03001912 ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
Vladimir Olteancacea622021-01-29 03:00:03 +02001913 OCELOT_TAG_PREFIX_NONE);
Vladimir Oltean21468192019-11-09 15:03:00 +02001914
1915 /* Configure the CPU port to be VLAN aware */
1916 ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
1917 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
1918 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
1919 ANA_PORT_VLAN_CFG, cpu);
Vladimir Oltean21468192019-11-09 15:03:00 +02001920}
Vladimir Oltean21468192019-11-09 15:03:00 +02001921
Vladimir Olteanf6fe01d2021-01-15 04:11:11 +02001922static void ocelot_detect_features(struct ocelot *ocelot)
1923{
1924 int mmgt, eq_ctrl;
1925
1926 /* For Ocelot, Felix, Seville, Serval etc, SYS:MMGT:MMGT:FREECNT holds
1927 * the number of 240-byte free memory words (aka 4-cell chunks) and not
1928 * 192 bytes as the documentation incorrectly says.
1929 */
1930 mmgt = ocelot_read(ocelot, SYS_MMGT);
1931 ocelot->packet_buffer_size = 240 * SYS_MMGT_FREECNT(mmgt);
1932
1933 eq_ctrl = ocelot_read(ocelot, QSYS_EQ_CTRL);
1934 ocelot->num_frame_refs = QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(eq_ctrl);
Vladimir Olteanf6fe01d2021-01-15 04:11:11 +02001935}
1936
Alexandre Bellonia556c762018-05-14 22:04:57 +02001937int ocelot_init(struct ocelot *ocelot)
1938{
Alexandre Bellonia556c762018-05-14 22:04:57 +02001939 char queue_name[32];
Vladimir Oltean21468192019-11-09 15:03:00 +02001940 int i, ret;
1941 u32 port;
Alexandre Bellonia556c762018-05-14 22:04:57 +02001942
Vladimir Oltean3a77b592019-11-14 17:03:26 +02001943 if (ocelot->ops->reset) {
1944 ret = ocelot->ops->reset(ocelot);
1945 if (ret) {
1946 dev_err(ocelot->dev, "Switch reset failed\n");
1947 return ret;
1948 }
1949 }
1950
Alexandre Bellonia556c762018-05-14 22:04:57 +02001951 ocelot->stats = devm_kcalloc(ocelot->dev,
1952 ocelot->num_phys_ports * ocelot->num_stats,
1953 sizeof(u64), GFP_KERNEL);
1954 if (!ocelot->stats)
1955 return -ENOMEM;
1956
1957 mutex_init(&ocelot->stats_lock);
Antoine Tenart4e3b0462019-08-12 16:45:37 +02001958 mutex_init(&ocelot->ptp_lock);
1959 spin_lock_init(&ocelot->ptp_clock_lock);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001960 snprintf(queue_name, sizeof(queue_name), "%s-stats",
1961 dev_name(ocelot->dev));
1962 ocelot->stats_queue = create_singlethread_workqueue(queue_name);
1963 if (!ocelot->stats_queue)
1964 return -ENOMEM;
1965
Vladimir Olteanca0b2722020-12-12 21:16:12 +02001966 ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0);
1967 if (!ocelot->owq) {
1968 destroy_workqueue(ocelot->stats_queue);
1969 return -ENOMEM;
1970 }
1971
Claudiu Manoil2b120dd2019-11-09 15:02:58 +02001972 INIT_LIST_HEAD(&ocelot->multicast);
Vladimir Olteane5d1f892020-10-29 04:27:38 +02001973 INIT_LIST_HEAD(&ocelot->pgids);
Vladimir Olteanf6fe01d2021-01-15 04:11:11 +02001974 ocelot_detect_features(ocelot);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001975 ocelot_mact_init(ocelot);
1976 ocelot_vlan_init(ocelot);
Vladimir Olteanaae4e502020-06-20 18:43:46 +03001977 ocelot_vcap_init(ocelot);
Vladimir Oltean2d44b092020-09-26 22:32:01 +03001978 ocelot_cpu_port_init(ocelot);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001979
1980 for (port = 0; port < ocelot->num_phys_ports; port++) {
1981 /* Clear all counters (5 groups) */
1982 ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port) |
1983 SYS_STAT_CFG_STAT_CLEAR_SHOT(0x7f),
1984 SYS_STAT_CFG);
1985 }
1986
1987 /* Only use S-Tag */
1988 ocelot_write(ocelot, ETH_P_8021AD, SYS_VLAN_ETYPE_CFG);
1989
1990 /* Aggregation mode */
1991 ocelot_write(ocelot, ANA_AGGR_CFG_AC_SMAC_ENA |
1992 ANA_AGGR_CFG_AC_DMAC_ENA |
1993 ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA |
Vladimir Olteanf79c20c2021-02-06 00:02:13 +02001994 ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA |
1995 ANA_AGGR_CFG_AC_IP6_FLOW_LBL_ENA |
1996 ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA,
1997 ANA_AGGR_CFG);
Alexandre Bellonia556c762018-05-14 22:04:57 +02001998
1999 /* Set MAC age time to default value. The entry is aged after
2000 * 2*AGE_PERIOD
2001 */
2002 ocelot_write(ocelot,
2003 ANA_AUTOAGE_AGE_PERIOD(BR_DEFAULT_AGEING_TIME / 2 / HZ),
2004 ANA_AUTOAGE);
2005
2006 /* Disable learning for frames discarded by VLAN ingress filtering */
2007 regmap_field_write(ocelot->regfields[ANA_ADVLEARN_VLAN_CHK], 1);
2008
2009 /* Setup frame ageing - fixed value "2 sec" - in 6.5 us units */
2010 ocelot_write(ocelot, SYS_FRM_AGING_AGE_TX_ENA |
2011 SYS_FRM_AGING_MAX_AGE(307692), SYS_FRM_AGING);
2012
2013 /* Setup flooding PGIDs */
Vladimir Olteanedd24102020-12-04 19:54:16 +02002014 for (i = 0; i < ocelot->num_flooding_pgids; i++)
2015 ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) |
Vladimir Olteanb360d942021-02-12 17:15:58 +02002016 ANA_FLOODING_FLD_BROADCAST(PGID_BC) |
Vladimir Olteanedd24102020-12-04 19:54:16 +02002017 ANA_FLOODING_FLD_UNICAST(PGID_UC),
2018 ANA_FLOODING, i);
Alexandre Bellonia556c762018-05-14 22:04:57 +02002019 ocelot_write(ocelot, ANA_FLOODING_IPMC_FLD_MC6_DATA(PGID_MCIPV6) |
2020 ANA_FLOODING_IPMC_FLD_MC6_CTRL(PGID_MC) |
2021 ANA_FLOODING_IPMC_FLD_MC4_DATA(PGID_MCIPV4) |
2022 ANA_FLOODING_IPMC_FLD_MC4_CTRL(PGID_MC),
2023 ANA_FLOODING_IPMC);
2024
2025 for (port = 0; port < ocelot->num_phys_ports; port++) {
2026 /* Transmit the frame to the local port. */
2027 ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, port);
2028 /* Do not forward BPDU frames to the front ports. */
2029 ocelot_write_gix(ocelot,
2030 ANA_PORT_CPU_FWD_BPDU_CFG_BPDU_REDIR_ENA(0xffff),
2031 ANA_PORT_CPU_FWD_BPDU_CFG,
2032 port);
2033 /* Ensure bridging is disabled */
2034 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_SRC + port);
2035 }
2036
Vladimir Oltean96b029b2020-06-21 14:46:02 +03002037 for_each_nonreserved_multicast_dest_pgid(ocelot, i) {
Alexandre Bellonia556c762018-05-14 22:04:57 +02002038 u32 val = ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports - 1, 0));
2039
2040 ocelot_write_rix(ocelot, val, ANA_PGID_PGID, i);
2041 }
Horatiu Vulturebb1bb42021-03-16 21:10:17 +01002042
2043 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_BLACKHOLE);
2044
Vladimir Olteanb360d942021-02-12 17:15:58 +02002045 /* Allow broadcast and unknown L2 multicast to the CPU. */
2046 ocelot_rmw_rix(ocelot, ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)),
2047 ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)),
2048 ANA_PGID_PGID, PGID_MC);
2049 ocelot_rmw_rix(ocelot, ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)),
2050 ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)),
2051 ANA_PGID_PGID, PGID_BC);
Alexandre Bellonia556c762018-05-14 22:04:57 +02002052 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV4);
2053 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV6);
2054
Alexandre Bellonia556c762018-05-14 22:04:57 +02002055 /* Allow manual injection via DEVCPU_QS registers, and byte swap these
2056 * registers endianness.
2057 */
2058 ocelot_write_rix(ocelot, QS_INJ_GRP_CFG_BYTE_SWAP |
2059 QS_INJ_GRP_CFG_MODE(1), QS_INJ_GRP_CFG, 0);
2060 ocelot_write_rix(ocelot, QS_XTR_GRP_CFG_BYTE_SWAP |
2061 QS_XTR_GRP_CFG_MODE(1), QS_XTR_GRP_CFG, 0);
2062 ocelot_write(ocelot, ANA_CPUQ_CFG_CPUQ_MIRROR(2) |
2063 ANA_CPUQ_CFG_CPUQ_LRN(2) |
2064 ANA_CPUQ_CFG_CPUQ_MAC_COPY(2) |
2065 ANA_CPUQ_CFG_CPUQ_SRC_COPY(2) |
2066 ANA_CPUQ_CFG_CPUQ_LOCKED_PORTMOVE(2) |
2067 ANA_CPUQ_CFG_CPUQ_ALLBRIDGE(6) |
2068 ANA_CPUQ_CFG_CPUQ_IPMC_CTRL(6) |
2069 ANA_CPUQ_CFG_CPUQ_IGMP(6) |
2070 ANA_CPUQ_CFG_CPUQ_MLD(6), ANA_CPUQ_CFG);
2071 for (i = 0; i < 16; i++)
2072 ocelot_write_rix(ocelot, ANA_CPUQ_8021_CFG_CPUQ_GARP_VAL(6) |
2073 ANA_CPUQ_8021_CFG_CPUQ_BPDU_VAL(6),
2074 ANA_CPUQ_8021_CFG, i);
2075
Claudiu Manoil1e1caa92019-04-16 17:51:59 +03002076 INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
Alexandre Bellonia556c762018-05-14 22:04:57 +02002077 queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
2078 OCELOT_STATS_CHECK_DELAY);
Antoine Tenart4e3b0462019-08-12 16:45:37 +02002079
Alexandre Bellonia556c762018-05-14 22:04:57 +02002080 return 0;
2081}
2082EXPORT_SYMBOL(ocelot_init);
2083
2084void ocelot_deinit(struct ocelot *ocelot)
2085{
Claudiu Manoilc5d13962019-07-25 16:33:18 +03002086 cancel_delayed_work(&ocelot->stats_work);
Alexandre Bellonia556c762018-05-14 22:04:57 +02002087 destroy_workqueue(ocelot->stats_queue);
Vladimir Olteanca0b2722020-12-12 21:16:12 +02002088 destroy_workqueue(ocelot->owq);
Alexandre Bellonia556c762018-05-14 22:04:57 +02002089 mutex_destroy(&ocelot->stats_lock);
Alexandre Bellonia556c762018-05-14 22:04:57 +02002090}
2091EXPORT_SYMBOL(ocelot_deinit);
2092
Vladimir Olteane5fb5122020-09-18 04:07:30 +03002093void ocelot_deinit_port(struct ocelot *ocelot, int port)
2094{
2095 struct ocelot_port *ocelot_port = ocelot->ports[port];
2096
2097 skb_queue_purge(&ocelot_port->tx_skbs);
2098}
2099EXPORT_SYMBOL(ocelot_deinit_port);
2100
Alexandre Bellonia556c762018-05-14 22:04:57 +02002101MODULE_LICENSE("Dual MIT/GPL");