Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: marvell: prestera: Add Switchdev driver implementation

The following features are supported:

- VLAN-aware bridge offloading
- VLAN-unaware bridge offloading
- FDB offloading (learning, ageing)
- Switchport configuration

Currently there are some limitations like:

- Only 1 VLAN-aware bridge instance supported
- FDB ageing timeout parameter is set globally per device

Co-developed-by: Serhiy Boiko <serhiy.boiko@plvision.eu>
Signed-off-by: Serhiy Boiko <serhiy.boiko@plvision.eu>
Co-developed-by: Serhiy Pshyk <serhiy.pshyk@plvision.eu>
Signed-off-by: Serhiy Pshyk <serhiy.pshyk@plvision.eu>
Co-developed-by: Taras Chornyi <taras.chornyi@plvision.eu>
Signed-off-by: Taras Chornyi <taras.chornyi@plvision.eu>
Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vadym Kochan and committed by
David S. Miller
e1189d9a a97d3c69

+1807 -4
+2 -1
drivers/net/ethernet/marvell/prestera/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 obj-$(CONFIG_PRESTERA) += prestera.o 3 3 prestera-objs := prestera_main.o prestera_hw.o prestera_dsa.o \ 4 - prestera_rxtx.o prestera_devlink.o prestera_ethtool.o 4 + prestera_rxtx.o prestera_devlink.o prestera_ethtool.o \ 5 + prestera_switchdev.o 5 6 6 7 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
+31
drivers/net/ethernet/marvell/prestera/prestera.h
··· 12 12 13 13 #define PRESTERA_DRV_NAME "prestera" 14 14 15 + #define PRESTERA_DEFAULT_VID 1 16 + 15 17 struct prestera_fw_rev { 16 18 u16 maj; 17 19 u16 min; ··· 68 66 u32 hw_id; 69 67 u32 dev_id; 70 68 u16 fp_id; 69 + u16 pvid; 71 70 bool autoneg; 72 71 u64 adver_link_modes; 73 72 u8 adver_fec; 74 73 struct prestera_port_caps caps; 75 74 struct list_head list; 75 + struct list_head vlans_list; 76 76 struct { 77 77 struct prestera_port_stats stats; 78 78 struct delayed_work caching_dw; ··· 104 100 PRESTERA_EVENT_TYPE_UNSPEC, 105 101 106 102 PRESTERA_EVENT_TYPE_PORT, 103 + PRESTERA_EVENT_TYPE_FDB, 107 104 PRESTERA_EVENT_TYPE_RXTX, 108 105 109 106 PRESTERA_EVENT_TYPE_MAX ··· 127 122 } data; 128 123 }; 129 124 125 + enum prestera_fdb_event_id { 126 + PRESTERA_FDB_EVENT_UNSPEC, 127 + PRESTERA_FDB_EVENT_LEARNED, 128 + PRESTERA_FDB_EVENT_AGED, 129 + }; 130 + 131 + struct prestera_fdb_event { 132 + u32 port_id; 133 + u32 vid; 134 + union { 135 + u8 mac[ETH_ALEN]; 136 + } data; 137 + }; 138 + 130 139 struct prestera_event { 131 140 u16 id; 132 141 union { 133 142 struct prestera_port_event port_evt; 143 + struct prestera_fdb_event fdb_evt; 134 144 }; 135 145 }; 136 146 147 + struct prestera_switchdev; 137 148 struct prestera_rxtx; 138 149 139 150 struct prestera_switch { 140 151 struct prestera_device *dev; 152 + struct prestera_switchdev *swdev; 141 153 struct prestera_rxtx *rxtx; 142 154 struct list_head event_handlers; 155 + struct notifier_block netdev_nb; 143 156 char base_mac[ETH_ALEN]; 144 157 struct list_head port_list; 145 158 rwlock_t port_list_lock; ··· 194 171 195 172 int prestera_port_autoneg_set(struct prestera_port *port, bool enable, 196 173 u64 adver_link_modes, u8 adver_fec); 174 + 175 + struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id); 176 + 177 + struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev); 178 + 179 + int prestera_port_pvid_set(struct prestera_port *port, u16 vid); 180 + 181 + bool prestera_netdev_check(const struct net_device *dev); 197 182 198 183 #endif /* _PRESTERA_H_ */
+329
drivers/net/ethernet/marvell/prestera/prestera_hw.c
··· 20 20 PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101, 21 21 PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110, 22 22 23 + PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200, 24 + PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201, 25 + PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202, 26 + PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203, 27 + 28 + PRESTERA_CMD_TYPE_FDB_ADD = 0x300, 29 + PRESTERA_CMD_TYPE_FDB_DELETE = 0x301, 30 + PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310, 31 + PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311, 32 + PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312, 33 + 34 + PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400, 35 + PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401, 36 + PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402, 37 + PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403, 38 + 23 39 PRESTERA_CMD_TYPE_RXTX_INIT = 0x800, 24 40 PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801, 41 + 42 + PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000, 25 43 26 44 PRESTERA_CMD_TYPE_ACK = 0x10000, 27 45 PRESTERA_CMD_TYPE_MAX ··· 50 32 PRESTERA_CMD_PORT_ATTR_MTU = 3, 51 33 PRESTERA_CMD_PORT_ATTR_MAC = 4, 52 34 PRESTERA_CMD_PORT_ATTR_SPEED = 5, 35 + PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6, 36 + PRESTERA_CMD_PORT_ATTR_LEARNING = 7, 37 + PRESTERA_CMD_PORT_ATTR_FLOOD = 8, 53 38 PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9, 54 39 PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY = 10, 55 40 PRESTERA_CMD_PORT_ATTR_REMOTE_FC = 11, ··· 68 47 69 48 enum { 70 49 PRESTERA_CMD_SWITCH_ATTR_MAC = 1, 50 + PRESTERA_CMD_SWITCH_ATTR_AGEING = 2, 71 51 }; 72 52 73 53 enum { ··· 154 132 155 133 union prestera_msg_switch_param { 156 134 u8 mac[ETH_ALEN]; 135 + u32 ageing_timeout_ms; 157 136 }; 158 137 159 138 struct prestera_msg_switch_attr_req { ··· 193 170 u8 oper_state; 194 171 u32 mtu; 195 172 u8 mac[ETH_ALEN]; 173 + u8 accept_frm_type; 196 174 u32 speed; 175 + u8 learning; 176 + u8 flood; 197 177 u32 link_mode; 198 178 u8 type; 199 179 u8 duplex; ··· 237 211 u16 fp_id; 238 212 }; 239 213 214 + struct prestera_msg_vlan_req { 215 + struct prestera_msg_cmd cmd; 216 + u32 port; 217 + u32 dev; 218 + u16 vid; 219 + u8 is_member; 220 + u8 is_tagged; 221 + }; 222 + 223 + struct prestera_msg_fdb_req { 224 + struct prestera_msg_cmd cmd; 225 + u8 dest_type; 226 + u32 port; 227 + u32 dev; 228 + u8 mac[ETH_ALEN]; 229 + u16 vid; 230 + u8 dynamic; 231 + u32 flush_mode; 232 + }; 233 + 234 + struct prestera_msg_bridge_req { 235 + struct prestera_msg_cmd cmd; 236 + u32 port; 237 + u32 dev; 238 + u16 bridge; 239 + }; 240 + 241 + struct prestera_msg_bridge_resp { 242 + struct prestera_msg_ret ret; 243 + u16 bridge; 244 + }; 245 + 246 + struct prestera_msg_stp_req { 247 + struct prestera_msg_cmd cmd; 248 + u32 port; 249 + u32 dev; 250 + u16 vid; 251 + u8 state; 252 + }; 253 + 240 254 struct prestera_msg_rxtx_req { 241 255 struct prestera_msg_cmd cmd; 242 256 u8 use_sdma; ··· 306 240 struct prestera_msg_event id; 307 241 u32 port_id; 308 242 union prestera_msg_event_port_param param; 243 + }; 244 + 245 + union prestera_msg_event_fdb_param { 246 + u8 mac[ETH_ALEN]; 247 + }; 248 + 249 + struct prestera_msg_event_fdb { 250 + struct prestera_msg_event id; 251 + u8 dest_type; 252 + u32 port_id; 253 + u32 vid; 254 + union prestera_msg_event_fdb_param param; 309 255 }; 310 256 311 257 static int __prestera_cmd_ret(struct prestera_switch *sw, ··· 382 304 return 0; 383 305 } 384 306 307 + static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt) 308 + { 309 + struct prestera_msg_event_fdb *hw_evt = msg; 310 + 311 + evt->fdb_evt.port_id = hw_evt->port_id; 312 + evt->fdb_evt.vid = hw_evt->vid; 313 + 314 + ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac); 315 + 316 + return 0; 317 + } 318 + 385 319 static struct prestera_fw_evt_parser { 386 320 int (*func)(void *msg, struct prestera_event *evt); 387 321 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = { 388 322 [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt }, 323 + [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt }, 389 324 }; 390 325 391 326 static struct prestera_fw_event_handler * ··· 540 449 WARN_ON(!list_empty(&sw->event_handlers)); 541 450 } 542 451 452 + int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms) 453 + { 454 + struct prestera_msg_switch_attr_req req = { 455 + .attr = PRESTERA_CMD_SWITCH_ATTR_AGEING, 456 + .param = { 457 + .ageing_timeout_ms = ageing_ms, 458 + }, 459 + }; 460 + 461 + return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET, 462 + &req.cmd, sizeof(req)); 463 + } 464 + 543 465 int prestera_hw_port_state_set(const struct prestera_port *port, 544 466 bool admin_state) 545 467 { ··· 593 489 }; 594 490 595 491 ether_addr_copy(req.param.mac, mac); 492 + 493 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 494 + &req.cmd, sizeof(req)); 495 + } 496 + 497 + int prestera_hw_port_accept_frm_type(struct prestera_port *port, 498 + enum prestera_accept_frm_type type) 499 + { 500 + struct prestera_msg_port_attr_req req = { 501 + .attr = PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE, 502 + .port = port->hw_id, 503 + .dev = port->dev_id, 504 + .param = { 505 + .accept_frm_type = type, 506 + } 507 + }; 596 508 597 509 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 598 510 &req.cmd, sizeof(req)); ··· 971 851 st->good_octets_sent = hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]; 972 852 973 853 return 0; 854 + } 855 + 856 + int prestera_hw_port_learning_set(struct prestera_port *port, bool enable) 857 + { 858 + struct prestera_msg_port_attr_req req = { 859 + .attr = PRESTERA_CMD_PORT_ATTR_LEARNING, 860 + .port = port->hw_id, 861 + .dev = port->dev_id, 862 + .param = { 863 + .learning = enable, 864 + } 865 + }; 866 + 867 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 868 + &req.cmd, sizeof(req)); 869 + } 870 + 871 + int prestera_hw_port_flood_set(struct prestera_port *port, bool flood) 872 + { 873 + struct prestera_msg_port_attr_req req = { 874 + .attr = PRESTERA_CMD_PORT_ATTR_FLOOD, 875 + .port = port->hw_id, 876 + .dev = port->dev_id, 877 + .param = { 878 + .flood = flood, 879 + } 880 + }; 881 + 882 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 883 + &req.cmd, sizeof(req)); 884 + } 885 + 886 + int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid) 887 + { 888 + struct prestera_msg_vlan_req req = { 889 + .vid = vid, 890 + }; 891 + 892 + return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE, 893 + &req.cmd, sizeof(req)); 894 + } 895 + 896 + int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid) 897 + { 898 + struct prestera_msg_vlan_req req = { 899 + .vid = vid, 900 + }; 901 + 902 + return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE, 903 + &req.cmd, sizeof(req)); 904 + } 905 + 906 + int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid, 907 + bool is_member, bool untagged) 908 + { 909 + struct prestera_msg_vlan_req req = { 910 + .port = port->hw_id, 911 + .dev = port->dev_id, 912 + .vid = vid, 913 + .is_member = is_member, 914 + .is_tagged = !untagged, 915 + }; 916 + 917 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET, 918 + &req.cmd, sizeof(req)); 919 + } 920 + 921 + int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid) 922 + { 923 + struct prestera_msg_vlan_req req = { 924 + .port = port->hw_id, 925 + .dev = port->dev_id, 926 + .vid = vid, 927 + }; 928 + 929 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET, 930 + &req.cmd, sizeof(req)); 931 + } 932 + 933 + int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state) 934 + { 935 + struct prestera_msg_stp_req req = { 936 + .port = port->hw_id, 937 + .dev = port->dev_id, 938 + .vid = vid, 939 + .state = state, 940 + }; 941 + 942 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET, 943 + &req.cmd, sizeof(req)); 944 + } 945 + 946 + int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac, 947 + u16 vid, bool dynamic) 948 + { 949 + struct prestera_msg_fdb_req req = { 950 + .port = port->hw_id, 951 + .dev = port->dev_id, 952 + .vid = vid, 953 + .dynamic = dynamic, 954 + }; 955 + 956 + ether_addr_copy(req.mac, mac); 957 + 958 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD, 959 + &req.cmd, sizeof(req)); 960 + } 961 + 962 + int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac, 963 + u16 vid) 964 + { 965 + struct prestera_msg_fdb_req req = { 966 + .port = port->hw_id, 967 + .dev = port->dev_id, 968 + .vid = vid, 969 + }; 970 + 971 + ether_addr_copy(req.mac, mac); 972 + 973 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE, 974 + &req.cmd, sizeof(req)); 975 + } 976 + 977 + int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode) 978 + { 979 + struct prestera_msg_fdb_req req = { 980 + .port = port->hw_id, 981 + .dev = port->dev_id, 982 + .flush_mode = mode, 983 + }; 984 + 985 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT, 986 + &req.cmd, sizeof(req)); 987 + } 988 + 989 + int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode) 990 + { 991 + struct prestera_msg_fdb_req req = { 992 + .vid = vid, 993 + .flush_mode = mode, 994 + }; 995 + 996 + return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN, 997 + &req.cmd, sizeof(req)); 998 + } 999 + 1000 + int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid, 1001 + u32 mode) 1002 + { 1003 + struct prestera_msg_fdb_req req = { 1004 + .port = port->hw_id, 1005 + .dev = port->dev_id, 1006 + .vid = vid, 1007 + .flush_mode = mode, 1008 + }; 1009 + 1010 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN, 1011 + &req.cmd, sizeof(req)); 1012 + } 1013 + 1014 + int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id) 1015 + { 1016 + struct prestera_msg_bridge_resp resp; 1017 + struct prestera_msg_bridge_req req; 1018 + int err; 1019 + 1020 + err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE, 1021 + &req.cmd, sizeof(req), 1022 + &resp.ret, sizeof(resp)); 1023 + if (err) 1024 + return err; 1025 + 1026 + *bridge_id = resp.bridge; 1027 + 1028 + return 0; 1029 + } 1030 + 1031 + int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id) 1032 + { 1033 + struct prestera_msg_bridge_req req = { 1034 + .bridge = bridge_id, 1035 + }; 1036 + 1037 + return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE, 1038 + &req.cmd, sizeof(req)); 1039 + } 1040 + 1041 + int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id) 1042 + { 1043 + struct prestera_msg_bridge_req req = { 1044 + .bridge = bridge_id, 1045 + .port = port->hw_id, 1046 + .dev = port->dev_id, 1047 + }; 1048 + 1049 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD, 1050 + &req.cmd, sizeof(req)); 1051 + } 1052 + 1053 + int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id) 1054 + { 1055 + struct prestera_msg_bridge_req req = { 1056 + .bridge = bridge_id, 1057 + .port = port->hw_id, 1058 + .dev = port->dev_id, 1059 + }; 1060 + 1061 + return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE, 1062 + &req.cmd, sizeof(req)); 974 1063 } 975 1064 976 1065 int prestera_hw_rxtx_init(struct prestera_switch *sw,
+48
drivers/net/ethernet/marvell/prestera/prestera_hw.h
··· 6 6 7 7 #include <linux/types.h> 8 8 9 + enum prestera_accept_frm_type { 10 + PRESTERA_ACCEPT_FRAME_TYPE_TAGGED, 11 + PRESTERA_ACCEPT_FRAME_TYPE_UNTAGGED, 12 + PRESTERA_ACCEPT_FRAME_TYPE_ALL, 13 + }; 14 + 15 + enum prestera_fdb_flush_mode { 16 + PRESTERA_FDB_FLUSH_MODE_DYNAMIC = BIT(0), 17 + PRESTERA_FDB_FLUSH_MODE_STATIC = BIT(1), 18 + PRESTERA_FDB_FLUSH_MODE_ALL = PRESTERA_FDB_FLUSH_MODE_DYNAMIC 19 + | PRESTERA_FDB_FLUSH_MODE_STATIC, 20 + }; 21 + 9 22 enum { 10 23 PRESTERA_LINK_MODE_10baseT_Half, 11 24 PRESTERA_LINK_MODE_10baseT_Full, ··· 82 69 PRESTERA_PORT_DUPLEX_FULL, 83 70 }; 84 71 72 + enum { 73 + PRESTERA_STP_DISABLED, 74 + PRESTERA_STP_BLOCK_LISTEN, 75 + PRESTERA_STP_LEARN, 76 + PRESTERA_STP_FORWARD, 77 + }; 78 + 85 79 struct prestera_switch; 86 80 struct prestera_port; 87 81 struct prestera_port_stats; ··· 104 84 /* Switch API */ 105 85 int prestera_hw_switch_init(struct prestera_switch *sw); 106 86 void prestera_hw_switch_fini(struct prestera_switch *sw); 87 + int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms); 107 88 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac); 108 89 109 90 /* Port API */ ··· 137 116 u8 *admin_mode); 138 117 int prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode); 139 118 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed); 119 + int prestera_hw_port_learning_set(struct prestera_port *port, bool enable); 120 + int prestera_hw_port_flood_set(struct prestera_port *port, bool flood); 121 + int prestera_hw_port_accept_frm_type(struct prestera_port *port, 122 + enum prestera_accept_frm_type type); 123 + /* Vlan API */ 124 + int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid); 125 + int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid); 126 + int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid, 127 + bool is_member, bool untagged); 128 + int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid); 129 + int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state); 130 + 131 + /* FDB API */ 132 + int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac, 133 + u16 vid, bool dynamic); 134 + int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac, 135 + u16 vid); 136 + int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode); 137 + int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode); 138 + int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid, 139 + u32 mode); 140 + 141 + /* Bridge API */ 142 + int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id); 143 + int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id); 144 + int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id); 145 + int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id); 140 146 141 147 /* Event handlers */ 142 148 int prestera_hw_event_handler_register(struct prestera_switch *sw,
+107 -3
drivers/net/ethernet/marvell/prestera/prestera_main.c
··· 14 14 #include "prestera_rxtx.h" 15 15 #include "prestera_devlink.h" 16 16 #include "prestera_ethtool.h" 17 + #include "prestera_switchdev.h" 17 18 18 19 #define PRESTERA_MTU_DEFAULT 1536 19 20 ··· 23 22 #define PRESTERA_MAC_ADDR_NUM_MAX 255 24 23 25 24 static struct workqueue_struct *prestera_wq; 25 + 26 + int prestera_port_pvid_set(struct prestera_port *port, u16 vid) 27 + { 28 + enum prestera_accept_frm_type frm_type; 29 + int err; 30 + 31 + frm_type = PRESTERA_ACCEPT_FRAME_TYPE_TAGGED; 32 + 33 + if (vid) { 34 + err = prestera_hw_vlan_port_vid_set(port, vid); 35 + if (err) 36 + return err; 37 + 38 + frm_type = PRESTERA_ACCEPT_FRAME_TYPE_ALL; 39 + } 40 + 41 + err = prestera_hw_port_accept_frm_type(port, frm_type); 42 + if (err && frm_type == PRESTERA_ACCEPT_FRAME_TYPE_ALL) 43 + prestera_hw_vlan_port_vid_set(port, port->pvid); 44 + 45 + port->pvid = vid; 46 + return 0; 47 + } 26 48 27 49 struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw, 28 50 u32 dev_id, u32 hw_id) ··· 62 38 return port; 63 39 } 64 40 65 - static struct prestera_port *prestera_find_port(struct prestera_switch *sw, 66 - u32 id) 41 + struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id) 67 42 { 68 43 struct prestera_port *port = NULL; 69 44 ··· 284 261 285 262 port = netdev_priv(dev); 286 263 264 + INIT_LIST_HEAD(&port->vlans_list); 265 + port->pvid = PRESTERA_DEFAULT_VID; 287 266 port->dev = dev; 288 267 port->id = id; 289 268 port->sw = sw; ··· 477 452 return prestera_hw_switch_mac_set(sw, sw->base_mac); 478 453 } 479 454 455 + bool prestera_netdev_check(const struct net_device *dev) 456 + { 457 + return dev->netdev_ops == &prestera_netdev_ops; 458 + } 459 + 460 + static int prestera_lower_dev_walk(struct net_device *dev, void *data) 461 + { 462 + struct prestera_port **pport = data; 463 + 464 + if (prestera_netdev_check(dev)) { 465 + *pport = netdev_priv(dev); 466 + return 1; 467 + } 468 + 469 + return 0; 470 + } 471 + 472 + struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev) 473 + { 474 + struct prestera_port *port = NULL; 475 + 476 + if (prestera_netdev_check(dev)) 477 + return netdev_priv(dev); 478 + 479 + netdev_walk_all_lower_dev(dev, prestera_lower_dev_walk, &port); 480 + 481 + return port; 482 + } 483 + 484 + static int prestera_netdev_port_event(struct net_device *dev, 485 + unsigned long event, void *ptr) 486 + { 487 + switch (event) { 488 + case NETDEV_PRECHANGEUPPER: 489 + case NETDEV_CHANGEUPPER: 490 + return prestera_bridge_port_event(dev, event, ptr); 491 + default: 492 + return 0; 493 + } 494 + } 495 + 496 + static int prestera_netdev_event_handler(struct notifier_block *nb, 497 + unsigned long event, void *ptr) 498 + { 499 + struct net_device *dev = netdev_notifier_info_to_dev(ptr); 500 + int err = 0; 501 + 502 + if (prestera_netdev_check(dev)) 503 + err = prestera_netdev_port_event(dev, event, ptr); 504 + 505 + return notifier_from_errno(err); 506 + } 507 + 508 + static int prestera_netdev_event_handler_register(struct prestera_switch *sw) 509 + { 510 + sw->netdev_nb.notifier_call = prestera_netdev_event_handler; 511 + 512 + return register_netdevice_notifier(&sw->netdev_nb); 513 + } 514 + 515 + static void prestera_netdev_event_handler_unregister(struct prestera_switch *sw) 516 + { 517 + unregister_netdevice_notifier(&sw->netdev_nb); 518 + } 519 + 480 520 static int prestera_switch_init(struct prestera_switch *sw) 481 521 { 482 522 int err; ··· 559 469 if (err) 560 470 return err; 561 471 562 - err = prestera_rxtx_switch_init(sw); 472 + err = prestera_netdev_event_handler_register(sw); 563 473 if (err) 564 474 return err; 475 + 476 + err = prestera_switchdev_init(sw); 477 + if (err) 478 + goto err_swdev_register; 479 + 480 + err = prestera_rxtx_switch_init(sw); 481 + if (err) 482 + goto err_rxtx_register; 565 483 566 484 err = prestera_event_handlers_register(sw); 567 485 if (err) ··· 591 493 prestera_event_handlers_unregister(sw); 592 494 err_handlers_register: 593 495 prestera_rxtx_switch_fini(sw); 496 + err_rxtx_register: 497 + prestera_switchdev_fini(sw); 498 + err_swdev_register: 499 + prestera_netdev_event_handler_unregister(sw); 594 500 prestera_hw_switch_fini(sw); 595 501 596 502 return err; ··· 606 504 prestera_devlink_unregister(sw); 607 505 prestera_event_handlers_unregister(sw); 608 506 prestera_rxtx_switch_fini(sw); 507 + prestera_switchdev_fini(sw); 508 + prestera_netdev_event_handler_unregister(sw); 609 509 prestera_hw_switch_fini(sw); 610 510 } 611 511
+1277
drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
··· 1 + // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 + /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */ 3 + 4 + #include <linux/if_bridge.h> 5 + #include <linux/if_vlan.h> 6 + #include <linux/kernel.h> 7 + #include <linux/module.h> 8 + #include <linux/notifier.h> 9 + #include <net/netevent.h> 10 + #include <net/switchdev.h> 11 + 12 + #include "prestera.h" 13 + #include "prestera_hw.h" 14 + #include "prestera_switchdev.h" 15 + 16 + #define PRESTERA_VID_ALL (0xffff) 17 + 18 + #define PRESTERA_DEFAULT_AGEING_TIME_MS 300000 19 + #define PRESTERA_MAX_AGEING_TIME_MS 1000000000 20 + #define PRESTERA_MIN_AGEING_TIME_MS 32000 21 + 22 + struct prestera_fdb_event_work { 23 + struct work_struct work; 24 + struct switchdev_notifier_fdb_info fdb_info; 25 + struct net_device *dev; 26 + unsigned long event; 27 + }; 28 + 29 + struct prestera_switchdev { 30 + struct prestera_switch *sw; 31 + struct list_head bridge_list; 32 + bool bridge_8021q_exists; 33 + struct notifier_block swdev_nb_blk; 34 + struct notifier_block swdev_nb; 35 + }; 36 + 37 + struct prestera_bridge { 38 + struct list_head head; 39 + struct net_device *dev; 40 + struct prestera_switchdev *swdev; 41 + struct list_head port_list; 42 + bool vlan_enabled; 43 + u16 bridge_id; 44 + }; 45 + 46 + struct prestera_bridge_port { 47 + struct list_head head; 48 + struct net_device *dev; 49 + struct prestera_bridge *bridge; 50 + struct list_head vlan_list; 51 + refcount_t ref_count; 52 + unsigned long flags; 53 + u8 stp_state; 54 + }; 55 + 56 + struct prestera_bridge_vlan { 57 + struct list_head head; 58 + struct list_head port_vlan_list; 59 + u16 vid; 60 + }; 61 + 62 + struct prestera_port_vlan { 63 + struct list_head br_vlan_head; 64 + struct list_head port_head; 65 + struct prestera_port *port; 66 + struct prestera_bridge_port *br_port; 67 + u16 vid; 68 + }; 69 + 70 + static struct workqueue_struct *swdev_wq; 71 + 72 + static void prestera_bridge_port_put(struct prestera_bridge_port *br_port); 73 + 74 + static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid, 75 + u8 state); 76 + 77 + static struct prestera_bridge_vlan * 78 + prestera_bridge_vlan_create(struct prestera_bridge_port *br_port, u16 vid) 79 + { 80 + struct prestera_bridge_vlan *br_vlan; 81 + 82 + br_vlan = kzalloc(sizeof(*br_vlan), GFP_KERNEL); 83 + if (!br_vlan) 84 + return NULL; 85 + 86 + INIT_LIST_HEAD(&br_vlan->port_vlan_list); 87 + br_vlan->vid = vid; 88 + list_add(&br_vlan->head, &br_port->vlan_list); 89 + 90 + return br_vlan; 91 + } 92 + 93 + static void prestera_bridge_vlan_destroy(struct prestera_bridge_vlan *br_vlan) 94 + { 95 + list_del(&br_vlan->head); 96 + WARN_ON(!list_empty(&br_vlan->port_vlan_list)); 97 + kfree(br_vlan); 98 + } 99 + 100 + static struct prestera_bridge_vlan * 101 + prestera_bridge_vlan_by_vid(struct prestera_bridge_port *br_port, u16 vid) 102 + { 103 + struct prestera_bridge_vlan *br_vlan; 104 + 105 + list_for_each_entry(br_vlan, &br_port->vlan_list, head) { 106 + if (br_vlan->vid == vid) 107 + return br_vlan; 108 + } 109 + 110 + return NULL; 111 + } 112 + 113 + static int prestera_bridge_vlan_port_count(struct prestera_bridge *bridge, 114 + u16 vid) 115 + { 116 + struct prestera_bridge_port *br_port; 117 + struct prestera_bridge_vlan *br_vlan; 118 + int count = 0; 119 + 120 + list_for_each_entry(br_port, &bridge->port_list, head) { 121 + list_for_each_entry(br_vlan, &br_port->vlan_list, head) { 122 + if (br_vlan->vid == vid) { 123 + count += 1; 124 + break; 125 + } 126 + } 127 + } 128 + 129 + return count; 130 + } 131 + 132 + static void prestera_bridge_vlan_put(struct prestera_bridge_vlan *br_vlan) 133 + { 134 + if (list_empty(&br_vlan->port_vlan_list)) 135 + prestera_bridge_vlan_destroy(br_vlan); 136 + } 137 + 138 + static struct prestera_port_vlan * 139 + prestera_port_vlan_by_vid(struct prestera_port *port, u16 vid) 140 + { 141 + struct prestera_port_vlan *port_vlan; 142 + 143 + list_for_each_entry(port_vlan, &port->vlans_list, port_head) { 144 + if (port_vlan->vid == vid) 145 + return port_vlan; 146 + } 147 + 148 + return NULL; 149 + } 150 + 151 + static struct prestera_port_vlan * 152 + prestera_port_vlan_create(struct prestera_port *port, u16 vid, bool untagged) 153 + { 154 + struct prestera_port_vlan *port_vlan; 155 + int err; 156 + 157 + port_vlan = prestera_port_vlan_by_vid(port, vid); 158 + if (port_vlan) 159 + return ERR_PTR(-EEXIST); 160 + 161 + err = prestera_hw_vlan_port_set(port, vid, true, untagged); 162 + if (err) 163 + return ERR_PTR(err); 164 + 165 + port_vlan = kzalloc(sizeof(*port_vlan), GFP_KERNEL); 166 + if (!port_vlan) { 167 + err = -ENOMEM; 168 + goto err_port_vlan_alloc; 169 + } 170 + 171 + port_vlan->port = port; 172 + port_vlan->vid = vid; 173 + 174 + list_add(&port_vlan->port_head, &port->vlans_list); 175 + 176 + return port_vlan; 177 + 178 + err_port_vlan_alloc: 179 + prestera_hw_vlan_port_set(port, vid, false, false); 180 + return ERR_PTR(err); 181 + } 182 + 183 + static void 184 + prestera_port_vlan_bridge_leave(struct prestera_port_vlan *port_vlan) 185 + { 186 + u32 fdb_flush_mode = PRESTERA_FDB_FLUSH_MODE_DYNAMIC; 187 + struct prestera_port *port = port_vlan->port; 188 + struct prestera_bridge_vlan *br_vlan; 189 + struct prestera_bridge_port *br_port; 190 + bool last_port, last_vlan; 191 + u16 vid = port_vlan->vid; 192 + int port_count; 193 + 194 + br_port = port_vlan->br_port; 195 + port_count = prestera_bridge_vlan_port_count(br_port->bridge, vid); 196 + br_vlan = prestera_bridge_vlan_by_vid(br_port, vid); 197 + 198 + last_vlan = list_is_singular(&br_port->vlan_list); 199 + last_port = port_count == 1; 200 + 201 + if (last_vlan) 202 + prestera_hw_fdb_flush_port(port, fdb_flush_mode); 203 + else if (last_port) 204 + prestera_hw_fdb_flush_vlan(port->sw, vid, fdb_flush_mode); 205 + else 206 + prestera_hw_fdb_flush_port_vlan(port, vid, fdb_flush_mode); 207 + 208 + list_del(&port_vlan->br_vlan_head); 209 + prestera_bridge_vlan_put(br_vlan); 210 + prestera_bridge_port_put(br_port); 211 + port_vlan->br_port = NULL; 212 + } 213 + 214 + static void prestera_port_vlan_destroy(struct prestera_port_vlan *port_vlan) 215 + { 216 + struct prestera_port *port = port_vlan->port; 217 + u16 vid = port_vlan->vid; 218 + 219 + if (port_vlan->br_port) 220 + prestera_port_vlan_bridge_leave(port_vlan); 221 + 222 + prestera_hw_vlan_port_set(port, vid, false, false); 223 + list_del(&port_vlan->port_head); 224 + kfree(port_vlan); 225 + } 226 + 227 + static struct prestera_bridge * 228 + prestera_bridge_create(struct prestera_switchdev *swdev, struct net_device *dev) 229 + { 230 + bool vlan_enabled = br_vlan_enabled(dev); 231 + struct prestera_bridge *bridge; 232 + u16 bridge_id; 233 + int err; 234 + 235 + if (vlan_enabled && swdev->bridge_8021q_exists) { 236 + netdev_err(dev, "Only one VLAN-aware bridge is supported\n"); 237 + return ERR_PTR(-EINVAL); 238 + } 239 + 240 + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); 241 + if (!bridge) 242 + return ERR_PTR(-ENOMEM); 243 + 244 + if (vlan_enabled) { 245 + swdev->bridge_8021q_exists = true; 246 + } else { 247 + err = prestera_hw_bridge_create(swdev->sw, &bridge_id); 248 + if (err) { 249 + kfree(bridge); 250 + return ERR_PTR(err); 251 + } 252 + 253 + bridge->bridge_id = bridge_id; 254 + } 255 + 256 + bridge->vlan_enabled = vlan_enabled; 257 + bridge->swdev = swdev; 258 + bridge->dev = dev; 259 + 260 + INIT_LIST_HEAD(&bridge->port_list); 261 + 262 + list_add(&bridge->head, &swdev->bridge_list); 263 + 264 + return bridge; 265 + } 266 + 267 + static void prestera_bridge_destroy(struct prestera_bridge *bridge) 268 + { 269 + struct prestera_switchdev *swdev = bridge->swdev; 270 + 271 + list_del(&bridge->head); 272 + 273 + if (bridge->vlan_enabled) 274 + swdev->bridge_8021q_exists = false; 275 + else 276 + prestera_hw_bridge_delete(swdev->sw, bridge->bridge_id); 277 + 278 + WARN_ON(!list_empty(&bridge->port_list)); 279 + kfree(bridge); 280 + } 281 + 282 + static void prestera_bridge_put(struct prestera_bridge *bridge) 283 + { 284 + if (list_empty(&bridge->port_list)) 285 + prestera_bridge_destroy(bridge); 286 + } 287 + 288 + static 289 + struct prestera_bridge *prestera_bridge_by_dev(struct prestera_switchdev *swdev, 290 + const struct net_device *dev) 291 + { 292 + struct prestera_bridge *bridge; 293 + 294 + list_for_each_entry(bridge, &swdev->bridge_list, head) 295 + if (bridge->dev == dev) 296 + return bridge; 297 + 298 + return NULL; 299 + } 300 + 301 + static struct prestera_bridge_port * 302 + __prestera_bridge_port_by_dev(struct prestera_bridge *bridge, 303 + struct net_device *dev) 304 + { 305 + struct prestera_bridge_port *br_port; 306 + 307 + list_for_each_entry(br_port, &bridge->port_list, head) { 308 + if (br_port->dev == dev) 309 + return br_port; 310 + } 311 + 312 + return NULL; 313 + } 314 + 315 + static struct prestera_bridge_port * 316 + prestera_bridge_port_by_dev(struct prestera_switchdev *swdev, 317 + struct net_device *dev) 318 + { 319 + struct net_device *br_dev = netdev_master_upper_dev_get(dev); 320 + struct prestera_bridge *bridge; 321 + 322 + if (!br_dev) 323 + return NULL; 324 + 325 + bridge = prestera_bridge_by_dev(swdev, br_dev); 326 + if (!bridge) 327 + return NULL; 328 + 329 + return __prestera_bridge_port_by_dev(bridge, dev); 330 + } 331 + 332 + static struct prestera_bridge_port * 333 + prestera_bridge_port_create(struct prestera_bridge *bridge, 334 + struct net_device *dev) 335 + { 336 + struct prestera_bridge_port *br_port; 337 + 338 + br_port = kzalloc(sizeof(*br_port), GFP_KERNEL); 339 + if (!br_port) 340 + return NULL; 341 + 342 + br_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC | 343 + BR_MCAST_FLOOD; 344 + br_port->stp_state = BR_STATE_DISABLED; 345 + refcount_set(&br_port->ref_count, 1); 346 + br_port->bridge = bridge; 347 + br_port->dev = dev; 348 + 349 + INIT_LIST_HEAD(&br_port->vlan_list); 350 + list_add(&br_port->head, &bridge->port_list); 351 + 352 + return br_port; 353 + } 354 + 355 + static void 356 + prestera_bridge_port_destroy(struct prestera_bridge_port *br_port) 357 + { 358 + list_del(&br_port->head); 359 + WARN_ON(!list_empty(&br_port->vlan_list)); 360 + kfree(br_port); 361 + } 362 + 363 + static void prestera_bridge_port_get(struct prestera_bridge_port *br_port) 364 + { 365 + refcount_inc(&br_port->ref_count); 366 + } 367 + 368 + static void prestera_bridge_port_put(struct prestera_bridge_port *br_port) 369 + { 370 + struct prestera_bridge *bridge = br_port->bridge; 371 + 372 + if (refcount_dec_and_test(&br_port->ref_count)) { 373 + prestera_bridge_port_destroy(br_port); 374 + prestera_bridge_put(bridge); 375 + } 376 + } 377 + 378 + static struct prestera_bridge_port * 379 + prestera_bridge_port_add(struct prestera_bridge *bridge, struct net_device *dev) 380 + { 381 + struct prestera_bridge_port *br_port; 382 + 383 + br_port = __prestera_bridge_port_by_dev(bridge, dev); 384 + if (br_port) { 385 + prestera_bridge_port_get(br_port); 386 + return br_port; 387 + } 388 + 389 + br_port = prestera_bridge_port_create(bridge, dev); 390 + if (!br_port) 391 + return ERR_PTR(-ENOMEM); 392 + 393 + return br_port; 394 + } 395 + 396 + static int 397 + prestera_bridge_1d_port_join(struct prestera_bridge_port *br_port) 398 + { 399 + struct prestera_port *port = netdev_priv(br_port->dev); 400 + struct prestera_bridge *bridge = br_port->bridge; 401 + int err; 402 + 403 + err = prestera_hw_bridge_port_add(port, bridge->bridge_id); 404 + if (err) 405 + return err; 406 + 407 + err = prestera_hw_port_flood_set(port, br_port->flags & BR_FLOOD); 408 + if (err) 409 + goto err_port_flood_set; 410 + 411 + err = prestera_hw_port_learning_set(port, br_port->flags & BR_LEARNING); 412 + if (err) 413 + goto err_port_learning_set; 414 + 415 + return 0; 416 + 417 + err_port_learning_set: 418 + prestera_hw_port_flood_set(port, false); 419 + err_port_flood_set: 420 + prestera_hw_bridge_port_delete(port, bridge->bridge_id); 421 + 422 + return err; 423 + } 424 + 425 + static int prestera_port_bridge_join(struct prestera_port *port, 426 + struct net_device *upper) 427 + { 428 + struct prestera_switchdev *swdev = port->sw->swdev; 429 + struct prestera_bridge_port *br_port; 430 + struct prestera_bridge *bridge; 431 + int err; 432 + 433 + bridge = prestera_bridge_by_dev(swdev, upper); 434 + if (!bridge) { 435 + bridge = prestera_bridge_create(swdev, upper); 436 + if (IS_ERR(bridge)) 437 + return PTR_ERR(bridge); 438 + } 439 + 440 + br_port = prestera_bridge_port_add(bridge, port->dev); 441 + if (IS_ERR(br_port)) { 442 + err = PTR_ERR(br_port); 443 + goto err_brport_create; 444 + } 445 + 446 + if (bridge->vlan_enabled) 447 + return 0; 448 + 449 + err = prestera_bridge_1d_port_join(br_port); 450 + if (err) 451 + goto err_port_join; 452 + 453 + return 0; 454 + 455 + err_port_join: 456 + prestera_bridge_port_put(br_port); 457 + err_brport_create: 458 + prestera_bridge_put(bridge); 459 + return err; 460 + } 461 + 462 + static void prestera_bridge_1q_port_leave(struct prestera_bridge_port *br_port) 463 + { 464 + struct prestera_port *port = netdev_priv(br_port->dev); 465 + 466 + prestera_hw_fdb_flush_port(port, PRESTERA_FDB_FLUSH_MODE_ALL); 467 + prestera_port_pvid_set(port, PRESTERA_DEFAULT_VID); 468 + } 469 + 470 + static void prestera_bridge_1d_port_leave(struct prestera_bridge_port *br_port) 471 + { 472 + struct prestera_port *port = netdev_priv(br_port->dev); 473 + 474 + prestera_hw_fdb_flush_port(port, PRESTERA_FDB_FLUSH_MODE_ALL); 475 + prestera_hw_bridge_port_delete(port, br_port->bridge->bridge_id); 476 + } 477 + 478 + static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid, 479 + u8 state) 480 + { 481 + u8 hw_state = state; 482 + 483 + switch (state) { 484 + case BR_STATE_DISABLED: 485 + hw_state = PRESTERA_STP_DISABLED; 486 + break; 487 + 488 + case BR_STATE_BLOCKING: 489 + case BR_STATE_LISTENING: 490 + hw_state = PRESTERA_STP_BLOCK_LISTEN; 491 + break; 492 + 493 + case BR_STATE_LEARNING: 494 + hw_state = PRESTERA_STP_LEARN; 495 + break; 496 + 497 + case BR_STATE_FORWARDING: 498 + hw_state = PRESTERA_STP_FORWARD; 499 + break; 500 + 501 + default: 502 + return -EINVAL; 503 + } 504 + 505 + return prestera_hw_vlan_port_stp_set(port, vid, hw_state); 506 + } 507 + 508 + static void prestera_port_bridge_leave(struct prestera_port *port, 509 + struct net_device *upper) 510 + { 511 + struct prestera_switchdev *swdev = port->sw->swdev; 512 + struct prestera_bridge_port *br_port; 513 + struct prestera_bridge *bridge; 514 + 515 + bridge = prestera_bridge_by_dev(swdev, upper); 516 + if (!bridge) 517 + return; 518 + 519 + br_port = __prestera_bridge_port_by_dev(bridge, port->dev); 520 + if (!br_port) 521 + return; 522 + 523 + bridge = br_port->bridge; 524 + 525 + if (bridge->vlan_enabled) 526 + prestera_bridge_1q_port_leave(br_port); 527 + else 528 + prestera_bridge_1d_port_leave(br_port); 529 + 530 + prestera_hw_port_learning_set(port, false); 531 + prestera_hw_port_flood_set(port, false); 532 + prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING); 533 + prestera_bridge_port_put(br_port); 534 + } 535 + 536 + int prestera_bridge_port_event(struct net_device *dev, unsigned long event, 537 + void *ptr) 538 + { 539 + struct netdev_notifier_changeupper_info *info = ptr; 540 + struct netlink_ext_ack *extack; 541 + struct prestera_port *port; 542 + struct net_device *upper; 543 + int err; 544 + 545 + extack = netdev_notifier_info_to_extack(&info->info); 546 + port = netdev_priv(dev); 547 + upper = info->upper_dev; 548 + 549 + switch (event) { 550 + case NETDEV_PRECHANGEUPPER: 551 + if (!netif_is_bridge_master(upper)) { 552 + NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type"); 553 + return -EINVAL; 554 + } 555 + 556 + if (!info->linking) 557 + break; 558 + 559 + if (netdev_has_any_upper_dev(upper)) { 560 + NL_SET_ERR_MSG_MOD(extack, "Upper device is already enslaved"); 561 + return -EINVAL; 562 + } 563 + break; 564 + 565 + case NETDEV_CHANGEUPPER: 566 + if (!netif_is_bridge_master(upper)) 567 + break; 568 + 569 + if (info->linking) { 570 + err = prestera_port_bridge_join(port, upper); 571 + if (err) 572 + return err; 573 + } else { 574 + prestera_port_bridge_leave(port, upper); 575 + } 576 + break; 577 + } 578 + 579 + return 0; 580 + } 581 + 582 + static int prestera_port_attr_br_flags_set(struct prestera_port *port, 583 + struct switchdev_trans *trans, 584 + struct net_device *dev, 585 + unsigned long flags) 586 + { 587 + struct prestera_bridge_port *br_port; 588 + int err; 589 + 590 + if (switchdev_trans_ph_prepare(trans)) 591 + return 0; 592 + 593 + br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev); 594 + if (!br_port) 595 + return 0; 596 + 597 + err = prestera_hw_port_flood_set(port, flags & BR_FLOOD); 598 + if (err) 599 + return err; 600 + 601 + err = prestera_hw_port_learning_set(port, flags & BR_LEARNING); 602 + if (err) 603 + return err; 604 + 605 + memcpy(&br_port->flags, &flags, sizeof(flags)); 606 + 607 + return 0; 608 + } 609 + 610 + static int prestera_port_attr_br_ageing_set(struct prestera_port *port, 611 + struct switchdev_trans *trans, 612 + unsigned long ageing_clock_t) 613 + { 614 + unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t); 615 + u32 ageing_time_ms = jiffies_to_msecs(ageing_jiffies); 616 + struct prestera_switch *sw = port->sw; 617 + 618 + if (switchdev_trans_ph_prepare(trans)) { 619 + if (ageing_time_ms < PRESTERA_MIN_AGEING_TIME_MS || 620 + ageing_time_ms > PRESTERA_MAX_AGEING_TIME_MS) 621 + return -ERANGE; 622 + else 623 + return 0; 624 + } 625 + 626 + return prestera_hw_switch_ageing_set(sw, ageing_time_ms); 627 + } 628 + 629 + static int prestera_port_attr_br_vlan_set(struct prestera_port *port, 630 + struct switchdev_trans *trans, 631 + struct net_device *dev, 632 + bool vlan_enabled) 633 + { 634 + struct prestera_switch *sw = port->sw; 635 + struct prestera_bridge *bridge; 636 + 637 + if (!switchdev_trans_ph_prepare(trans)) 638 + return 0; 639 + 640 + bridge = prestera_bridge_by_dev(sw->swdev, dev); 641 + if (WARN_ON(!bridge)) 642 + return -EINVAL; 643 + 644 + if (bridge->vlan_enabled == vlan_enabled) 645 + return 0; 646 + 647 + netdev_err(bridge->dev, "VLAN filtering can't be changed for existing bridge\n"); 648 + 649 + return -EINVAL; 650 + } 651 + 652 + static int prestera_port_bridge_vlan_stp_set(struct prestera_port *port, 653 + struct prestera_bridge_vlan *br_vlan, 654 + u8 state) 655 + { 656 + struct prestera_port_vlan *port_vlan; 657 + 658 + list_for_each_entry(port_vlan, &br_vlan->port_vlan_list, br_vlan_head) { 659 + if (port_vlan->port != port) 660 + continue; 661 + 662 + return prestera_port_vid_stp_set(port, br_vlan->vid, state); 663 + } 664 + 665 + return 0; 666 + } 667 + 668 + static int presterar_port_attr_stp_state_set(struct prestera_port *port, 669 + struct switchdev_trans *trans, 670 + struct net_device *dev, 671 + u8 state) 672 + { 673 + struct prestera_bridge_port *br_port; 674 + struct prestera_bridge_vlan *br_vlan; 675 + int err; 676 + u16 vid; 677 + 678 + if (switchdev_trans_ph_prepare(trans)) 679 + return 0; 680 + 681 + br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev); 682 + if (!br_port) 683 + return 0; 684 + 685 + if (!br_port->bridge->vlan_enabled) { 686 + vid = br_port->bridge->bridge_id; 687 + err = prestera_port_vid_stp_set(port, vid, state); 688 + if (err) 689 + goto err_port_stp_set; 690 + } else { 691 + list_for_each_entry(br_vlan, &br_port->vlan_list, head) { 692 + err = prestera_port_bridge_vlan_stp_set(port, br_vlan, 693 + state); 694 + if (err) 695 + goto err_port_vlan_stp_set; 696 + } 697 + } 698 + 699 + br_port->stp_state = state; 700 + 701 + return 0; 702 + 703 + err_port_vlan_stp_set: 704 + list_for_each_entry_continue_reverse(br_vlan, &br_port->vlan_list, head) 705 + prestera_port_bridge_vlan_stp_set(port, br_vlan, br_port->stp_state); 706 + return err; 707 + 708 + err_port_stp_set: 709 + prestera_port_vid_stp_set(port, vid, br_port->stp_state); 710 + 711 + return err; 712 + } 713 + 714 + static int prestera_port_obj_attr_set(struct net_device *dev, 715 + const struct switchdev_attr *attr, 716 + struct switchdev_trans *trans) 717 + { 718 + struct prestera_port *port = netdev_priv(dev); 719 + int err = 0; 720 + 721 + switch (attr->id) { 722 + case SWITCHDEV_ATTR_ID_PORT_STP_STATE: 723 + err = presterar_port_attr_stp_state_set(port, trans, 724 + attr->orig_dev, 725 + attr->u.stp_state); 726 + break; 727 + case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: 728 + if (attr->u.brport_flags & 729 + ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) 730 + err = -EINVAL; 731 + break; 732 + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: 733 + err = prestera_port_attr_br_flags_set(port, trans, 734 + attr->orig_dev, 735 + attr->u.brport_flags); 736 + break; 737 + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 738 + err = prestera_port_attr_br_ageing_set(port, trans, 739 + attr->u.ageing_time); 740 + break; 741 + case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 742 + err = prestera_port_attr_br_vlan_set(port, trans, 743 + attr->orig_dev, 744 + attr->u.vlan_filtering); 745 + break; 746 + default: 747 + err = -EOPNOTSUPP; 748 + } 749 + 750 + return err; 751 + } 752 + 753 + static void 754 + prestera_fdb_offload_notify(struct prestera_port *port, 755 + struct switchdev_notifier_fdb_info *info) 756 + { 757 + struct switchdev_notifier_fdb_info send_info; 758 + 759 + send_info.addr = info->addr; 760 + send_info.vid = info->vid; 761 + send_info.offloaded = true; 762 + 763 + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, port->dev, 764 + &send_info.info, NULL); 765 + } 766 + 767 + static int prestera_port_fdb_set(struct prestera_port *port, 768 + struct switchdev_notifier_fdb_info *fdb_info, 769 + bool adding) 770 + { 771 + struct prestera_switch *sw = port->sw; 772 + struct prestera_bridge_port *br_port; 773 + struct prestera_bridge *bridge; 774 + int err; 775 + u16 vid; 776 + 777 + br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev); 778 + if (!br_port) 779 + return -EINVAL; 780 + 781 + bridge = br_port->bridge; 782 + 783 + if (bridge->vlan_enabled) 784 + vid = fdb_info->vid; 785 + else 786 + vid = bridge->bridge_id; 787 + 788 + if (adding) 789 + err = prestera_hw_fdb_add(port, fdb_info->addr, vid, false); 790 + else 791 + err = prestera_hw_fdb_del(port, fdb_info->addr, vid); 792 + 793 + return err; 794 + } 795 + 796 + static void prestera_fdb_event_work(struct work_struct *work) 797 + { 798 + struct switchdev_notifier_fdb_info *fdb_info; 799 + struct prestera_fdb_event_work *swdev_work; 800 + struct prestera_port *port; 801 + struct net_device *dev; 802 + int err; 803 + 804 + swdev_work = container_of(work, struct prestera_fdb_event_work, work); 805 + dev = swdev_work->dev; 806 + 807 + rtnl_lock(); 808 + 809 + port = prestera_port_dev_lower_find(dev); 810 + if (!port) 811 + goto out_unlock; 812 + 813 + switch (swdev_work->event) { 814 + case SWITCHDEV_FDB_ADD_TO_DEVICE: 815 + fdb_info = &swdev_work->fdb_info; 816 + if (!fdb_info->added_by_user) 817 + break; 818 + 819 + err = prestera_port_fdb_set(port, fdb_info, true); 820 + if (err) 821 + break; 822 + 823 + prestera_fdb_offload_notify(port, fdb_info); 824 + break; 825 + 826 + case SWITCHDEV_FDB_DEL_TO_DEVICE: 827 + fdb_info = &swdev_work->fdb_info; 828 + prestera_port_fdb_set(port, fdb_info, false); 829 + break; 830 + } 831 + 832 + out_unlock: 833 + rtnl_unlock(); 834 + 835 + kfree(swdev_work->fdb_info.addr); 836 + kfree(swdev_work); 837 + dev_put(dev); 838 + } 839 + 840 + static int prestera_switchdev_event(struct notifier_block *unused, 841 + unsigned long event, void *ptr) 842 + { 843 + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 844 + struct switchdev_notifier_fdb_info *fdb_info; 845 + struct switchdev_notifier_info *info = ptr; 846 + struct prestera_fdb_event_work *swdev_work; 847 + struct net_device *upper; 848 + int err; 849 + 850 + if (event == SWITCHDEV_PORT_ATTR_SET) { 851 + err = switchdev_handle_port_attr_set(dev, ptr, 852 + prestera_netdev_check, 853 + prestera_port_obj_attr_set); 854 + return notifier_from_errno(err); 855 + } 856 + 857 + if (!prestera_netdev_check(dev)) 858 + return NOTIFY_DONE; 859 + 860 + upper = netdev_master_upper_dev_get_rcu(dev); 861 + if (!upper) 862 + return NOTIFY_DONE; 863 + 864 + if (!netif_is_bridge_master(upper)) 865 + return NOTIFY_DONE; 866 + 867 + swdev_work = kzalloc(sizeof(*swdev_work), GFP_ATOMIC); 868 + if (!swdev_work) 869 + return NOTIFY_BAD; 870 + 871 + swdev_work->event = event; 872 + swdev_work->dev = dev; 873 + 874 + switch (event) { 875 + case SWITCHDEV_FDB_ADD_TO_DEVICE: 876 + case SWITCHDEV_FDB_DEL_TO_DEVICE: 877 + fdb_info = container_of(info, 878 + struct switchdev_notifier_fdb_info, 879 + info); 880 + 881 + INIT_WORK(&swdev_work->work, prestera_fdb_event_work); 882 + memcpy(&swdev_work->fdb_info, ptr, 883 + sizeof(swdev_work->fdb_info)); 884 + 885 + swdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); 886 + if (!swdev_work->fdb_info.addr) 887 + goto out_bad; 888 + 889 + ether_addr_copy((u8 *)swdev_work->fdb_info.addr, 890 + fdb_info->addr); 891 + dev_hold(dev); 892 + break; 893 + 894 + default: 895 + kfree(swdev_work); 896 + return NOTIFY_DONE; 897 + } 898 + 899 + queue_work(swdev_wq, &swdev_work->work); 900 + return NOTIFY_DONE; 901 + 902 + out_bad: 903 + kfree(swdev_work); 904 + return NOTIFY_BAD; 905 + } 906 + 907 + static int 908 + prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan, 909 + struct prestera_bridge_port *br_port) 910 + { 911 + struct prestera_port *port = port_vlan->port; 912 + struct prestera_bridge_vlan *br_vlan; 913 + u16 vid = port_vlan->vid; 914 + int err; 915 + 916 + if (port_vlan->br_port) 917 + return 0; 918 + 919 + err = prestera_hw_port_flood_set(port, br_port->flags & BR_FLOOD); 920 + if (err) 921 + return err; 922 + 923 + err = prestera_hw_port_learning_set(port, br_port->flags & BR_LEARNING); 924 + if (err) 925 + goto err_port_learning_set; 926 + 927 + err = prestera_port_vid_stp_set(port, vid, br_port->stp_state); 928 + if (err) 929 + goto err_port_vid_stp_set; 930 + 931 + br_vlan = prestera_bridge_vlan_by_vid(br_port, vid); 932 + if (!br_vlan) { 933 + br_vlan = prestera_bridge_vlan_create(br_port, vid); 934 + if (!br_vlan) { 935 + err = -ENOMEM; 936 + goto err_bridge_vlan_get; 937 + } 938 + } 939 + 940 + list_add(&port_vlan->br_vlan_head, &br_vlan->port_vlan_list); 941 + 942 + prestera_bridge_port_get(br_port); 943 + port_vlan->br_port = br_port; 944 + 945 + return 0; 946 + 947 + err_bridge_vlan_get: 948 + prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING); 949 + err_port_vid_stp_set: 950 + prestera_hw_port_learning_set(port, false); 951 + err_port_learning_set: 952 + return err; 953 + } 954 + 955 + static int 956 + prestera_bridge_port_vlan_add(struct prestera_port *port, 957 + struct prestera_bridge_port *br_port, 958 + u16 vid, bool is_untagged, bool is_pvid, 959 + struct netlink_ext_ack *extack) 960 + { 961 + struct prestera_port_vlan *port_vlan; 962 + u16 old_pvid = port->pvid; 963 + u16 pvid; 964 + int err; 965 + 966 + if (is_pvid) 967 + pvid = vid; 968 + else 969 + pvid = port->pvid == vid ? 0 : port->pvid; 970 + 971 + port_vlan = prestera_port_vlan_by_vid(port, vid); 972 + if (port_vlan && port_vlan->br_port != br_port) 973 + return -EEXIST; 974 + 975 + if (!port_vlan) { 976 + port_vlan = prestera_port_vlan_create(port, vid, is_untagged); 977 + if (IS_ERR(port_vlan)) 978 + return PTR_ERR(port_vlan); 979 + } else { 980 + err = prestera_hw_vlan_port_set(port, vid, true, is_untagged); 981 + if (err) 982 + goto err_port_vlan_set; 983 + } 984 + 985 + err = prestera_port_pvid_set(port, pvid); 986 + if (err) 987 + goto err_port_pvid_set; 988 + 989 + err = prestera_port_vlan_bridge_join(port_vlan, br_port); 990 + if (err) 991 + goto err_port_vlan_bridge_join; 992 + 993 + return 0; 994 + 995 + err_port_vlan_bridge_join: 996 + prestera_port_pvid_set(port, old_pvid); 997 + err_port_pvid_set: 998 + prestera_hw_vlan_port_set(port, vid, false, false); 999 + err_port_vlan_set: 1000 + prestera_port_vlan_destroy(port_vlan); 1001 + 1002 + return err; 1003 + } 1004 + 1005 + static void 1006 + prestera_bridge_port_vlan_del(struct prestera_port *port, 1007 + struct prestera_bridge_port *br_port, u16 vid) 1008 + { 1009 + u16 pvid = port->pvid == vid ? 0 : port->pvid; 1010 + struct prestera_port_vlan *port_vlan; 1011 + 1012 + port_vlan = prestera_port_vlan_by_vid(port, vid); 1013 + if (WARN_ON(!port_vlan)) 1014 + return; 1015 + 1016 + prestera_port_vlan_bridge_leave(port_vlan); 1017 + prestera_port_pvid_set(port, pvid); 1018 + prestera_port_vlan_destroy(port_vlan); 1019 + } 1020 + 1021 + static int prestera_port_vlans_add(struct prestera_port *port, 1022 + const struct switchdev_obj_port_vlan *vlan, 1023 + struct switchdev_trans *trans, 1024 + struct netlink_ext_ack *extack) 1025 + { 1026 + bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 1027 + bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 1028 + struct net_device *dev = vlan->obj.orig_dev; 1029 + struct prestera_bridge_port *br_port; 1030 + struct prestera_switch *sw = port->sw; 1031 + struct prestera_bridge *bridge; 1032 + u16 vid; 1033 + 1034 + if (netif_is_bridge_master(dev)) 1035 + return 0; 1036 + 1037 + if (switchdev_trans_ph_commit(trans)) 1038 + return 0; 1039 + 1040 + br_port = prestera_bridge_port_by_dev(sw->swdev, dev); 1041 + if (WARN_ON(!br_port)) 1042 + return -EINVAL; 1043 + 1044 + bridge = br_port->bridge; 1045 + if (!bridge->vlan_enabled) 1046 + return 0; 1047 + 1048 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 1049 + int err; 1050 + 1051 + err = prestera_bridge_port_vlan_add(port, br_port, 1052 + vid, flag_untagged, 1053 + flag_pvid, extack); 1054 + if (err) 1055 + return err; 1056 + } 1057 + 1058 + return 0; 1059 + } 1060 + 1061 + static int prestera_port_obj_add(struct net_device *dev, 1062 + const struct switchdev_obj *obj, 1063 + struct switchdev_trans *trans, 1064 + struct netlink_ext_ack *extack) 1065 + { 1066 + struct prestera_port *port = netdev_priv(dev); 1067 + const struct switchdev_obj_port_vlan *vlan; 1068 + 1069 + switch (obj->id) { 1070 + case SWITCHDEV_OBJ_ID_PORT_VLAN: 1071 + vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); 1072 + return prestera_port_vlans_add(port, vlan, trans, extack); 1073 + default: 1074 + return -EOPNOTSUPP; 1075 + } 1076 + } 1077 + 1078 + static int prestera_port_vlans_del(struct prestera_port *port, 1079 + const struct switchdev_obj_port_vlan *vlan) 1080 + { 1081 + struct net_device *dev = vlan->obj.orig_dev; 1082 + struct prestera_bridge_port *br_port; 1083 + struct prestera_switch *sw = port->sw; 1084 + u16 vid; 1085 + 1086 + if (netif_is_bridge_master(dev)) 1087 + return -EOPNOTSUPP; 1088 + 1089 + br_port = prestera_bridge_port_by_dev(sw->swdev, dev); 1090 + if (WARN_ON(!br_port)) 1091 + return -EINVAL; 1092 + 1093 + if (!br_port->bridge->vlan_enabled) 1094 + return 0; 1095 + 1096 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) 1097 + prestera_bridge_port_vlan_del(port, br_port, vid); 1098 + 1099 + return 0; 1100 + } 1101 + 1102 + static int prestera_port_obj_del(struct net_device *dev, 1103 + const struct switchdev_obj *obj) 1104 + { 1105 + struct prestera_port *port = netdev_priv(dev); 1106 + 1107 + switch (obj->id) { 1108 + case SWITCHDEV_OBJ_ID_PORT_VLAN: 1109 + return prestera_port_vlans_del(port, SWITCHDEV_OBJ_PORT_VLAN(obj)); 1110 + default: 1111 + return -EOPNOTSUPP; 1112 + } 1113 + } 1114 + 1115 + static int prestera_switchdev_blk_event(struct notifier_block *unused, 1116 + unsigned long event, void *ptr) 1117 + { 1118 + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 1119 + int err; 1120 + 1121 + switch (event) { 1122 + case SWITCHDEV_PORT_OBJ_ADD: 1123 + err = switchdev_handle_port_obj_add(dev, ptr, 1124 + prestera_netdev_check, 1125 + prestera_port_obj_add); 1126 + break; 1127 + case SWITCHDEV_PORT_OBJ_DEL: 1128 + err = switchdev_handle_port_obj_del(dev, ptr, 1129 + prestera_netdev_check, 1130 + prestera_port_obj_del); 1131 + break; 1132 + case SWITCHDEV_PORT_ATTR_SET: 1133 + err = switchdev_handle_port_attr_set(dev, ptr, 1134 + prestera_netdev_check, 1135 + prestera_port_obj_attr_set); 1136 + break; 1137 + default: 1138 + err = -EOPNOTSUPP; 1139 + } 1140 + 1141 + return notifier_from_errno(err); 1142 + } 1143 + 1144 + static void prestera_fdb_event(struct prestera_switch *sw, 1145 + struct prestera_event *evt, void *arg) 1146 + { 1147 + struct switchdev_notifier_fdb_info info; 1148 + struct prestera_port *port; 1149 + 1150 + port = prestera_find_port(sw, evt->fdb_evt.port_id); 1151 + if (!port) 1152 + return; 1153 + 1154 + info.addr = evt->fdb_evt.data.mac; 1155 + info.vid = evt->fdb_evt.vid; 1156 + info.offloaded = true; 1157 + 1158 + rtnl_lock(); 1159 + 1160 + switch (evt->id) { 1161 + case PRESTERA_FDB_EVENT_LEARNED: 1162 + call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, 1163 + port->dev, &info.info, NULL); 1164 + break; 1165 + case PRESTERA_FDB_EVENT_AGED: 1166 + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, 1167 + port->dev, &info.info, NULL); 1168 + break; 1169 + } 1170 + 1171 + rtnl_unlock(); 1172 + } 1173 + 1174 + static int prestera_fdb_init(struct prestera_switch *sw) 1175 + { 1176 + int err; 1177 + 1178 + err = prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_FDB, 1179 + prestera_fdb_event, NULL); 1180 + if (err) 1181 + return err; 1182 + 1183 + err = prestera_hw_switch_ageing_set(sw, PRESTERA_DEFAULT_AGEING_TIME_MS); 1184 + if (err) 1185 + goto err_ageing_set; 1186 + 1187 + return 0; 1188 + 1189 + err_ageing_set: 1190 + prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_FDB, 1191 + prestera_fdb_event); 1192 + return err; 1193 + } 1194 + 1195 + static void prestera_fdb_fini(struct prestera_switch *sw) 1196 + { 1197 + prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_FDB, 1198 + prestera_fdb_event); 1199 + } 1200 + 1201 + static int prestera_switchdev_handler_init(struct prestera_switchdev *swdev) 1202 + { 1203 + int err; 1204 + 1205 + swdev->swdev_nb.notifier_call = prestera_switchdev_event; 1206 + err = register_switchdev_notifier(&swdev->swdev_nb); 1207 + if (err) 1208 + goto err_register_swdev_notifier; 1209 + 1210 + swdev->swdev_nb_blk.notifier_call = prestera_switchdev_blk_event; 1211 + err = register_switchdev_blocking_notifier(&swdev->swdev_nb_blk); 1212 + if (err) 1213 + goto err_register_blk_swdev_notifier; 1214 + 1215 + return 0; 1216 + 1217 + err_register_blk_swdev_notifier: 1218 + unregister_switchdev_notifier(&swdev->swdev_nb); 1219 + err_register_swdev_notifier: 1220 + destroy_workqueue(swdev_wq); 1221 + return err; 1222 + } 1223 + 1224 + static void prestera_switchdev_handler_fini(struct prestera_switchdev *swdev) 1225 + { 1226 + unregister_switchdev_blocking_notifier(&swdev->swdev_nb_blk); 1227 + unregister_switchdev_notifier(&swdev->swdev_nb); 1228 + } 1229 + 1230 + int prestera_switchdev_init(struct prestera_switch *sw) 1231 + { 1232 + struct prestera_switchdev *swdev; 1233 + int err; 1234 + 1235 + swdev = kzalloc(sizeof(*swdev), GFP_KERNEL); 1236 + if (!swdev) 1237 + return -ENOMEM; 1238 + 1239 + sw->swdev = swdev; 1240 + swdev->sw = sw; 1241 + 1242 + INIT_LIST_HEAD(&swdev->bridge_list); 1243 + 1244 + swdev_wq = alloc_ordered_workqueue("%s_ordered", 0, "prestera_br"); 1245 + if (!swdev_wq) { 1246 + err = -ENOMEM; 1247 + goto err_alloc_wq; 1248 + } 1249 + 1250 + err = prestera_switchdev_handler_init(swdev); 1251 + if (err) 1252 + goto err_swdev_init; 1253 + 1254 + err = prestera_fdb_init(sw); 1255 + if (err) 1256 + goto err_fdb_init; 1257 + 1258 + return 0; 1259 + 1260 + err_fdb_init: 1261 + err_swdev_init: 1262 + destroy_workqueue(swdev_wq); 1263 + err_alloc_wq: 1264 + kfree(swdev); 1265 + 1266 + return err; 1267 + } 1268 + 1269 + void prestera_switchdev_fini(struct prestera_switch *sw) 1270 + { 1271 + struct prestera_switchdev *swdev = sw->swdev; 1272 + 1273 + prestera_fdb_fini(sw); 1274 + prestera_switchdev_handler_fini(swdev); 1275 + destroy_workqueue(swdev_wq); 1276 + kfree(swdev); 1277 + }
+13
drivers/net/ethernet/marvell/prestera/prestera_switchdev.h
··· 1 + /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ 2 + /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved. */ 3 + 4 + #ifndef _PRESTERA_SWITCHDEV_H_ 5 + #define _PRESTERA_SWITCHDEV_H_ 6 + 7 + int prestera_switchdev_init(struct prestera_switch *sw); 8 + void prestera_switchdev_fini(struct prestera_switch *sw); 9 + 10 + int prestera_bridge_port_event(struct net_device *dev, unsigned long event, 11 + void *ptr); 12 + 13 + #endif /* _PRESTERA_SWITCHDEV_H_ */