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 /* When the interface is in host mode, the interface should not be vlan aware 153 * but it should insert all the tags that it gets from the network stack. 154 * The tags are not in the data of the frame but actually in the skb and the ifh 155 * is configured already to get this tag. So what we need to do is to update the 156 * rewriter to insert the vlan tag for all frames which have a vlan tag 157 * different than 0. 158 */ 159 void lan966x_vlan_port_rew_host(struct lan966x_port *port) 160 { 161 struct lan966x *lan966x = port->lan966x; 162 u32 val; 163 164 /* Tag all frames except when VID=0*/ 165 val = REW_TAG_CFG_TAG_CFG_SET(2); 166 167 /* Update only some bits in the register */ 168 lan_rmw(val, 169 REW_TAG_CFG_TAG_CFG, 170 lan966x, REW_TAG_CFG(port->chip_port)); 171 } 172 173 void lan966x_vlan_port_apply(struct lan966x_port *port) 174 { 175 struct lan966x *lan966x = port->lan966x; 176 u16 pvid; 177 u32 val; 178 179 pvid = lan966x_vlan_port_get_pvid(port); 180 181 /* Ingress classification (ANA_PORT_VLAN_CFG) */ 182 /* Default vlan to classify for untagged frames (may be zero) */ 183 val = ANA_VLAN_CFG_VLAN_VID_SET(pvid); 184 if (port->vlan_aware) 185 val |= ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) | 186 ANA_VLAN_CFG_VLAN_POP_CNT_SET(1); 187 188 lan_rmw(val, 189 ANA_VLAN_CFG_VLAN_VID | ANA_VLAN_CFG_VLAN_AWARE_ENA | 190 ANA_VLAN_CFG_VLAN_POP_CNT, 191 lan966x, ANA_VLAN_CFG(port->chip_port)); 192 193 lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) | 194 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware), 195 DEV_MAC_TAGS_CFG_VLAN_AWR_ENA | 196 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, 197 lan966x, DEV_MAC_TAGS_CFG(port->chip_port)); 198 199 /* Drop frames with multicast source address */ 200 val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1); 201 if (port->vlan_aware && !pvid) 202 /* If port is vlan-aware and tagged, drop untagged and priority 203 * tagged frames. 204 */ 205 val |= ANA_DROP_CFG_DROP_UNTAGGED_ENA_SET(1) | 206 ANA_DROP_CFG_DROP_PRIO_S_TAGGED_ENA_SET(1) | 207 ANA_DROP_CFG_DROP_PRIO_C_TAGGED_ENA_SET(1); 208 209 lan_wr(val, lan966x, ANA_DROP_CFG(port->chip_port)); 210 211 /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */ 212 val = REW_TAG_CFG_TAG_TPID_CFG_SET(0); 213 if (port->vlan_aware) { 214 if (port->vid) 215 /* Tag all frames except when VID == DEFAULT_VLAN */ 216 val |= REW_TAG_CFG_TAG_CFG_SET(1); 217 else 218 val |= REW_TAG_CFG_TAG_CFG_SET(3); 219 } 220 221 /* Update only some bits in the register */ 222 lan_rmw(val, 223 REW_TAG_CFG_TAG_TPID_CFG | REW_TAG_CFG_TAG_CFG, 224 lan966x, REW_TAG_CFG(port->chip_port)); 225 226 /* Set default VLAN and tag type to 8021Q */ 227 lan_rmw(REW_PORT_VLAN_CFG_PORT_TPID_SET(ETH_P_8021Q) | 228 REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid), 229 REW_PORT_VLAN_CFG_PORT_TPID | 230 REW_PORT_VLAN_CFG_PORT_VID, 231 lan966x, REW_PORT_VLAN_CFG(port->chip_port)); 232 } 233 234 void lan966x_vlan_port_add_vlan(struct lan966x_port *port, 235 u16 vid, 236 bool pvid, 237 bool untagged) 238 { 239 struct lan966x *lan966x = port->lan966x; 240 241 /* If the CPU(br) is already part of the vlan then add the fdb 242 * entries in MAC table to copy the frames to the CPU(br). 243 * If the CPU(br) is not part of the vlan then it would 244 * just drop the frames. 245 */ 246 if (lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x, vid)) { 247 lan966x_vlan_cpu_add_vlan_mask(lan966x, vid); 248 lan966x_fdb_write_entries(lan966x, vid); 249 lan966x_mdb_write_entries(lan966x, vid); 250 } 251 252 lan966x_vlan_port_set_vid(port, vid, pvid, untagged); 253 lan966x_vlan_port_add_vlan_mask(port, vid); 254 lan966x_vlan_port_apply(port); 255 } 256 257 void lan966x_vlan_port_del_vlan(struct lan966x_port *port, u16 vid) 258 { 259 struct lan966x *lan966x = port->lan966x; 260 261 lan966x_vlan_port_remove_vid(port, vid); 262 lan966x_vlan_port_del_vlan_mask(port, vid); 263 lan966x_vlan_port_apply(port); 264 265 /* In case there are no other ports in vlan then remove the CPU from 266 * that vlan but still keep it in the mask because it may be needed 267 * again then another port gets added in that vlan 268 */ 269 if (!lan966x_vlan_port_any_vlan_mask(lan966x, vid)) { 270 lan966x_vlan_cpu_del_vlan_mask(lan966x, vid); 271 lan966x_fdb_erase_entries(lan966x, vid); 272 lan966x_mdb_erase_entries(lan966x, vid); 273 } 274 } 275 276 void lan966x_vlan_cpu_add_vlan(struct lan966x *lan966x, u16 vid) 277 { 278 /* Add an entry in the MAC table for the CPU 279 * Add the CPU part of the vlan only if there is another port in that 280 * vlan otherwise all the broadcast frames in that vlan will go to CPU 281 * even if none of the ports are in the vlan and then the CPU will just 282 * need to discard these frames. It is required to store this 283 * information so when a front port is added then it would add also the 284 * CPU port. 285 */ 286 if (lan966x_vlan_port_any_vlan_mask(lan966x, vid)) { 287 lan966x_vlan_cpu_add_vlan_mask(lan966x, vid); 288 lan966x_mdb_write_entries(lan966x, vid); 289 } 290 291 lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, vid); 292 lan966x_fdb_write_entries(lan966x, vid); 293 } 294 295 void lan966x_vlan_cpu_del_vlan(struct lan966x *lan966x, u16 vid) 296 { 297 /* Remove the CPU part of the vlan */ 298 lan966x_vlan_cpu_del_cpu_vlan_mask(lan966x, vid); 299 lan966x_vlan_cpu_del_vlan_mask(lan966x, vid); 300 lan966x_fdb_erase_entries(lan966x, vid); 301 lan966x_mdb_erase_entries(lan966x, vid); 302 } 303 304 void lan966x_vlan_init(struct lan966x *lan966x) 305 { 306 u16 port, vid; 307 308 /* Clear VLAN table, by default all ports are members of all VLANS */ 309 lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_INIT), 310 ANA_VLANACCESS_VLAN_TBL_CMD, 311 lan966x, ANA_VLANACCESS); 312 lan966x_vlan_wait_for_completion(lan966x); 313 314 for (vid = 1; vid < VLAN_N_VID; vid++) { 315 lan966x->vlan_mask[vid] = 0; 316 lan966x_vlan_set_mask(lan966x, vid); 317 } 318 319 /* Set all the ports + cpu to be part of HOST_PVID and UNAWARE_PVID */ 320 lan966x->vlan_mask[HOST_PVID] = 321 GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT); 322 lan966x_vlan_set_mask(lan966x, HOST_PVID); 323 324 lan966x->vlan_mask[UNAWARE_PVID] = 325 GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT); 326 lan966x_vlan_set_mask(lan966x, UNAWARE_PVID); 327 328 lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, UNAWARE_PVID); 329 330 /* Configure the CPU port to be vlan aware */ 331 lan_wr(ANA_VLAN_CFG_VLAN_VID_SET(0) | 332 ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) | 333 ANA_VLAN_CFG_VLAN_POP_CNT_SET(1), 334 lan966x, ANA_VLAN_CFG(CPU_PORT)); 335 336 /* Set vlan ingress filter mask to all ports */ 337 lan_wr(GENMASK(lan966x->num_phys_ports, 0), 338 lan966x, ANA_VLANMASK); 339 340 for (port = 0; port < lan966x->num_phys_ports; port++) { 341 lan_wr(0, lan966x, REW_PORT_VLAN_CFG(port)); 342 lan_wr(0, lan966x, REW_TAG_CFG(port)); 343 } 344 } 345