Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 #include <linux/if_bridge.h>
0004 #include <net/switchdev.h>
0005 
0006 #include "lan966x_main.h"
0007 
0008 static struct notifier_block lan966x_netdevice_nb __read_mostly;
0009 static struct notifier_block lan966x_switchdev_nb __read_mostly;
0010 static struct notifier_block lan966x_switchdev_blocking_nb __read_mostly;
0011 
0012 static void lan966x_port_set_mcast_ip_flood(struct lan966x_port *port,
0013                         u32 pgid_ip)
0014 {
0015     struct lan966x *lan966x = port->lan966x;
0016     u32 flood_mask_ip;
0017 
0018     flood_mask_ip = lan_rd(lan966x, ANA_PGID(pgid_ip));
0019     flood_mask_ip = ANA_PGID_PGID_GET(flood_mask_ip);
0020 
0021     /* If mcast snooping is not enabled then use mcast flood mask
0022      * to decide to enable multicast flooding or not.
0023      */
0024     if (!port->mcast_ena) {
0025         u32 flood_mask;
0026 
0027         flood_mask = lan_rd(lan966x, ANA_PGID(PGID_MC));
0028         flood_mask = ANA_PGID_PGID_GET(flood_mask);
0029 
0030         if (flood_mask & BIT(port->chip_port))
0031             flood_mask_ip |= BIT(port->chip_port);
0032         else
0033             flood_mask_ip &= ~BIT(port->chip_port);
0034     } else {
0035         flood_mask_ip &= ~BIT(port->chip_port);
0036     }
0037 
0038     lan_rmw(ANA_PGID_PGID_SET(flood_mask_ip),
0039         ANA_PGID_PGID,
0040         lan966x, ANA_PGID(pgid_ip));
0041 }
0042 
0043 static void lan966x_port_set_mcast_flood(struct lan966x_port *port,
0044                      bool enabled)
0045 {
0046     u32 val = lan_rd(port->lan966x, ANA_PGID(PGID_MC));
0047 
0048     val = ANA_PGID_PGID_GET(val);
0049     if (enabled)
0050         val |= BIT(port->chip_port);
0051     else
0052         val &= ~BIT(port->chip_port);
0053 
0054     lan_rmw(ANA_PGID_PGID_SET(val),
0055         ANA_PGID_PGID,
0056         port->lan966x, ANA_PGID(PGID_MC));
0057 
0058     if (!port->mcast_ena) {
0059         lan966x_port_set_mcast_ip_flood(port, PGID_MCIPV4);
0060         lan966x_port_set_mcast_ip_flood(port, PGID_MCIPV6);
0061     }
0062 }
0063 
0064 static void lan966x_port_set_ucast_flood(struct lan966x_port *port,
0065                      bool enabled)
0066 {
0067     u32 val = lan_rd(port->lan966x, ANA_PGID(PGID_UC));
0068 
0069     val = ANA_PGID_PGID_GET(val);
0070     if (enabled)
0071         val |= BIT(port->chip_port);
0072     else
0073         val &= ~BIT(port->chip_port);
0074 
0075     lan_rmw(ANA_PGID_PGID_SET(val),
0076         ANA_PGID_PGID,
0077         port->lan966x, ANA_PGID(PGID_UC));
0078 }
0079 
0080 static void lan966x_port_set_bcast_flood(struct lan966x_port *port,
0081                      bool enabled)
0082 {
0083     u32 val = lan_rd(port->lan966x, ANA_PGID(PGID_BC));
0084 
0085     val = ANA_PGID_PGID_GET(val);
0086     if (enabled)
0087         val |= BIT(port->chip_port);
0088     else
0089         val &= ~BIT(port->chip_port);
0090 
0091     lan_rmw(ANA_PGID_PGID_SET(val),
0092         ANA_PGID_PGID,
0093         port->lan966x, ANA_PGID(PGID_BC));
0094 }
0095 
0096 static void lan966x_port_set_learning(struct lan966x_port *port, bool enabled)
0097 {
0098     lan_rmw(ANA_PORT_CFG_LEARN_ENA_SET(enabled),
0099         ANA_PORT_CFG_LEARN_ENA,
0100         port->lan966x, ANA_PORT_CFG(port->chip_port));
0101 
0102     port->learn_ena = enabled;
0103 }
0104 
0105 static void lan966x_port_bridge_flags(struct lan966x_port *port,
0106                       struct switchdev_brport_flags flags)
0107 {
0108     if (flags.mask & BR_MCAST_FLOOD)
0109         lan966x_port_set_mcast_flood(port,
0110                          !!(flags.val & BR_MCAST_FLOOD));
0111 
0112     if (flags.mask & BR_FLOOD)
0113         lan966x_port_set_ucast_flood(port,
0114                          !!(flags.val & BR_FLOOD));
0115 
0116     if (flags.mask & BR_BCAST_FLOOD)
0117         lan966x_port_set_bcast_flood(port,
0118                          !!(flags.val & BR_BCAST_FLOOD));
0119 
0120     if (flags.mask & BR_LEARNING)
0121         lan966x_port_set_learning(port,
0122                       !!(flags.val & BR_LEARNING));
0123 }
0124 
0125 static int lan966x_port_pre_bridge_flags(struct lan966x_port *port,
0126                      struct switchdev_brport_flags flags)
0127 {
0128     if (flags.mask & ~(BR_MCAST_FLOOD | BR_FLOOD | BR_BCAST_FLOOD |
0129                BR_LEARNING))
0130         return -EINVAL;
0131 
0132     return 0;
0133 }
0134 
0135 static void lan966x_update_fwd_mask(struct lan966x *lan966x)
0136 {
0137     int i;
0138 
0139     for (i = 0; i < lan966x->num_phys_ports; i++) {
0140         struct lan966x_port *port = lan966x->ports[i];
0141         unsigned long mask = 0;
0142 
0143         if (port && lan966x->bridge_fwd_mask & BIT(i))
0144             mask = lan966x->bridge_fwd_mask & ~BIT(i);
0145 
0146         mask |= BIT(CPU_PORT);
0147 
0148         lan_wr(ANA_PGID_PGID_SET(mask),
0149                lan966x, ANA_PGID(PGID_SRC + i));
0150     }
0151 }
0152 
0153 static void lan966x_port_stp_state_set(struct lan966x_port *port, u8 state)
0154 {
0155     struct lan966x *lan966x = port->lan966x;
0156     bool learn_ena = false;
0157 
0158     if ((state == BR_STATE_FORWARDING || state == BR_STATE_LEARNING) &&
0159         port->learn_ena)
0160         learn_ena = true;
0161 
0162     if (state == BR_STATE_FORWARDING)
0163         lan966x->bridge_fwd_mask |= BIT(port->chip_port);
0164     else
0165         lan966x->bridge_fwd_mask &= ~BIT(port->chip_port);
0166 
0167     lan_rmw(ANA_PORT_CFG_LEARN_ENA_SET(learn_ena),
0168         ANA_PORT_CFG_LEARN_ENA,
0169         lan966x, ANA_PORT_CFG(port->chip_port));
0170 
0171     lan966x_update_fwd_mask(lan966x);
0172 }
0173 
0174 static void lan966x_port_ageing_set(struct lan966x_port *port,
0175                     unsigned long ageing_clock_t)
0176 {
0177     unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);
0178     u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000;
0179 
0180     lan966x_mac_set_ageing(port->lan966x, ageing_time);
0181 }
0182 
0183 static void lan966x_port_mc_set(struct lan966x_port *port, bool mcast_ena)
0184 {
0185     struct lan966x *lan966x = port->lan966x;
0186 
0187     port->mcast_ena = mcast_ena;
0188     if (mcast_ena)
0189         lan966x_mdb_restore_entries(lan966x);
0190     else
0191         lan966x_mdb_clear_entries(lan966x);
0192 
0193     lan_rmw(ANA_CPU_FWD_CFG_IGMP_REDIR_ENA_SET(mcast_ena) |
0194         ANA_CPU_FWD_CFG_MLD_REDIR_ENA_SET(mcast_ena) |
0195         ANA_CPU_FWD_CFG_IPMC_CTRL_COPY_ENA_SET(mcast_ena),
0196         ANA_CPU_FWD_CFG_IGMP_REDIR_ENA |
0197         ANA_CPU_FWD_CFG_MLD_REDIR_ENA |
0198         ANA_CPU_FWD_CFG_IPMC_CTRL_COPY_ENA,
0199         lan966x, ANA_CPU_FWD_CFG(port->chip_port));
0200 
0201     lan966x_port_set_mcast_ip_flood(port, PGID_MCIPV4);
0202     lan966x_port_set_mcast_ip_flood(port, PGID_MCIPV6);
0203 }
0204 
0205 static int lan966x_port_attr_set(struct net_device *dev, const void *ctx,
0206                  const struct switchdev_attr *attr,
0207                  struct netlink_ext_ack *extack)
0208 {
0209     struct lan966x_port *port = netdev_priv(dev);
0210     int err = 0;
0211 
0212     if (ctx && ctx != port)
0213         return 0;
0214 
0215     switch (attr->id) {
0216     case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
0217         lan966x_port_bridge_flags(port, attr->u.brport_flags);
0218         break;
0219     case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
0220         err = lan966x_port_pre_bridge_flags(port, attr->u.brport_flags);
0221         break;
0222     case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
0223         lan966x_port_stp_state_set(port, attr->u.stp_state);
0224         break;
0225     case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
0226         lan966x_port_ageing_set(port, attr->u.ageing_time);
0227         break;
0228     case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
0229         lan966x_vlan_port_set_vlan_aware(port, attr->u.vlan_filtering);
0230         lan966x_vlan_port_apply(port);
0231         break;
0232     case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
0233         lan966x_port_mc_set(port, !attr->u.mc_disabled);
0234         break;
0235     default:
0236         err = -EOPNOTSUPP;
0237         break;
0238     }
0239 
0240     return err;
0241 }
0242 
0243 static int lan966x_port_bridge_join(struct lan966x_port *port,
0244                     struct net_device *bridge,
0245                     struct netlink_ext_ack *extack)
0246 {
0247     struct switchdev_brport_flags flags = {0};
0248     struct lan966x *lan966x = port->lan966x;
0249     struct net_device *dev = port->dev;
0250     int err;
0251 
0252     if (!lan966x->bridge_mask) {
0253         lan966x->bridge = bridge;
0254     } else {
0255         if (lan966x->bridge != bridge) {
0256             NL_SET_ERR_MSG_MOD(extack, "Not allow to add port to different bridge");
0257             return -ENODEV;
0258         }
0259     }
0260 
0261     err = switchdev_bridge_port_offload(dev, dev, port,
0262                         &lan966x_switchdev_nb,
0263                         &lan966x_switchdev_blocking_nb,
0264                         false, extack);
0265     if (err)
0266         return err;
0267 
0268     lan966x->bridge_mask |= BIT(port->chip_port);
0269 
0270     flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
0271     flags.val = flags.mask;
0272     lan966x_port_bridge_flags(port, flags);
0273 
0274     return 0;
0275 }
0276 
0277 static void lan966x_port_bridge_leave(struct lan966x_port *port,
0278                       struct net_device *bridge)
0279 {
0280     struct switchdev_brport_flags flags = {0};
0281     struct lan966x *lan966x = port->lan966x;
0282 
0283     flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
0284     flags.val = flags.mask & ~BR_LEARNING;
0285     lan966x_port_bridge_flags(port, flags);
0286 
0287     lan966x->bridge_mask &= ~BIT(port->chip_port);
0288 
0289     if (!lan966x->bridge_mask)
0290         lan966x->bridge = NULL;
0291 
0292     /* Set the port back to host mode */
0293     lan966x_vlan_port_set_vlan_aware(port, false);
0294     lan966x_vlan_port_set_vid(port, HOST_PVID, false, false);
0295     lan966x_vlan_port_apply(port);
0296 }
0297 
0298 static int lan966x_port_changeupper(struct net_device *dev,
0299                     struct netdev_notifier_changeupper_info *info)
0300 {
0301     struct lan966x_port *port = netdev_priv(dev);
0302     struct netlink_ext_ack *extack;
0303     int err = 0;
0304 
0305     extack = netdev_notifier_info_to_extack(&info->info);
0306 
0307     if (netif_is_bridge_master(info->upper_dev)) {
0308         if (info->linking)
0309             err = lan966x_port_bridge_join(port, info->upper_dev,
0310                                extack);
0311         else
0312             lan966x_port_bridge_leave(port, info->upper_dev);
0313     }
0314 
0315     return err;
0316 }
0317 
0318 static int lan966x_port_prechangeupper(struct net_device *dev,
0319                        struct netdev_notifier_changeupper_info *info)
0320 {
0321     struct lan966x_port *port = netdev_priv(dev);
0322 
0323     if (netif_is_bridge_master(info->upper_dev) && !info->linking)
0324         switchdev_bridge_port_unoffload(port->dev, port,
0325                         NULL, NULL);
0326 
0327     return NOTIFY_DONE;
0328 }
0329 
0330 static int lan966x_foreign_bridging_check(struct net_device *bridge,
0331                       struct netlink_ext_ack *extack)
0332 {
0333     struct lan966x *lan966x = NULL;
0334     bool has_foreign = false;
0335     struct net_device *dev;
0336     struct list_head *iter;
0337 
0338     if (!netif_is_bridge_master(bridge))
0339         return 0;
0340 
0341     netdev_for_each_lower_dev(bridge, dev, iter) {
0342         if (lan966x_netdevice_check(dev)) {
0343             struct lan966x_port *port = netdev_priv(dev);
0344 
0345             if (lan966x) {
0346                 /* Bridge already has at least one port of a
0347                  * lan966x switch inside it, check that it's
0348                  * the same instance of the driver.
0349                  */
0350                 if (port->lan966x != lan966x) {
0351                     NL_SET_ERR_MSG_MOD(extack,
0352                                "Bridging between multiple lan966x switches disallowed");
0353                     return -EINVAL;
0354                 }
0355             } else {
0356                 /* This is the first lan966x port inside this
0357                  * bridge
0358                  */
0359                 lan966x = port->lan966x;
0360             }
0361         } else {
0362             has_foreign = true;
0363         }
0364 
0365         if (lan966x && has_foreign) {
0366             NL_SET_ERR_MSG_MOD(extack,
0367                        "Bridging lan966x ports with foreign interfaces disallowed");
0368             return -EINVAL;
0369         }
0370     }
0371 
0372     return 0;
0373 }
0374 
0375 static int lan966x_bridge_check(struct net_device *dev,
0376                 struct netdev_notifier_changeupper_info *info)
0377 {
0378     return lan966x_foreign_bridging_check(info->upper_dev,
0379                           info->info.extack);
0380 }
0381 
0382 static int lan966x_netdevice_port_event(struct net_device *dev,
0383                     struct notifier_block *nb,
0384                     unsigned long event, void *ptr)
0385 {
0386     int err = 0;
0387 
0388     if (!lan966x_netdevice_check(dev)) {
0389         if (event == NETDEV_CHANGEUPPER)
0390             return lan966x_bridge_check(dev, ptr);
0391         return 0;
0392     }
0393 
0394     switch (event) {
0395     case NETDEV_PRECHANGEUPPER:
0396         err = lan966x_port_prechangeupper(dev, ptr);
0397         break;
0398     case NETDEV_CHANGEUPPER:
0399         err = lan966x_bridge_check(dev, ptr);
0400         if (err)
0401             return err;
0402 
0403         err = lan966x_port_changeupper(dev, ptr);
0404         break;
0405     }
0406 
0407     return err;
0408 }
0409 
0410 static int lan966x_netdevice_event(struct notifier_block *nb,
0411                    unsigned long event, void *ptr)
0412 {
0413     struct net_device *dev = netdev_notifier_info_to_dev(ptr);
0414     int ret;
0415 
0416     ret = lan966x_netdevice_port_event(dev, nb, event, ptr);
0417 
0418     return notifier_from_errno(ret);
0419 }
0420 
0421 /* We don't offload uppers such as LAG as bridge ports, so every device except
0422  * the bridge itself is foreign.
0423  */
0424 static bool lan966x_foreign_dev_check(const struct net_device *dev,
0425                       const struct net_device *foreign_dev)
0426 {
0427     struct lan966x_port *port = netdev_priv(dev);
0428     struct lan966x *lan966x = port->lan966x;
0429 
0430     if (netif_is_bridge_master(foreign_dev))
0431         if (lan966x->bridge == foreign_dev)
0432             return false;
0433 
0434     return true;
0435 }
0436 
0437 static int lan966x_switchdev_event(struct notifier_block *nb,
0438                    unsigned long event, void *ptr)
0439 {
0440     struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
0441     int err;
0442 
0443     switch (event) {
0444     case SWITCHDEV_PORT_ATTR_SET:
0445         err = switchdev_handle_port_attr_set(dev, ptr,
0446                              lan966x_netdevice_check,
0447                              lan966x_port_attr_set);
0448         return notifier_from_errno(err);
0449     case SWITCHDEV_FDB_ADD_TO_DEVICE:
0450     case SWITCHDEV_FDB_DEL_TO_DEVICE:
0451         err = switchdev_handle_fdb_event_to_device(dev, event, ptr,
0452                                lan966x_netdevice_check,
0453                                lan966x_foreign_dev_check,
0454                                lan966x_handle_fdb);
0455         return notifier_from_errno(err);
0456     }
0457 
0458     return NOTIFY_DONE;
0459 }
0460 
0461 static int lan966x_handle_port_vlan_add(struct lan966x_port *port,
0462                     const struct switchdev_obj *obj)
0463 {
0464     const struct switchdev_obj_port_vlan *v = SWITCHDEV_OBJ_PORT_VLAN(obj);
0465     struct lan966x *lan966x = port->lan966x;
0466 
0467     if (!netif_is_bridge_master(obj->orig_dev))
0468         lan966x_vlan_port_add_vlan(port, v->vid,
0469                        v->flags & BRIDGE_VLAN_INFO_PVID,
0470                        v->flags & BRIDGE_VLAN_INFO_UNTAGGED);
0471     else
0472         lan966x_vlan_cpu_add_vlan(lan966x, v->vid);
0473 
0474     return 0;
0475 }
0476 
0477 static int lan966x_handle_port_obj_add(struct net_device *dev, const void *ctx,
0478                        const struct switchdev_obj *obj,
0479                        struct netlink_ext_ack *extack)
0480 {
0481     struct lan966x_port *port = netdev_priv(dev);
0482     int err;
0483 
0484     if (ctx && ctx != port)
0485         return 0;
0486 
0487     switch (obj->id) {
0488     case SWITCHDEV_OBJ_ID_PORT_VLAN:
0489         err = lan966x_handle_port_vlan_add(port, obj);
0490         break;
0491     case SWITCHDEV_OBJ_ID_PORT_MDB:
0492     case SWITCHDEV_OBJ_ID_HOST_MDB:
0493         err = lan966x_handle_port_mdb_add(port, obj);
0494         break;
0495     default:
0496         err = -EOPNOTSUPP;
0497         break;
0498     }
0499 
0500     return err;
0501 }
0502 
0503 static int lan966x_handle_port_vlan_del(struct lan966x_port *port,
0504                     const struct switchdev_obj *obj)
0505 {
0506     const struct switchdev_obj_port_vlan *v = SWITCHDEV_OBJ_PORT_VLAN(obj);
0507     struct lan966x *lan966x = port->lan966x;
0508 
0509     if (!netif_is_bridge_master(obj->orig_dev))
0510         lan966x_vlan_port_del_vlan(port, v->vid);
0511     else
0512         lan966x_vlan_cpu_del_vlan(lan966x, v->vid);
0513 
0514     return 0;
0515 }
0516 
0517 static int lan966x_handle_port_obj_del(struct net_device *dev, const void *ctx,
0518                        const struct switchdev_obj *obj)
0519 {
0520     struct lan966x_port *port = netdev_priv(dev);
0521     int err;
0522 
0523     if (ctx && ctx != port)
0524         return 0;
0525 
0526     switch (obj->id) {
0527     case SWITCHDEV_OBJ_ID_PORT_VLAN:
0528         err = lan966x_handle_port_vlan_del(port, obj);
0529         break;
0530     case SWITCHDEV_OBJ_ID_PORT_MDB:
0531     case SWITCHDEV_OBJ_ID_HOST_MDB:
0532         err = lan966x_handle_port_mdb_del(port, obj);
0533         break;
0534     default:
0535         err = -EOPNOTSUPP;
0536         break;
0537     }
0538 
0539     return err;
0540 }
0541 
0542 static int lan966x_switchdev_blocking_event(struct notifier_block *nb,
0543                         unsigned long event,
0544                         void *ptr)
0545 {
0546     struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
0547     int err;
0548 
0549     switch (event) {
0550     case SWITCHDEV_PORT_OBJ_ADD:
0551         err = switchdev_handle_port_obj_add(dev, ptr,
0552                             lan966x_netdevice_check,
0553                             lan966x_handle_port_obj_add);
0554         return notifier_from_errno(err);
0555     case SWITCHDEV_PORT_OBJ_DEL:
0556         err = switchdev_handle_port_obj_del(dev, ptr,
0557                             lan966x_netdevice_check,
0558                             lan966x_handle_port_obj_del);
0559         return notifier_from_errno(err);
0560     case SWITCHDEV_PORT_ATTR_SET:
0561         err = switchdev_handle_port_attr_set(dev, ptr,
0562                              lan966x_netdevice_check,
0563                              lan966x_port_attr_set);
0564         return notifier_from_errno(err);
0565     }
0566 
0567     return NOTIFY_DONE;
0568 }
0569 
0570 static struct notifier_block lan966x_netdevice_nb __read_mostly = {
0571     .notifier_call = lan966x_netdevice_event,
0572 };
0573 
0574 static struct notifier_block lan966x_switchdev_nb __read_mostly = {
0575     .notifier_call = lan966x_switchdev_event,
0576 };
0577 
0578 static struct notifier_block lan966x_switchdev_blocking_nb __read_mostly = {
0579     .notifier_call = lan966x_switchdev_blocking_event,
0580 };
0581 
0582 void lan966x_register_notifier_blocks(void)
0583 {
0584     register_netdevice_notifier(&lan966x_netdevice_nb);
0585     register_switchdev_notifier(&lan966x_switchdev_nb);
0586     register_switchdev_blocking_notifier(&lan966x_switchdev_blocking_nb);
0587 }
0588 
0589 void lan966x_unregister_notifier_blocks(void)
0590 {
0591     unregister_switchdev_blocking_notifier(&lan966x_switchdev_blocking_nb);
0592     unregister_switchdev_notifier(&lan966x_switchdev_nb);
0593     unregister_netdevice_notifier(&lan966x_netdevice_nb);
0594 }