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

Configure Feed

Select the types of activity you want to include in your feed.

net: dsa: vsc73xx: Add vlan filtering

This patch implements VLAN filtering for the vsc73xx driver.

After starting VLAN filtering, the switch is reconfigured from QinQ to
a simple VLAN aware mode. This is required because VSC73XX chips do not
support inner VLAN tag filtering.

Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Link: https://patch.msgid.link/20240713211620.1125910-3-paweldembicki@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Pawel Dembicki and committed by
Jakub Kicinski
6b783ded 1e5b23e5

+566 -3
+529 -3
drivers/net/dsa/vitesse-vsc73xx-core.c
··· 22 22 #include <linux/of_mdio.h> 23 23 #include <linux/bitops.h> 24 24 #include <linux/if_bridge.h> 25 + #include <linux/if_vlan.h> 25 26 #include <linux/etherdevice.h> 26 27 #include <linux/gpio/consumer.h> 27 28 #include <linux/gpio/driver.h> 29 + #include <linux/dsa/8021q.h> 28 30 #include <linux/random.h> 29 31 #include <net/dsa.h> 30 32 ··· 64 62 #define VSC73XX_CAT_DROP 0x6e 65 63 #define VSC73XX_CAT_PR_MISC_L2 0x6f 66 64 #define VSC73XX_CAT_PR_USR_PRIO 0x75 65 + #define VSC73XX_CAT_VLAN_MISC 0x79 66 + #define VSC73XX_CAT_PORT_VLAN 0x7a 67 67 #define VSC73XX_Q_MISC_CONF 0xdf 68 68 69 69 /* MAC_CFG register bits */ ··· 126 122 #define VSC73XX_ADVPORTM_IO_LOOPBACK BIT(1) 127 123 #define VSC73XX_ADVPORTM_HOST_LOOPBACK BIT(0) 128 124 125 + /* TXUPDCFG transmit modify setup bits */ 126 + #define VSC73XX_TXUPDCFG_DSCP_REWR_MODE GENMASK(20, 19) 127 + #define VSC73XX_TXUPDCFG_DSCP_REWR_ENA BIT(18) 128 + #define VSC73XX_TXUPDCFG_TX_INT_TO_USRPRIO_ENA BIT(17) 129 + #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID GENMASK(15, 4) 130 + #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA BIT(3) 131 + #define VSC73XX_TXUPDCFG_TX_UPDATE_CRC_CPU_ENA BIT(1) 132 + #define VSC73XX_TXUPDCFG_TX_INSERT_TAG BIT(0) 133 + 134 + #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT 4 135 + 129 136 /* CAT_DROP categorizer frame dropping register bits */ 130 137 #define VSC73XX_CAT_DROP_DROP_MC_SMAC_ENA BIT(6) 131 138 #define VSC73XX_CAT_DROP_FWD_CTRL_ENA BIT(4) ··· 149 134 #define VSC73XX_Q_MISC_CONF_EARLY_TX_MASK GENMASK(4, 1) 150 135 #define VSC73XX_Q_MISC_CONF_EARLY_TX_512 (1 << 1) 151 136 #define VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE BIT(0) 137 + 138 + /* CAT_VLAN_MISC categorizer VLAN miscellaneous bits */ 139 + #define VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA BIT(8) 140 + #define VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA BIT(7) 141 + 142 + /* CAT_PORT_VLAN categorizer port VLAN */ 143 + #define VSC73XX_CAT_PORT_VLAN_VLAN_CFI BIT(15) 144 + #define VSC73XX_CAT_PORT_VLAN_VLAN_USR_PRIO GENMASK(14, 12) 145 + #define VSC73XX_CAT_PORT_VLAN_VLAN_VID GENMASK(11, 0) 152 146 153 147 /* Frame analyzer block 2 registers */ 154 148 #define VSC73XX_STORMLIMIT 0x02 ··· 213 189 #define VSC73XX_VLANACCESS_VLAN_MIRROR BIT(29) 214 190 #define VSC73XX_VLANACCESS_VLAN_SRC_CHECK BIT(28) 215 191 #define VSC73XX_VLANACCESS_VLAN_PORT_MASK GENMASK(9, 2) 216 - #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK GENMASK(2, 0) 192 + #define VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT 2 193 + #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK GENMASK(1, 0) 217 194 #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE 0 218 195 #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY 1 219 196 #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY 2 ··· 370 345 { 27, "TxQoSClass1" }, /* non-standard counter */ 371 346 { 28, "TxQoSClass2" }, /* non-standard counter */ 372 347 { 29, "TxQoSClass3" }, /* non-standard counter */ 348 + }; 349 + 350 + struct vsc73xx_vlan_summary { 351 + size_t num_tagged; 352 + size_t num_untagged; 353 + }; 354 + 355 + enum vsc73xx_port_vlan_conf { 356 + VSC73XX_VLAN_FILTER, 357 + VSC73XX_VLAN_FILTER_UNTAG_ALL, 358 + VSC73XX_VLAN_IGNORE, 373 359 }; 374 360 375 361 int vsc73xx_is_addr_valid(u8 block, u8 subblock) ··· 600 564 return DSA_TAG_PROTO_NONE; 601 565 } 602 566 567 + static int vsc73xx_wait_for_vlan_table_cmd(struct vsc73xx *vsc) 568 + { 569 + int ret, err; 570 + u32 val; 571 + 572 + ret = read_poll_timeout(vsc73xx_read, err, 573 + err < 0 || 574 + ((val & VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK) == 575 + VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE), 576 + VSC73XX_POLL_SLEEP_US, VSC73XX_POLL_TIMEOUT_US, 577 + false, vsc, VSC73XX_BLOCK_ANALYZER, 578 + 0, VSC73XX_VLANACCESS, &val); 579 + if (ret) 580 + return ret; 581 + return err; 582 + } 583 + 584 + static int 585 + vsc73xx_read_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 *portmap) 586 + { 587 + u32 val; 588 + int ret; 589 + 590 + vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid); 591 + 592 + ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 593 + if (ret) 594 + return ret; 595 + 596 + vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, 597 + VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK, 598 + VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY); 599 + 600 + ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 601 + if (ret) 602 + return ret; 603 + 604 + vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, &val); 605 + *portmap = (val & VSC73XX_VLANACCESS_VLAN_PORT_MASK) >> 606 + VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT; 607 + 608 + return 0; 609 + } 610 + 611 + static int 612 + vsc73xx_write_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 portmap) 613 + { 614 + int ret; 615 + 616 + vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid); 617 + 618 + ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 619 + if (ret) 620 + return ret; 621 + 622 + vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, 623 + VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK | 624 + VSC73XX_VLANACCESS_VLAN_SRC_CHECK | 625 + VSC73XX_VLANACCESS_VLAN_PORT_MASK, 626 + VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY | 627 + VSC73XX_VLANACCESS_VLAN_SRC_CHECK | 628 + (portmap << VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT)); 629 + 630 + return vsc73xx_wait_for_vlan_table_cmd(vsc); 631 + } 632 + 633 + static int 634 + vsc73xx_update_vlan_table(struct vsc73xx *vsc, int port, u16 vid, bool set) 635 + { 636 + u8 portmap; 637 + int ret; 638 + 639 + ret = vsc73xx_read_vlan_table_entry(vsc, vid, &portmap); 640 + if (ret) 641 + return ret; 642 + 643 + if (set) 644 + portmap |= BIT(port); 645 + else 646 + portmap &= ~BIT(port); 647 + 648 + return vsc73xx_write_vlan_table_entry(vsc, vid, portmap); 649 + } 650 + 603 651 static int vsc73xx_setup(struct dsa_switch *ds) 604 652 { 605 653 struct vsc73xx *vsc = ds->priv; ··· 718 598 VSC73XX_MACACCESS, 719 599 VSC73XX_MACACCESS_CMD_CLEAR_TABLE); 720 600 721 - /* Clear VLAN table */ 601 + /* Set VLAN table to default values */ 722 602 vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, 723 603 VSC73XX_VLANACCESS, 724 604 VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE); ··· 747 627 vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GMIIDELAY, 748 628 VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS | 749 629 VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS); 630 + /* Ingess VLAN reception mask (table 145) */ 631 + vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANMASK, 632 + 0xff); 750 633 /* IP multicast flood mask (table 144) */ 751 634 vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_IFLODMSK, 752 635 0xff); ··· 761 638 VSC73XX_GLORESET_PHY_RESET); 762 639 763 640 udelay(4); 641 + 642 + /* Clear VLAN table */ 643 + for (i = 0; i < VLAN_N_VID; i++) 644 + vsc73xx_write_vlan_table_entry(vsc, i, 0); 645 + 646 + INIT_LIST_HEAD(&vsc->vlans); 764 647 765 648 return 0; 766 649 } ··· 954 825 val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET; 955 826 val |= VSC73XX_MAC_CFG_SEED_LOAD; 956 827 val |= VSC73XX_MAC_CFG_WEXC_DIS; 828 + 829 + /* Those bits are responsible for MTU only. Kernel takes care about MTU, 830 + * let's enable +8 bytes frame length unconditionally. 831 + */ 832 + val |= VSC73XX_MAC_CFG_VLAN_AWR | VSC73XX_MAC_CFG_VLAN_DBLAWR; 833 + 957 834 vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val); 958 835 959 836 /* Flow control for the PHY facing ports: ··· 988 853 VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN); 989 854 } 990 855 856 + static bool vsc73xx_tag_8021q_active(struct dsa_port *dp) 857 + { 858 + return !dsa_port_is_vlan_filtering(dp); 859 + } 860 + 861 + static struct vsc73xx_bridge_vlan * 862 + vsc73xx_bridge_vlan_find(struct vsc73xx *vsc, u16 vid) 863 + { 864 + struct vsc73xx_bridge_vlan *vlan; 865 + 866 + list_for_each_entry(vlan, &vsc->vlans, list) 867 + if (vlan->vid == vid) 868 + return vlan; 869 + 870 + return NULL; 871 + } 872 + 873 + static void 874 + vsc73xx_bridge_vlan_remove_port(struct vsc73xx_bridge_vlan *vsc73xx_vlan, 875 + int port) 876 + { 877 + vsc73xx_vlan->portmask &= ~BIT(port); 878 + 879 + if (vsc73xx_vlan->portmask) 880 + return; 881 + 882 + list_del(&vsc73xx_vlan->list); 883 + kfree(vsc73xx_vlan); 884 + } 885 + 886 + static void vsc73xx_bridge_vlan_summary(struct vsc73xx *vsc, int port, 887 + struct vsc73xx_vlan_summary *summary, 888 + u16 ignored_vid) 889 + { 890 + size_t num_tagged = 0, num_untagged = 0; 891 + struct vsc73xx_bridge_vlan *vlan; 892 + 893 + list_for_each_entry(vlan, &vsc->vlans, list) { 894 + if (!(vlan->portmask & BIT(port)) || vlan->vid == ignored_vid) 895 + continue; 896 + 897 + if (vlan->untagged & BIT(port)) 898 + num_untagged++; 899 + else 900 + num_tagged++; 901 + } 902 + 903 + summary->num_untagged = num_untagged; 904 + summary->num_tagged = num_tagged; 905 + } 906 + 907 + static u16 vsc73xx_find_first_vlan_untagged(struct vsc73xx *vsc, int port) 908 + { 909 + struct vsc73xx_bridge_vlan *vlan; 910 + 911 + list_for_each_entry(vlan, &vsc->vlans, list) 912 + if ((vlan->portmask & BIT(port)) && 913 + (vlan->untagged & BIT(port))) 914 + return vlan->vid; 915 + 916 + return VLAN_N_VID; 917 + } 918 + 919 + static int vsc73xx_set_vlan_conf(struct vsc73xx *vsc, int port, 920 + enum vsc73xx_port_vlan_conf port_vlan_conf) 921 + { 922 + u32 val = 0; 923 + int ret; 924 + 925 + if (port_vlan_conf == VSC73XX_VLAN_IGNORE) 926 + val = VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA | 927 + VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA; 928 + 929 + ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 930 + VSC73XX_CAT_VLAN_MISC, 931 + VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA | 932 + VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA, val); 933 + if (ret) 934 + return ret; 935 + 936 + val = (port_vlan_conf == VSC73XX_VLAN_FILTER) ? 937 + VSC73XX_TXUPDCFG_TX_INSERT_TAG : 0; 938 + 939 + return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 940 + VSC73XX_TXUPDCFG, 941 + VSC73XX_TXUPDCFG_TX_INSERT_TAG, val); 942 + } 943 + 944 + /** 945 + * vsc73xx_vlan_commit_conf - Update VLAN configuration of a port 946 + * @vsc: Switch private data structure 947 + * @port: Port index on which to operate 948 + * 949 + * Update the VLAN behavior of a port to make sure that when it is under 950 + * a VLAN filtering bridge, the port is either filtering with tag 951 + * preservation, or filtering with all VLANs egress-untagged. Otherwise, 952 + * the port ignores VLAN tags from packets and applies the port-based 953 + * VID. 954 + * 955 + * Must be called when changes are made to: 956 + * - the bridge VLAN filtering state of the port 957 + * - the number or attributes of VLANs from the bridge VLAN table, 958 + * while the port is currently VLAN-aware 959 + * 960 + * Return: 0 on success, or negative errno on error. 961 + */ 962 + static int vsc73xx_vlan_commit_conf(struct vsc73xx *vsc, int port) 963 + { 964 + enum vsc73xx_port_vlan_conf port_vlan_conf = VSC73XX_VLAN_IGNORE; 965 + struct dsa_port *dp = dsa_to_port(vsc->ds, port); 966 + 967 + if (port == CPU_PORT) { 968 + port_vlan_conf = VSC73XX_VLAN_FILTER; 969 + } else if (dsa_port_is_vlan_filtering(dp)) { 970 + struct vsc73xx_vlan_summary summary; 971 + 972 + port_vlan_conf = VSC73XX_VLAN_FILTER; 973 + 974 + vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID); 975 + if (summary.num_tagged == 0) 976 + port_vlan_conf = VSC73XX_VLAN_FILTER_UNTAG_ALL; 977 + } 978 + 979 + return vsc73xx_set_vlan_conf(vsc, port, port_vlan_conf); 980 + } 981 + 982 + static int 983 + vsc73xx_vlan_change_untagged(struct vsc73xx *vsc, int port, u16 vid, bool set) 984 + { 985 + u32 val = 0; 986 + 987 + if (set) 988 + val = VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA | 989 + ((vid << VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT) & 990 + VSC73XX_TXUPDCFG_TX_UNTAGGED_VID); 991 + 992 + return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 993 + VSC73XX_TXUPDCFG, 994 + VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA | 995 + VSC73XX_TXUPDCFG_TX_UNTAGGED_VID, val); 996 + } 997 + 998 + /** 999 + * vsc73xx_vlan_commit_untagged - Update native VLAN of a port 1000 + * @vsc: Switch private data structure 1001 + * @port: Port index on which to operate 1002 + * 1003 + * Update the native VLAN of a port (the one VLAN which is transmitted 1004 + * as egress-tagged on a trunk port) when port is in VLAN filtering mode and 1005 + * only one untagged vid is configured. 1006 + * In other cases no need to configure it because switch can untag all vlans on 1007 + * the port. 1008 + * 1009 + * Return: 0 on success, or negative errno on error. 1010 + */ 1011 + static int vsc73xx_vlan_commit_untagged(struct vsc73xx *vsc, int port) 1012 + { 1013 + struct dsa_port *dp = dsa_to_port(vsc->ds, port); 1014 + struct vsc73xx_vlan_summary summary; 1015 + u16 vid = 0; 1016 + bool valid; 1017 + 1018 + if (!dsa_port_is_vlan_filtering(dp)) 1019 + /* Port is configured to untag all vlans in that case. 1020 + * No need to commit untagged config change. 1021 + */ 1022 + return 0; 1023 + 1024 + vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID); 1025 + 1026 + if (summary.num_untagged > 1) 1027 + /* Port must untag all vlans in that case. 1028 + * No need to commit untagged config change. 1029 + */ 1030 + return 0; 1031 + 1032 + valid = (summary.num_untagged == 1); 1033 + if (valid) 1034 + vid = vsc73xx_find_first_vlan_untagged(vsc, port); 1035 + 1036 + return vsc73xx_vlan_change_untagged(vsc, port, vid, valid); 1037 + } 1038 + 1039 + static int 1040 + vsc73xx_vlan_change_pvid(struct vsc73xx *vsc, int port, u16 vid, bool set) 1041 + { 1042 + u32 val = 0; 1043 + int ret; 1044 + 1045 + val = set ? 0 : VSC73XX_CAT_DROP_UNTAGGED_ENA; 1046 + 1047 + ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 1048 + VSC73XX_CAT_DROP, 1049 + VSC73XX_CAT_DROP_UNTAGGED_ENA, val); 1050 + if (!set || ret) 1051 + return ret; 1052 + 1053 + return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 1054 + VSC73XX_CAT_PORT_VLAN, 1055 + VSC73XX_CAT_PORT_VLAN_VLAN_VID, 1056 + vid & VSC73XX_CAT_PORT_VLAN_VLAN_VID); 1057 + } 1058 + 1059 + /** 1060 + * vsc73xx_vlan_commit_pvid - Update port-based default VLAN of a port 1061 + * @vsc: Switch private data structure 1062 + * @port: Port index on which to operate 1063 + * 1064 + * Update the PVID of a port so that it follows either the bridge PVID 1065 + * configuration, when the bridge is currently VLAN-aware, or the PVID 1066 + * from tag_8021q, when the port is standalone or under a VLAN-unaware 1067 + * bridge. A port with no PVID drops all untagged and VID 0 tagged 1068 + * traffic. 1069 + * 1070 + * Must be called when changes are made to: 1071 + * - the bridge VLAN filtering state of the port 1072 + * - the number or attributes of VLANs from the bridge VLAN table, 1073 + * while the port is currently VLAN-aware 1074 + * 1075 + * Return: 0 on success, or negative errno on error. 1076 + */ 1077 + static int vsc73xx_vlan_commit_pvid(struct vsc73xx *vsc, int port) 1078 + { 1079 + struct vsc73xx_portinfo *portinfo = &vsc->portinfo[port]; 1080 + bool valid = portinfo->pvid_tag_8021q_configured; 1081 + struct dsa_port *dp = dsa_to_port(vsc->ds, port); 1082 + u16 vid = portinfo->pvid_tag_8021q; 1083 + 1084 + if (dsa_port_is_vlan_filtering(dp)) { 1085 + vid = portinfo->pvid_vlan_filtering; 1086 + valid = portinfo->pvid_vlan_filtering_configured; 1087 + } 1088 + 1089 + return vsc73xx_vlan_change_pvid(vsc, port, vid, valid); 1090 + } 1091 + 1092 + static int vsc73xx_vlan_commit_settings(struct vsc73xx *vsc, int port) 1093 + { 1094 + int ret; 1095 + 1096 + ret = vsc73xx_vlan_commit_untagged(vsc, port); 1097 + if (ret) 1098 + return ret; 1099 + 1100 + ret = vsc73xx_vlan_commit_pvid(vsc, port); 1101 + if (ret) 1102 + return ret; 1103 + 1104 + return vsc73xx_vlan_commit_conf(vsc, port); 1105 + } 1106 + 991 1107 static int vsc73xx_port_enable(struct dsa_switch *ds, int port, 992 1108 struct phy_device *phy) 993 1109 { ··· 1247 861 dev_info(vsc->dev, "enable port %d\n", port); 1248 862 vsc73xx_init_port(vsc, port); 1249 863 1250 - return 0; 864 + return vsc73xx_vlan_commit_settings(vsc, port); 1251 865 } 1252 866 1253 867 static void vsc73xx_port_disable(struct dsa_switch *ds, int port) ··· 1418 1032 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000; 1419 1033 } 1420 1034 1035 + static int 1036 + vsc73xx_port_vlan_filtering(struct dsa_switch *ds, int port, 1037 + bool vlan_filtering, struct netlink_ext_ack *extack) 1038 + { 1039 + struct vsc73xx *vsc = ds->priv; 1040 + 1041 + /* The commit to hardware processed below is required because vsc73xx 1042 + * is using tag_8021q. When vlan_filtering is disabled, tag_8021q uses 1043 + * pvid/untagged vlans for port recognition. The values configured for 1044 + * vlans and pvid/untagged states are stored in portinfo structure. 1045 + * When vlan_filtering is enabled, we need to restore pvid/untagged from 1046 + * portinfo structure. Analogous routine is processed when 1047 + * vlan_filtering is disabled, but values used for tag_8021q are 1048 + * restored. 1049 + */ 1050 + 1051 + return vsc73xx_vlan_commit_settings(vsc, port); 1052 + } 1053 + 1054 + static int vsc73xx_port_vlan_add(struct dsa_switch *ds, int port, 1055 + const struct switchdev_obj_port_vlan *vlan, 1056 + struct netlink_ext_ack *extack) 1057 + { 1058 + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 1059 + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 1060 + struct dsa_port *dp = dsa_to_port(ds, port); 1061 + struct vsc73xx_bridge_vlan *vsc73xx_vlan; 1062 + struct vsc73xx_vlan_summary summary; 1063 + struct vsc73xx_portinfo *portinfo; 1064 + struct vsc73xx *vsc = ds->priv; 1065 + bool commit_to_hardware; 1066 + int ret = 0; 1067 + 1068 + /* Be sure to deny alterations to the configuration done by tag_8021q. 1069 + */ 1070 + if (vid_is_dsa_8021q(vlan->vid)) { 1071 + NL_SET_ERR_MSG_MOD(extack, 1072 + "Range 3072-4095 reserved for dsa_8021q operation"); 1073 + return -EBUSY; 1074 + } 1075 + 1076 + /* The processed vlan->vid is excluded from the search because the VLAN 1077 + * can be re-added with a different set of flags, so it's easiest to 1078 + * ignore its old flags from the VLAN database software copy. 1079 + */ 1080 + vsc73xx_bridge_vlan_summary(vsc, port, &summary, vlan->vid); 1081 + 1082 + /* VSC73XX allows only three untagged states: none, one or all */ 1083 + if ((untagged && summary.num_tagged > 0 && summary.num_untagged > 0) || 1084 + (!untagged && summary.num_untagged > 1)) { 1085 + NL_SET_ERR_MSG_MOD(extack, 1086 + "Port can have only none, one or all untagged vlan"); 1087 + return -EBUSY; 1088 + } 1089 + 1090 + vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid); 1091 + 1092 + if (!vsc73xx_vlan) { 1093 + vsc73xx_vlan = kzalloc(sizeof(*vsc73xx_vlan), GFP_KERNEL); 1094 + if (!vsc73xx_vlan) 1095 + return -ENOMEM; 1096 + 1097 + vsc73xx_vlan->vid = vlan->vid; 1098 + 1099 + list_add_tail(&vsc73xx_vlan->list, &vsc->vlans); 1100 + } 1101 + 1102 + vsc73xx_vlan->portmask |= BIT(port); 1103 + 1104 + /* CPU port must be always tagged because source port identification is 1105 + * based on tag_8021q. 1106 + */ 1107 + if (port == CPU_PORT) 1108 + goto update_vlan_table; 1109 + 1110 + if (untagged) 1111 + vsc73xx_vlan->untagged |= BIT(port); 1112 + else 1113 + vsc73xx_vlan->untagged &= ~BIT(port); 1114 + 1115 + portinfo = &vsc->portinfo[port]; 1116 + 1117 + if (pvid) { 1118 + portinfo->pvid_vlan_filtering_configured = true; 1119 + portinfo->pvid_vlan_filtering = vlan->vid; 1120 + } else if (portinfo->pvid_vlan_filtering_configured && 1121 + portinfo->pvid_vlan_filtering == vlan->vid) { 1122 + portinfo->pvid_vlan_filtering_configured = false; 1123 + } 1124 + 1125 + commit_to_hardware = !vsc73xx_tag_8021q_active(dp); 1126 + if (commit_to_hardware) { 1127 + ret = vsc73xx_vlan_commit_settings(vsc, port); 1128 + if (ret) 1129 + goto err; 1130 + } 1131 + 1132 + update_vlan_table: 1133 + ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, true); 1134 + if (!ret) 1135 + return 0; 1136 + err: 1137 + vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port); 1138 + return ret; 1139 + } 1140 + 1141 + static int vsc73xx_port_vlan_del(struct dsa_switch *ds, int port, 1142 + const struct switchdev_obj_port_vlan *vlan) 1143 + { 1144 + struct vsc73xx_bridge_vlan *vsc73xx_vlan; 1145 + struct vsc73xx_portinfo *portinfo; 1146 + struct vsc73xx *vsc = ds->priv; 1147 + bool commit_to_hardware; 1148 + int ret; 1149 + 1150 + ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, false); 1151 + if (ret) 1152 + return ret; 1153 + 1154 + portinfo = &vsc->portinfo[port]; 1155 + 1156 + if (portinfo->pvid_vlan_filtering_configured && 1157 + portinfo->pvid_vlan_filtering == vlan->vid) 1158 + portinfo->pvid_vlan_filtering_configured = false; 1159 + 1160 + vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid); 1161 + 1162 + if (vsc73xx_vlan) 1163 + vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port); 1164 + 1165 + commit_to_hardware = !vsc73xx_tag_8021q_active(dsa_to_port(ds, port)); 1166 + if (commit_to_hardware) 1167 + return vsc73xx_vlan_commit_settings(vsc, port); 1168 + 1169 + return 0; 1170 + } 1171 + 1421 1172 static void vsc73xx_refresh_fwd_map(struct dsa_switch *ds, int port, u8 state) 1422 1173 { 1423 1174 struct dsa_port *other_dp, *dp = dsa_to_port(ds, port); ··· 1654 1131 .port_change_mtu = vsc73xx_change_mtu, 1655 1132 .port_max_mtu = vsc73xx_get_max_mtu, 1656 1133 .port_stp_state_set = vsc73xx_port_stp_state_set, 1134 + .port_vlan_filtering = vsc73xx_port_vlan_filtering, 1135 + .port_vlan_add = vsc73xx_port_vlan_add, 1136 + .port_vlan_del = vsc73xx_port_vlan_del, 1657 1137 .phylink_get_caps = vsc73xx_phylink_get_caps, 1658 1138 }; 1659 1139
+37
drivers/net/dsa/vitesse-vsc73xx.h
··· 15 15 #define VSC73XX_MAX_NUM_PORTS 8 16 16 17 17 /** 18 + * struct vsc73xx_portinfo - port data structure: contains storage data 19 + * @pvid_vlan_filtering: pvid vlan number used in vlan filtering mode 20 + * @pvid_tag_8021q: pvid vlan number used in tag_8021q mode 21 + * @pvid_vlan_filtering_configured: informs if port has configured pvid in vlan 22 + * filtering mode 23 + * @pvid_tag_8021q_configured: imforms if port have configured pvid in tag_8021q 24 + * mode 25 + */ 26 + struct vsc73xx_portinfo { 27 + u16 pvid_vlan_filtering; 28 + u16 pvid_tag_8021q; 29 + bool pvid_vlan_filtering_configured; 30 + bool pvid_tag_8021q_configured; 31 + }; 32 + 33 + /** 18 34 * struct vsc73xx - VSC73xx state container: main data structure 19 35 * @dev: The device pointer 20 36 * @reset: The descriptor for the GPIO line tied to the reset pin ··· 41 25 * @addr: MAC address used in flow control frames 42 26 * @ops: Structure with hardware-dependent operations 43 27 * @priv: Pointer to the configuration interface structure 28 + * @portinfo: Storage table portinfo structructures 29 + * @vlans: List of configured vlans. Contains port mask and untagged status of 30 + * every vlan configured in port vlan operation. It doesn't cover tag_8021q 31 + * vlans. 44 32 */ 45 33 struct vsc73xx { 46 34 struct device *dev; ··· 55 35 u8 addr[ETH_ALEN]; 56 36 const struct vsc73xx_ops *ops; 57 37 void *priv; 38 + struct vsc73xx_portinfo portinfo[VSC73XX_MAX_NUM_PORTS]; 39 + struct list_head vlans; 58 40 }; 59 41 60 42 /** ··· 69 47 u32 *val); 70 48 int (*write)(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, 71 49 u32 val); 50 + }; 51 + 52 + /** 53 + * struct vsc73xx_bridge_vlan - VSC73xx driver structure which keeps vlan 54 + * database copy 55 + * @vid: VLAN number 56 + * @portmask: each bit represents one port 57 + * @untagged: each bit represents one port configured with @vid untagged 58 + * @list: list structure 59 + */ 60 + struct vsc73xx_bridge_vlan { 61 + u16 vid; 62 + u8 portmask; 63 + u8 untagged; 64 + struct list_head list; 72 65 }; 73 66 74 67 int vsc73xx_is_addr_valid(u8 block, u8 subblock);