Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 #include "lan966x_main.h"
0004 
0005 #define VLANACCESS_CMD_IDLE     0
0006 #define VLANACCESS_CMD_READ     1
0007 #define VLANACCESS_CMD_WRITE        2
0008 #define VLANACCESS_CMD_INIT     3
0009 
0010 static int lan966x_vlan_get_status(struct lan966x *lan966x)
0011 {
0012     return lan_rd(lan966x, ANA_VLANACCESS);
0013 }
0014 
0015 static int lan966x_vlan_wait_for_completion(struct lan966x *lan966x)
0016 {
0017     u32 val;
0018 
0019     return readx_poll_timeout(lan966x_vlan_get_status,
0020         lan966x, val,
0021         (val & ANA_VLANACCESS_VLAN_TBL_CMD) ==
0022         VLANACCESS_CMD_IDLE,
0023         TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
0024 }
0025 
0026 static void lan966x_vlan_set_mask(struct lan966x *lan966x, u16 vid)
0027 {
0028     u16 mask = lan966x->vlan_mask[vid];
0029     bool cpu_dis;
0030 
0031     cpu_dis = !(mask & BIT(CPU_PORT));
0032 
0033     /* Set flags and the VID to configure */
0034     lan_rmw(ANA_VLANTIDX_VLAN_PGID_CPU_DIS_SET(cpu_dis) |
0035         ANA_VLANTIDX_V_INDEX_SET(vid),
0036         ANA_VLANTIDX_VLAN_PGID_CPU_DIS |
0037         ANA_VLANTIDX_V_INDEX,
0038         lan966x, ANA_VLANTIDX);
0039 
0040     /* Set the vlan port members mask */
0041     lan_rmw(ANA_VLAN_PORT_MASK_VLAN_PORT_MASK_SET(mask),
0042         ANA_VLAN_PORT_MASK_VLAN_PORT_MASK,
0043         lan966x, ANA_VLAN_PORT_MASK);
0044 
0045     /* Issue a write command */
0046     lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_WRITE),
0047         ANA_VLANACCESS_VLAN_TBL_CMD,
0048         lan966x, ANA_VLANACCESS);
0049 
0050     if (lan966x_vlan_wait_for_completion(lan966x))
0051         dev_err(lan966x->dev, "Vlan set mask failed\n");
0052 }
0053 
0054 static void lan966x_vlan_port_add_vlan_mask(struct lan966x_port *port, u16 vid)
0055 {
0056     struct lan966x *lan966x = port->lan966x;
0057     u8 p = port->chip_port;
0058 
0059     lan966x->vlan_mask[vid] |= BIT(p);
0060     lan966x_vlan_set_mask(lan966x, vid);
0061 }
0062 
0063 static void lan966x_vlan_port_del_vlan_mask(struct lan966x_port *port, u16 vid)
0064 {
0065     struct lan966x *lan966x = port->lan966x;
0066     u8 p = port->chip_port;
0067 
0068     lan966x->vlan_mask[vid] &= ~BIT(p);
0069     lan966x_vlan_set_mask(lan966x, vid);
0070 }
0071 
0072 static bool lan966x_vlan_port_any_vlan_mask(struct lan966x *lan966x, u16 vid)
0073 {
0074     return !!(lan966x->vlan_mask[vid] & ~BIT(CPU_PORT));
0075 }
0076 
0077 static void lan966x_vlan_cpu_add_vlan_mask(struct lan966x *lan966x, u16 vid)
0078 {
0079     lan966x->vlan_mask[vid] |= BIT(CPU_PORT);
0080     lan966x_vlan_set_mask(lan966x, vid);
0081 }
0082 
0083 static void lan966x_vlan_cpu_del_vlan_mask(struct lan966x *lan966x, u16 vid)
0084 {
0085     lan966x->vlan_mask[vid] &= ~BIT(CPU_PORT);
0086     lan966x_vlan_set_mask(lan966x, vid);
0087 }
0088 
0089 static void lan966x_vlan_cpu_add_cpu_vlan_mask(struct lan966x *lan966x, u16 vid)
0090 {
0091     __set_bit(vid, lan966x->cpu_vlan_mask);
0092 }
0093 
0094 static void lan966x_vlan_cpu_del_cpu_vlan_mask(struct lan966x *lan966x, u16 vid)
0095 {
0096     __clear_bit(vid, lan966x->cpu_vlan_mask);
0097 }
0098 
0099 bool lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x *lan966x, u16 vid)
0100 {
0101     return test_bit(vid, lan966x->cpu_vlan_mask);
0102 }
0103 
0104 static u16 lan966x_vlan_port_get_pvid(struct lan966x_port *port)
0105 {
0106     struct lan966x *lan966x = port->lan966x;
0107 
0108     if (!(lan966x->bridge_mask & BIT(port->chip_port)))
0109         return HOST_PVID;
0110 
0111     return port->vlan_aware ? port->pvid : UNAWARE_PVID;
0112 }
0113 
0114 int lan966x_vlan_port_set_vid(struct lan966x_port *port, u16 vid,
0115                   bool pvid, bool untagged)
0116 {
0117     struct lan966x *lan966x = port->lan966x;
0118 
0119     /* Egress vlan classification */
0120     if (untagged && port->vid != vid) {
0121         if (port->vid) {
0122             dev_err(lan966x->dev,
0123                 "Port already has a native VLAN: %d\n",
0124                 port->vid);
0125             return -EBUSY;
0126         }
0127         port->vid = vid;
0128     }
0129 
0130     /* Default ingress vlan classification */
0131     if (pvid)
0132         port->pvid = vid;
0133 
0134     return 0;
0135 }
0136 
0137 static void lan966x_vlan_port_remove_vid(struct lan966x_port *port, u16 vid)
0138 {
0139     if (port->pvid == vid)
0140         port->pvid = 0;
0141 
0142     if (port->vid == vid)
0143         port->vid = 0;
0144 }
0145 
0146 void lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port,
0147                       bool vlan_aware)
0148 {
0149     port->vlan_aware = vlan_aware;
0150 }
0151 
0152 void lan966x_vlan_port_apply(struct lan966x_port *port)
0153 {
0154     struct lan966x *lan966x = port->lan966x;
0155     u16 pvid;
0156     u32 val;
0157 
0158     pvid = lan966x_vlan_port_get_pvid(port);
0159 
0160     /* Ingress clasification (ANA_PORT_VLAN_CFG) */
0161     /* Default vlan to classify for untagged frames (may be zero) */
0162     val = ANA_VLAN_CFG_VLAN_VID_SET(pvid);
0163     if (port->vlan_aware)
0164         val |= ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) |
0165                ANA_VLAN_CFG_VLAN_POP_CNT_SET(1);
0166 
0167     lan_rmw(val,
0168         ANA_VLAN_CFG_VLAN_VID | ANA_VLAN_CFG_VLAN_AWARE_ENA |
0169         ANA_VLAN_CFG_VLAN_POP_CNT,
0170         lan966x, ANA_VLAN_CFG(port->chip_port));
0171 
0172     /* Drop frames with multicast source address */
0173     val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1);
0174     if (port->vlan_aware && !pvid)
0175         /* If port is vlan-aware and tagged, drop untagged and priority
0176          * tagged frames.
0177          */
0178         val |= ANA_DROP_CFG_DROP_UNTAGGED_ENA_SET(1) |
0179                ANA_DROP_CFG_DROP_PRIO_S_TAGGED_ENA_SET(1) |
0180                ANA_DROP_CFG_DROP_PRIO_C_TAGGED_ENA_SET(1);
0181 
0182     lan_wr(val, lan966x, ANA_DROP_CFG(port->chip_port));
0183 
0184     /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */
0185     val = REW_TAG_CFG_TAG_TPID_CFG_SET(0);
0186     if (port->vlan_aware) {
0187         if (port->vid)
0188             /* Tag all frames except when VID == DEFAULT_VLAN */
0189             val |= REW_TAG_CFG_TAG_CFG_SET(1);
0190         else
0191             val |= REW_TAG_CFG_TAG_CFG_SET(3);
0192     }
0193 
0194     /* Update only some bits in the register */
0195     lan_rmw(val,
0196         REW_TAG_CFG_TAG_TPID_CFG | REW_TAG_CFG_TAG_CFG,
0197         lan966x, REW_TAG_CFG(port->chip_port));
0198 
0199     /* Set default VLAN and tag type to 8021Q */
0200     lan_rmw(REW_PORT_VLAN_CFG_PORT_TPID_SET(ETH_P_8021Q) |
0201         REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid),
0202         REW_PORT_VLAN_CFG_PORT_TPID |
0203         REW_PORT_VLAN_CFG_PORT_VID,
0204         lan966x, REW_PORT_VLAN_CFG(port->chip_port));
0205 }
0206 
0207 void lan966x_vlan_port_add_vlan(struct lan966x_port *port,
0208                 u16 vid,
0209                 bool pvid,
0210                 bool untagged)
0211 {
0212     struct lan966x *lan966x = port->lan966x;
0213 
0214     /* If the CPU(br) is already part of the vlan then add the fdb
0215      * entries in MAC table to copy the frames to the CPU(br).
0216      * If the CPU(br) is not part of the vlan then it would
0217      * just drop the frames.
0218      */
0219     if (lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x, vid)) {
0220         lan966x_vlan_cpu_add_vlan_mask(lan966x, vid);
0221         lan966x_fdb_write_entries(lan966x, vid);
0222         lan966x_mdb_write_entries(lan966x, vid);
0223     }
0224 
0225     lan966x_vlan_port_set_vid(port, vid, pvid, untagged);
0226     lan966x_vlan_port_add_vlan_mask(port, vid);
0227     lan966x_vlan_port_apply(port);
0228 }
0229 
0230 void lan966x_vlan_port_del_vlan(struct lan966x_port *port, u16 vid)
0231 {
0232     struct lan966x *lan966x = port->lan966x;
0233 
0234     lan966x_vlan_port_remove_vid(port, vid);
0235     lan966x_vlan_port_del_vlan_mask(port, vid);
0236     lan966x_vlan_port_apply(port);
0237 
0238     /* In case there are no other ports in vlan then remove the CPU from
0239      * that vlan but still keep it in the mask because it may be needed
0240      * again then another port gets added in that vlan
0241      */
0242     if (!lan966x_vlan_port_any_vlan_mask(lan966x, vid)) {
0243         lan966x_vlan_cpu_del_vlan_mask(lan966x, vid);
0244         lan966x_fdb_erase_entries(lan966x, vid);
0245         lan966x_mdb_erase_entries(lan966x, vid);
0246     }
0247 }
0248 
0249 void lan966x_vlan_cpu_add_vlan(struct lan966x *lan966x, u16 vid)
0250 {
0251     /* Add an entry in the MAC table for the CPU
0252      * Add the CPU part of the vlan only if there is another port in that
0253      * vlan otherwise all the broadcast frames in that vlan will go to CPU
0254      * even if none of the ports are in the vlan and then the CPU will just
0255      * need to discard these frames. It is required to store this
0256      * information so when a front port is added then it would add also the
0257      * CPU port.
0258      */
0259     if (lan966x_vlan_port_any_vlan_mask(lan966x, vid)) {
0260         lan966x_vlan_cpu_add_vlan_mask(lan966x, vid);
0261         lan966x_mdb_write_entries(lan966x, vid);
0262     }
0263 
0264     lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, vid);
0265     lan966x_fdb_write_entries(lan966x, vid);
0266 }
0267 
0268 void lan966x_vlan_cpu_del_vlan(struct lan966x *lan966x, u16 vid)
0269 {
0270     /* Remove the CPU part of the vlan */
0271     lan966x_vlan_cpu_del_cpu_vlan_mask(lan966x, vid);
0272     lan966x_vlan_cpu_del_vlan_mask(lan966x, vid);
0273     lan966x_fdb_erase_entries(lan966x, vid);
0274     lan966x_mdb_erase_entries(lan966x, vid);
0275 }
0276 
0277 void lan966x_vlan_init(struct lan966x *lan966x)
0278 {
0279     u16 port, vid;
0280 
0281     /* Clear VLAN table, by default all ports are members of all VLANS */
0282     lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_INIT),
0283         ANA_VLANACCESS_VLAN_TBL_CMD,
0284         lan966x, ANA_VLANACCESS);
0285     lan966x_vlan_wait_for_completion(lan966x);
0286 
0287     for (vid = 1; vid < VLAN_N_VID; vid++) {
0288         lan966x->vlan_mask[vid] = 0;
0289         lan966x_vlan_set_mask(lan966x, vid);
0290     }
0291 
0292     /* Set all the ports + cpu to be part of HOST_PVID and UNAWARE_PVID */
0293     lan966x->vlan_mask[HOST_PVID] =
0294         GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT);
0295     lan966x_vlan_set_mask(lan966x, HOST_PVID);
0296 
0297     lan966x->vlan_mask[UNAWARE_PVID] =
0298         GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT);
0299     lan966x_vlan_set_mask(lan966x, UNAWARE_PVID);
0300 
0301     lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, UNAWARE_PVID);
0302 
0303     /* Configure the CPU port to be vlan aware */
0304     lan_wr(ANA_VLAN_CFG_VLAN_VID_SET(0) |
0305            ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) |
0306            ANA_VLAN_CFG_VLAN_POP_CNT_SET(1),
0307            lan966x, ANA_VLAN_CFG(CPU_PORT));
0308 
0309     /* Set vlan ingress filter mask to all ports */
0310     lan_wr(GENMASK(lan966x->num_phys_ports, 0),
0311            lan966x, ANA_VLANMASK);
0312 
0313     for (port = 0; port < lan966x->num_phys_ports; port++) {
0314         lan_wr(0, lan966x, REW_PORT_VLAN_CFG(port));
0315         lan_wr(0, lan966x, REW_TAG_CFG(port));
0316     }
0317 }