ocelot.c (a4721ced760684d1776bf31f7925aa41bb3f4846) ocelot.c (87b0f983f66f23762921129fd35966eddc3f2dae)
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/etherdevice.h>
8#include <linux/ethtool.h>

--- 169 unchanged lines hidden (view full) ---

178 val = ocelot_read(ocelot, ANA_VLANMASK);
179 if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
180 val |= BIT(port);
181 else
182 val &= ~BIT(port);
183 ocelot_write(ocelot, val, ANA_VLANMASK);
184}
185
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/etherdevice.h>
8#include <linux/ethtool.h>

--- 169 unchanged lines hidden (view full) ---

178 val = ocelot_read(ocelot, ANA_VLANMASK);
179 if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
180 val |= BIT(port);
181 else
182 val &= ~BIT(port);
183 ocelot_write(ocelot, val, ANA_VLANMASK);
184}
185
186void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
187 bool vlan_aware)
186static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
187 u16 vid)
188{
189 struct ocelot_port *ocelot_port = ocelot->ports[port];
188{
189 struct ocelot_port *ocelot_port = ocelot->ports[port];
190 u32 val;
190 u32 val = 0;
191
191
192 if (vlan_aware)
193 val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
194 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
195 else
196 val = 0;
197 ocelot_rmw_gix(ocelot, val,
198 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
199 ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
200 ANA_PORT_VLAN_CFG, port);
192 if (ocelot_port->vid != vid) {
193 /* Always permit deleting the native VLAN (vid = 0) */
194 if (ocelot_port->vid && vid) {
195 dev_err(ocelot->dev,
196 "Port already has a native VLAN: %d\n",
197 ocelot_port->vid);
198 return -EBUSY;
199 }
200 ocelot_port->vid = vid;
201 }
201
202
202 if (vlan_aware && !ocelot_port->vid)
203 ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid),
204 REW_PORT_VLAN_CFG_PORT_VID_M,
205 REW_PORT_VLAN_CFG, port);
206
207 if (ocelot_port->vlan_aware && !ocelot_port->vid)
203 /* If port is vlan-aware and tagged, drop untagged and priority
204 * tagged frames.
205 */
206 val = ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
207 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
208 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
208 /* If port is vlan-aware and tagged, drop untagged and priority
209 * tagged frames.
210 */
211 val = ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
212 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
213 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
209 else
210 val = 0;
211 ocelot_rmw_gix(ocelot, val,
212 ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
213 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
214 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
215 ANA_PORT_DROP_CFG, port);
216
214 ocelot_rmw_gix(ocelot, val,
215 ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
216 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
217 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
218 ANA_PORT_DROP_CFG, port);
219
217 if (vlan_aware) {
220 if (ocelot_port->vlan_aware) {
218 if (ocelot_port->vid)
219 /* Tag all frames except when VID == DEFAULT_VLAN */
221 if (ocelot_port->vid)
222 /* Tag all frames except when VID == DEFAULT_VLAN */
220 val |= REW_TAG_CFG_TAG_CFG(1);
223 val = REW_TAG_CFG_TAG_CFG(1);
221 else
222 /* Tag all frames */
224 else
225 /* Tag all frames */
223 val |= REW_TAG_CFG_TAG_CFG(3);
226 val = REW_TAG_CFG_TAG_CFG(3);
224 } else {
225 /* Port tagging disabled. */
226 val = REW_TAG_CFG_TAG_CFG(0);
227 }
228 ocelot_rmw_gix(ocelot, val,
229 REW_TAG_CFG_TAG_CFG_M,
230 REW_TAG_CFG, port);
227 } else {
228 /* Port tagging disabled. */
229 val = REW_TAG_CFG_TAG_CFG(0);
230 }
231 ocelot_rmw_gix(ocelot, val,
232 REW_TAG_CFG_TAG_CFG_M,
233 REW_TAG_CFG, port);
234
235 return 0;
231}
236}
232EXPORT_SYMBOL(ocelot_port_vlan_filtering);
233
237
234static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
235 u16 vid)
238void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
239 bool vlan_aware)
236{
237 struct ocelot_port *ocelot_port = ocelot->ports[port];
240{
241 struct ocelot_port *ocelot_port = ocelot->ports[port];
242 u32 val;
238
243
239 if (ocelot_port->vid != vid) {
240 /* Always permit deleting the native VLAN (vid = 0) */
241 if (ocelot_port->vid && vid) {
242 dev_err(ocelot->dev,
243 "Port already has a native VLAN: %d\n",
244 ocelot_port->vid);
245 return -EBUSY;
246 }
247 ocelot_port->vid = vid;
248 }
244 ocelot_port->vlan_aware = vlan_aware;
249
245
250 ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid),
251 REW_PORT_VLAN_CFG_PORT_VID_M,
252 REW_PORT_VLAN_CFG, port);
246 if (vlan_aware)
247 val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
248 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
249 else
250 val = 0;
251 ocelot_rmw_gix(ocelot, val,
252 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
253 ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
254 ANA_PORT_VLAN_CFG, port);
253
255
254 return 0;
256 ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid);
255}
257}
258EXPORT_SYMBOL(ocelot_port_vlan_filtering);
256
257/* Default vlan to clasify for untagged frames (may be zero) */
258static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid)
259{
260 struct ocelot_port *ocelot_port = ocelot->ports[port];
261
262 ocelot_rmw_gix(ocelot,
263 ANA_PORT_VLAN_CFG_VLAN_VID(pvid),

--- 604 unchanged lines hidden (view full) ---

868 ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) +
869 ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX);
870 stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) +
871 ocelot_read(ocelot, SYS_COUNT_TX_AGING);
872 stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION);
873}
874
875int ocelot_fdb_add(struct ocelot *ocelot, int port,
259
260/* Default vlan to clasify for untagged frames (may be zero) */
261static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid)
262{
263 struct ocelot_port *ocelot_port = ocelot->ports[port];
264
265 ocelot_rmw_gix(ocelot,
266 ANA_PORT_VLAN_CFG_VLAN_VID(pvid),

--- 604 unchanged lines hidden (view full) ---

871 ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) +
872 ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX);
873 stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) +
874 ocelot_read(ocelot, SYS_COUNT_TX_AGING);
875 stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION);
876}
877
878int ocelot_fdb_add(struct ocelot *ocelot, int port,
876 const unsigned char *addr, u16 vid, bool vlan_aware)
879 const unsigned char *addr, u16 vid)
877{
878 struct ocelot_port *ocelot_port = ocelot->ports[port];
879
880 if (!vid) {
880{
881 struct ocelot_port *ocelot_port = ocelot->ports[port];
882
883 if (!vid) {
881 if (!vlan_aware)
884 if (!ocelot_port->vlan_aware)
882 /* If the bridge is not VLAN aware and no VID was
883 * provided, set it to pvid to ensure the MAC entry
884 * matches incoming untagged packets
885 */
886 vid = ocelot_port->pvid;
887 else
888 /* If the bridge is VLAN aware a VID must be provided as
889 * otherwise the learnt entry wouldn't match any frame.

--- 10 unchanged lines hidden (view full) ---

900 const unsigned char *addr,
901 u16 vid, u16 flags,
902 struct netlink_ext_ack *extack)
903{
904 struct ocelot_port_private *priv = netdev_priv(dev);
905 struct ocelot *ocelot = priv->port.ocelot;
906 int port = priv->chip_port;
907
885 /* If the bridge is not VLAN aware and no VID was
886 * provided, set it to pvid to ensure the MAC entry
887 * matches incoming untagged packets
888 */
889 vid = ocelot_port->pvid;
890 else
891 /* If the bridge is VLAN aware a VID must be provided as
892 * otherwise the learnt entry wouldn't match any frame.

--- 10 unchanged lines hidden (view full) ---

903 const unsigned char *addr,
904 u16 vid, u16 flags,
905 struct netlink_ext_ack *extack)
906{
907 struct ocelot_port_private *priv = netdev_priv(dev);
908 struct ocelot *ocelot = priv->port.ocelot;
909 int port = priv->chip_port;
910
908 return ocelot_fdb_add(ocelot, port, addr, vid, priv->vlan_aware);
911 return ocelot_fdb_add(ocelot, port, addr, vid);
909}
910
911int ocelot_fdb_del(struct ocelot *ocelot, int port,
912 const unsigned char *addr, u16 vid)
913{
914 return ocelot_mact_forget(ocelot, addr, vid);
915}
916EXPORT_SYMBOL(ocelot_fdb_del);

--- 574 unchanged lines hidden (view full) ---

1491 case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
1492 ocelot_port_attr_stp_state_set(ocelot, port, trans,
1493 attr->u.stp_state);
1494 break;
1495 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
1496 ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);
1497 break;
1498 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
912}
913
914int ocelot_fdb_del(struct ocelot *ocelot, int port,
915 const unsigned char *addr, u16 vid)
916{
917 return ocelot_mact_forget(ocelot, addr, vid);
918}
919EXPORT_SYMBOL(ocelot_fdb_del);

--- 574 unchanged lines hidden (view full) ---

1494 case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
1495 ocelot_port_attr_stp_state_set(ocelot, port, trans,
1496 attr->u.stp_state);
1497 break;
1498 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
1499 ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);
1500 break;
1501 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
1499 priv->vlan_aware = attr->u.vlan_filtering;
1500 ocelot_port_vlan_filtering(ocelot, port, priv->vlan_aware);
1502 ocelot_port_vlan_filtering(ocelot, port,
1503 attr->u.vlan_filtering);
1501 break;
1502 case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
1503 ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
1504 break;
1505 default:
1506 err = -EOPNOTSUPP;
1507 break;
1508 }

--- 354 unchanged lines hidden (view full) ---

1863 case NETDEV_CHANGEUPPER:
1864 if (netif_is_bridge_master(info->upper_dev)) {
1865 if (info->linking) {
1866 err = ocelot_port_bridge_join(ocelot, port,
1867 info->upper_dev);
1868 } else {
1869 err = ocelot_port_bridge_leave(ocelot, port,
1870 info->upper_dev);
1504 break;
1505 case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
1506 ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
1507 break;
1508 default:
1509 err = -EOPNOTSUPP;
1510 break;
1511 }

--- 354 unchanged lines hidden (view full) ---

1866 case NETDEV_CHANGEUPPER:
1867 if (netif_is_bridge_master(info->upper_dev)) {
1868 if (info->linking) {
1869 err = ocelot_port_bridge_join(ocelot, port,
1870 info->upper_dev);
1871 } else {
1872 err = ocelot_port_bridge_leave(ocelot, port,
1873 info->upper_dev);
1871 priv->vlan_aware = false;
1872 }
1873 }
1874 if (netif_is_lag_master(info->upper_dev)) {
1875 if (info->linking)
1876 err = ocelot_port_lag_join(ocelot, port,
1877 info->upper_dev);
1878 else
1879 ocelot_port_lag_leave(ocelot, port,

--- 683 unchanged lines hidden ---
1874 }
1875 }
1876 if (netif_is_lag_master(info->upper_dev)) {
1877 if (info->linking)
1878 err = ocelot_port_lag_join(ocelot, port,
1879 info->upper_dev);
1880 else
1881 ocelot_port_lag_leave(ocelot, port,

--- 683 unchanged lines hidden ---