1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include "lan966x_main.h" 4 5 #define VLANACCESS_CMD_IDLE 0 6 #define VLANACCESS_CMD_READ 1 7 #define VLANACCESS_CMD_WRITE 2 8 #define VLANACCESS_CMD_INIT 3 9 10 static int lan966x_vlan_get_status(struct lan966x *lan966x) 11 { 12 return lan_rd(lan966x, ANA_VLANACCESS); 13 } 14 15 static int lan966x_vlan_wait_for_completion(struct lan966x *lan966x) 16 { 17 u32 val; 18 19 return readx_poll_timeout(lan966x_vlan_get_status, 20 lan966x, val, 21 (val & ANA_VLANACCESS_VLAN_TBL_CMD) == 22 VLANACCESS_CMD_IDLE, 23 TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US); 24 } 25 26 static void lan966x_vlan_set_mask(struct lan966x *lan966x, u16 vid) 27 { 28 u16 mask = lan966x->vlan_mask[vid]; 29 bool cpu_dis; 30 31 cpu_dis = !(mask & BIT(CPU_PORT)); 32 33 /* Set flags and the VID to configure */ 34 lan_rmw(ANA_VLANTIDX_VLAN_PGID_CPU_DIS_SET(cpu_dis) | 35 ANA_VLANTIDX_V_INDEX_SET(vid), 36 ANA_VLANTIDX_VLAN_PGID_CPU_DIS | 37 ANA_VLANTIDX_V_INDEX, 38 lan966x, ANA_VLANTIDX); 39 40 /* Set the vlan port members mask */ 41 lan_rmw(ANA_VLAN_PORT_MASK_VLAN_PORT_MASK_SET(mask), 42 ANA_VLAN_PORT_MASK_VLAN_PORT_MASK, 43 lan966x, ANA_VLAN_PORT_MASK); 44 45 /* Issue a write command */ 46 lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_WRITE), 47 ANA_VLANACCESS_VLAN_TBL_CMD, 48 lan966x, ANA_VLANACCESS); 49 50 if (lan966x_vlan_wait_for_completion(lan966x)) 51 dev_err(lan966x->dev, "Vlan set mask failed\n"); 52 } 53 54 static void lan966x_vlan_port_add_vlan_mask(struct lan966x_port *port, u16 vid) 55 { 56 struct lan966x *lan966x = port->lan966x; 57 u8 p = port->chip_port; 58 59 lan966x->vlan_mask[vid] |= BIT(p); 60 lan966x_vlan_set_mask(lan966x, vid); 61 } 62 63 static void lan966x_vlan_port_del_vlan_mask(struct lan966x_port *port, u16 vid) 64 { 65 struct lan966x *lan966x = port->lan966x; 66 u8 p = port->chip_port; 67 68 lan966x->vlan_mask[vid] &= ~BIT(p); 69 lan966x_vlan_set_mask(lan966x, vid); 70 } 71 72 static bool lan966x_vlan_port_any_vlan_mask(struct lan966x *lan966x, u16 vid) 73 { 74 return !!(lan966x->vlan_mask[vid] & ~BIT(CPU_PORT)); 75 } 76 77 static void lan966x_vlan_cpu_add_vlan_mask(struct lan966x *lan966x, u16 vid) 78 { 79 lan966x->vlan_mask[vid] |= BIT(CPU_PORT); 80 lan966x_vlan_set_mask(lan966x, vid); 81 } 82 83 static void lan966x_vlan_cpu_del_vlan_mask(struct lan966x *lan966x, u16 vid) 84 { 85 lan966x->vlan_mask[vid] &= ~BIT(CPU_PORT); 86 lan966x_vlan_set_mask(lan966x, vid); 87 } 88 89 static void lan966x_vlan_cpu_add_cpu_vlan_mask(struct lan966x *lan966x, u16 vid) 90 { 91 __set_bit(vid, lan966x->cpu_vlan_mask); 92 } 93 94 static void lan966x_vlan_cpu_del_cpu_vlan_mask(struct lan966x *lan966x, u16 vid) 95 { 96 __clear_bit(vid, lan966x->cpu_vlan_mask); 97 } 98 99 bool lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x *lan966x, u16 vid) 100 { 101 return test_bit(vid, lan966x->cpu_vlan_mask); 102 } 103 104 static u16 lan966x_vlan_port_get_pvid(struct lan966x_port *port) 105 { 106 struct lan966x *lan966x = port->lan966x; 107 108 if (!(lan966x->bridge_mask & BIT(port->chip_port))) 109 return HOST_PVID; 110 111 return port->vlan_aware ? port->pvid : UNAWARE_PVID; 112 } 113 114 int lan966x_vlan_port_set_vid(struct lan966x_port *port, u16 vid, 115 bool pvid, bool untagged) 116 { 117 struct lan966x *lan966x = port->lan966x; 118 119 /* Egress vlan classification */ 120 if (untagged && port->vid != vid) { 121 if (port->vid) { 122 dev_err(lan966x->dev, 123 "Port already has a native VLAN: %d\n", 124 port->vid); 125 return -EBUSY; 126 } 127 port->vid = vid; 128 } 129 130 /* Default ingress vlan classification */ 131 if (pvid) 132 port->pvid = vid; 133 134 return 0; 135 } 136 137 static void lan966x_vlan_port_remove_vid(struct lan966x_port *port, u16 vid) 138 { 139 if (port->pvid == vid) 140 port->pvid = 0; 141 142 if (port->vid == vid) 143 port->vid = 0; 144 } 145 146 void lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port, 147 bool vlan_aware) 148 { 149 port->vlan_aware = vlan_aware; 150 } 151 152 void lan966x_vlan_port_apply(struct lan966x_port *port) 153 { 154 struct lan966x *lan966x = port->lan966x; 155 u16 pvid; 156 u32 val; 157 158 pvid = lan966x_vlan_port_get_pvid(port); 159 160 /* Ingress clasification (ANA_PORT_VLAN_CFG) */ 161 /* Default vlan to classify for untagged frames (may be zero) */ 162 val = ANA_VLAN_CFG_VLAN_VID_SET(pvid); 163 if (port->vlan_aware) 164 val |= ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) | 165 ANA_VLAN_CFG_VLAN_POP_CNT_SET(1); 166 167 lan_rmw(val, 168 ANA_VLAN_CFG_VLAN_VID | ANA_VLAN_CFG_VLAN_AWARE_ENA | 169 ANA_VLAN_CFG_VLAN_POP_CNT, 170 lan966x, ANA_VLAN_CFG(port->chip_port)); 171 172 lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) | 173 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware), 174 DEV_MAC_TAGS_CFG_VLAN_AWR_ENA | 175 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, 176 lan966x, DEV_MAC_TAGS_CFG(port->chip_port)); 177 178 /* Drop frames with multicast source address */ 179 val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1); 180 if (port->vlan_aware && !pvid) 181 /* If port is vlan-aware and tagged, drop untagged and priority 182 * tagged frames. 183 */ 184 val |= ANA_DROP_CFG_DROP_UNTAGGED_ENA_SET(1) | 185 ANA_DROP_CFG_DROP_PRIO_S_TAGGED_ENA_SET(1) | 186 ANA_DROP_CFG_DROP_PRIO_C_TAGGED_ENA_SET(1); 187 188 lan_wr(val, lan966x, ANA_DROP_CFG(port->chip_port)); 189 190 /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */ 191 val = REW_TAG_CFG_TAG_TPID_CFG_SET(0); 192 if (port->vlan_aware) { 193 if (port->vid) 194 /* Tag all frames except when VID == DEFAULT_VLAN */ 195 val |= REW_TAG_CFG_TAG_CFG_SET(1); 196 else 197 val |= REW_TAG_CFG_TAG_CFG_SET(3); 198 } 199 200 /* Update only some bits in the register */ 201 lan_rmw(val, 202 REW_TAG_CFG_TAG_TPID_CFG | REW_TAG_CFG_TAG_CFG, 203 lan966x, REW_TAG_CFG(port->chip_port)); 204 205 /* Set default VLAN and tag type to 8021Q */ 206 lan_rmw(REW_PORT_VLAN_CFG_PORT_TPID_SET(ETH_P_8021Q) | 207 REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid), 208 REW_PORT_VLAN_CFG_PORT_TPID | 209 REW_PORT_VLAN_CFG_PORT_VID, 210 lan966x, REW_PORT_VLAN_CFG(port->chip_port)); 211 } 212 213 void lan966x_vlan_port_add_vlan(struct lan966x_port *port, 214 u16 vid, 215 bool pvid, 216 bool untagged) 217 { 218 struct lan966x *lan966x = port->lan966x; 219 220 /* If the CPU(br) is already part of the vlan then add the fdb 221 * entries in MAC table to copy the frames to the CPU(br). 222 * If the CPU(br) is not part of the vlan then it would 223 * just drop the frames. 224 */ 225 if (lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x, vid)) { 226 lan966x_vlan_cpu_add_vlan_mask(lan966x, vid); 227 lan966x_fdb_write_entries(lan966x, vid); 228 lan966x_mdb_write_entries(lan966x, vid); 229 } 230 231 lan966x_vlan_port_set_vid(port, vid, pvid, untagged); 232 lan966x_vlan_port_add_vlan_mask(port, vid); 233 lan966x_vlan_port_apply(port); 234 } 235 236 void lan966x_vlan_port_del_vlan(struct lan966x_port *port, u16 vid) 237 { 238 struct lan966x *lan966x = port->lan966x; 239 240 lan966x_vlan_port_remove_vid(port, vid); 241 lan966x_vlan_port_del_vlan_mask(port, vid); 242 lan966x_vlan_port_apply(port); 243 244 /* In case there are no other ports in vlan then remove the CPU from 245 * that vlan but still keep it in the mask because it may be needed 246 * again then another port gets added in that vlan 247 */ 248 if (!lan966x_vlan_port_any_vlan_mask(lan966x, vid)) { 249 lan966x_vlan_cpu_del_vlan_mask(lan966x, vid); 250 lan966x_fdb_erase_entries(lan966x, vid); 251 lan966x_mdb_erase_entries(lan966x, vid); 252 } 253 } 254 255 void lan966x_vlan_cpu_add_vlan(struct lan966x *lan966x, u16 vid) 256 { 257 /* Add an entry in the MAC table for the CPU 258 * Add the CPU part of the vlan only if there is another port in that 259 * vlan otherwise all the broadcast frames in that vlan will go to CPU 260 * even if none of the ports are in the vlan and then the CPU will just 261 * need to discard these frames. It is required to store this 262 * information so when a front port is added then it would add also the 263 * CPU port. 264 */ 265 if (lan966x_vlan_port_any_vlan_mask(lan966x, vid)) { 266 lan966x_vlan_cpu_add_vlan_mask(lan966x, vid); 267 lan966x_mdb_write_entries(lan966x, vid); 268 } 269 270 lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, vid); 271 lan966x_fdb_write_entries(lan966x, vid); 272 } 273 274 void lan966x_vlan_cpu_del_vlan(struct lan966x *lan966x, u16 vid) 275 { 276 /* Remove the CPU part of the vlan */ 277 lan966x_vlan_cpu_del_cpu_vlan_mask(lan966x, vid); 278 lan966x_vlan_cpu_del_vlan_mask(lan966x, vid); 279 lan966x_fdb_erase_entries(lan966x, vid); 280 lan966x_mdb_erase_entries(lan966x, vid); 281 } 282 283 void lan966x_vlan_init(struct lan966x *lan966x) 284 { 285 u16 port, vid; 286 287 /* Clear VLAN table, by default all ports are members of all VLANS */ 288 lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_INIT), 289 ANA_VLANACCESS_VLAN_TBL_CMD, 290 lan966x, ANA_VLANACCESS); 291 lan966x_vlan_wait_for_completion(lan966x); 292 293 for (vid = 1; vid < VLAN_N_VID; vid++) { 294 lan966x->vlan_mask[vid] = 0; 295 lan966x_vlan_set_mask(lan966x, vid); 296 } 297 298 /* Set all the ports + cpu to be part of HOST_PVID and UNAWARE_PVID */ 299 lan966x->vlan_mask[HOST_PVID] = 300 GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT); 301 lan966x_vlan_set_mask(lan966x, HOST_PVID); 302 303 lan966x->vlan_mask[UNAWARE_PVID] = 304 GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT); 305 lan966x_vlan_set_mask(lan966x, UNAWARE_PVID); 306 307 lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, UNAWARE_PVID); 308 309 /* Configure the CPU port to be vlan aware */ 310 lan_wr(ANA_VLAN_CFG_VLAN_VID_SET(0) | 311 ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) | 312 ANA_VLAN_CFG_VLAN_POP_CNT_SET(1), 313 lan966x, ANA_VLAN_CFG(CPU_PORT)); 314 315 /* Set vlan ingress filter mask to all ports */ 316 lan_wr(GENMASK(lan966x->num_phys_ports, 0), 317 lan966x, ANA_VLANMASK); 318 319 for (port = 0; port < lan966x->num_phys_ports; port++) { 320 lan_wr(0, lan966x, REW_PORT_VLAN_CFG(port)); 321 lan_wr(0, lan966x, REW_TAG_CFG(port)); 322 } 323 } 324