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 --- |