Message ID | 72a0a9f2748193bc02fed5e74c343aa5397348b7.1513136754.git.sean.wang@mediatek.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
Series | add VLAN support to DSA MT7530 | expand |
Hi Sean, I love your patch! Yet something to improve: [auto build test ERROR on net-next/master] url: https://github.com/0day-ci/linux/commits/sean-wang-mediatek-com/add-VLAN-support-to-DSA-MT7530/20171215-214450 config: i386-randconfig-x019-201750 (attached as .config) compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025 reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): drivers/net/dsa/mt7530.c: In function 'mt7530_port_vlan_add': drivers/net/dsa/mt7530.c:1131:6: warning: unused variable 'ret' [-Wunused-variable] int ret; ^~~ drivers/net/dsa/mt7530.c: At top level: >> drivers/net/dsa/mt7530.c:1324:23: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] .port_vlan_prepare = mt7530_port_vlan_prepare, ^~~~~~~~~~~~~~~~~~~~~~~~ drivers/net/dsa/mt7530.c:1324:23: note: (near initialization for 'mt7530_switch_ops.port_vlan_prepare') drivers/net/dsa/mt7530.c:1325:20: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] .port_vlan_add = mt7530_port_vlan_add, ^~~~~~~~~~~~~~~~~~~~ drivers/net/dsa/mt7530.c:1325:20: note: (near initialization for 'mt7530_switch_ops.port_vlan_add') cc1: some warnings being treated as errors vim +1324 drivers/net/dsa/mt7530.c 1121 1122 static void 1123 mt7530_port_vlan_add(struct dsa_switch *ds, int port, 1124 const struct switchdev_obj_port_vlan *vlan, 1125 struct switchdev_trans *trans) 1126 { 1127 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 1128 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 1129 struct mt7530_hw_vlan_entry new_entry; 1130 struct mt7530_priv *priv = ds->priv; > 1131 int ret; 1132 u16 vid; 1133 1134 /* The port is kept as VLAN-unaware if bridge with vlan_filtering not 1135 * being set. 1136 */ 1137 if (!priv->ports[port].vlan_filtering) 1138 return; 1139 1140 mutex_lock(&priv->reg_mutex); 1141 1142 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { 1143 mt7530_hw_vlan_entry_init(&new_entry, port, untagged); 1144 mt7530_hw_vlan_update(priv, vid, &new_entry, 1145 mt7530_hw_vlan_add); 1146 } 1147 1148 if (pvid) { 1149 mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, 1150 G0_PORT_VID(vlan->vid_end)); 1151 priv->ports[port].pvid = vlan->vid_end; 1152 } 1153 1154 mutex_unlock(&priv->reg_mutex); 1155 } 1156 1157 static int 1158 mt7530_port_vlan_del(struct dsa_switch *ds, int port, 1159 const struct switchdev_obj_port_vlan *vlan) 1160 { 1161 struct mt7530_hw_vlan_entry target_entry; 1162 struct mt7530_priv *priv = ds->priv; 1163 u16 vid, pvid; 1164 1165 /* The port is kept as VLAN-unaware if bridge with vlan_filtering not 1166 * being set. 1167 */ 1168 if (!priv->ports[port].vlan_filtering) 1169 return 0; 1170 1171 mutex_lock(&priv->reg_mutex); 1172 1173 pvid = priv->ports[port].pvid; 1174 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { 1175 mt7530_hw_vlan_entry_init(&target_entry, port, 0); 1176 mt7530_hw_vlan_update(priv, vid, &target_entry, 1177 mt7530_hw_vlan_del); 1178 1179 /* PVID is being restored to the default whenever the PVID port 1180 * is being removed from the VLAN. 1181 */ 1182 if (pvid == vid) 1183 pvid = G0_PORT_VID_DEF; 1184 } 1185 1186 mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, pvid); 1187 priv->ports[port].pvid = pvid; 1188 1189 mutex_unlock(&priv->reg_mutex); 1190 1191 return 0; 1192 } 1193 1194 static enum dsa_tag_protocol 1195 mtk_get_tag_protocol(struct dsa_switch *ds, int port) 1196 { 1197 struct mt7530_priv *priv = ds->priv; 1198 1199 if (port != MT7530_CPU_PORT) { 1200 dev_warn(priv->dev, 1201 "port not matched with tagging CPU port\n"); 1202 return DSA_TAG_PROTO_NONE; 1203 } else { 1204 return DSA_TAG_PROTO_MTK; 1205 } 1206 } 1207 1208 static int 1209 mt7530_setup(struct dsa_switch *ds) 1210 { 1211 struct mt7530_priv *priv = ds->priv; 1212 int ret, i; 1213 u32 id, val; 1214 struct device_node *dn; 1215 struct mt7530_dummy_poll p; 1216 1217 /* The parent node of master netdev which holds the common system 1218 * controller also is the container for two GMACs nodes representing 1219 * as two netdev instances. 1220 */ 1221 dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent; 1222 priv->ethernet = syscon_node_to_regmap(dn); 1223 if (IS_ERR(priv->ethernet)) 1224 return PTR_ERR(priv->ethernet); 1225 1226 regulator_set_voltage(priv->core_pwr, 1000000, 1000000); 1227 ret = regulator_enable(priv->core_pwr); 1228 if (ret < 0) { 1229 dev_err(priv->dev, 1230 "Failed to enable core power: %d\n", ret); 1231 return ret; 1232 } 1233 1234 regulator_set_voltage(priv->io_pwr, 3300000, 3300000); 1235 ret = regulator_enable(priv->io_pwr); 1236 if (ret < 0) { 1237 dev_err(priv->dev, "Failed to enable io pwr: %d\n", 1238 ret); 1239 return ret; 1240 } 1241 1242 /* Reset whole chip through gpio pin or memory-mapped registers for 1243 * different type of hardware 1244 */ 1245 if (priv->mcm) { 1246 reset_control_assert(priv->rstc); 1247 usleep_range(1000, 1100); 1248 reset_control_deassert(priv->rstc); 1249 } else { 1250 gpiod_set_value_cansleep(priv->reset, 0); 1251 usleep_range(1000, 1100); 1252 gpiod_set_value_cansleep(priv->reset, 1); 1253 } 1254 1255 /* Waiting for MT7530 got to stable */ 1256 INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); 1257 ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, 1258 20, 1000000); 1259 if (ret < 0) { 1260 dev_err(priv->dev, "reset timeout\n"); 1261 return ret; 1262 } 1263 1264 id = mt7530_read(priv, MT7530_CREV); 1265 id >>= CHIP_NAME_SHIFT; 1266 if (id != MT7530_ID) { 1267 dev_err(priv->dev, "chip %x can't be supported\n", id); 1268 return -ENODEV; 1269 } 1270 1271 /* Reset the switch through internal reset */ 1272 mt7530_write(priv, MT7530_SYS_CTRL, 1273 SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | 1274 SYS_CTRL_REG_RST); 1275 1276 /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ 1277 val = mt7530_read(priv, MT7530_MHWTRAP); 1278 val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; 1279 val |= MHWTRAP_MANUAL; 1280 mt7530_write(priv, MT7530_MHWTRAP, val); 1281 1282 /* Enable and reset MIB counters */ 1283 mt7530_mib_reset(ds); 1284 1285 mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK); 1286 1287 for (i = 0; i < MT7530_NUM_PORTS; i++) { 1288 /* Disable forwarding by default on all ports */ 1289 mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, 1290 PCR_MATRIX_CLR); 1291 1292 if (dsa_is_cpu_port(ds, i)) 1293 mt7530_cpu_port_enable(priv, i); 1294 else 1295 mt7530_port_disable(ds, i, NULL); 1296 } 1297 1298 /* Flush the FDB table */ 1299 ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, 0); 1300 if (ret < 0) 1301 return ret; 1302 1303 return 0; 1304 } 1305 1306 static const struct dsa_switch_ops mt7530_switch_ops = { 1307 .get_tag_protocol = mtk_get_tag_protocol, 1308 .setup = mt7530_setup, 1309 .get_strings = mt7530_get_strings, 1310 .phy_read = mt7530_phy_read, 1311 .phy_write = mt7530_phy_write, 1312 .get_ethtool_stats = mt7530_get_ethtool_stats, 1313 .get_sset_count = mt7530_get_sset_count, 1314 .adjust_link = mt7530_adjust_link, 1315 .port_enable = mt7530_port_enable, 1316 .port_disable = mt7530_port_disable, 1317 .port_stp_state_set = mt7530_stp_state_set, 1318 .port_bridge_join = mt7530_port_bridge_join, 1319 .port_bridge_leave = mt7530_port_bridge_leave, 1320 .port_fdb_add = mt7530_port_fdb_add, 1321 .port_fdb_del = mt7530_port_fdb_del, 1322 .port_fdb_dump = mt7530_port_fdb_dump, 1323 .port_vlan_filtering = mt7530_port_vlan_filtering, > 1324 .port_vlan_prepare = mt7530_port_vlan_prepare, 1325 .port_vlan_add = mt7530_port_vlan_add, 1326 .port_vlan_del = mt7530_port_vlan_del, 1327 }; 1328 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Sean, I love your patch! Perhaps something to improve: [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/sean-wang-mediatek-com/add-VLAN-support-to-DSA-MT7530/20171215-214450 reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) vim +1324 drivers/net/dsa/mt7530.c 1305 1306 static const struct dsa_switch_ops mt7530_switch_ops = { 1307 .get_tag_protocol = mtk_get_tag_protocol, 1308 .setup = mt7530_setup, 1309 .get_strings = mt7530_get_strings, 1310 .phy_read = mt7530_phy_read, 1311 .phy_write = mt7530_phy_write, 1312 .get_ethtool_stats = mt7530_get_ethtool_stats, 1313 .get_sset_count = mt7530_get_sset_count, 1314 .adjust_link = mt7530_adjust_link, 1315 .port_enable = mt7530_port_enable, 1316 .port_disable = mt7530_port_disable, 1317 .port_stp_state_set = mt7530_stp_state_set, 1318 .port_bridge_join = mt7530_port_bridge_join, 1319 .port_bridge_leave = mt7530_port_bridge_leave, 1320 .port_fdb_add = mt7530_port_fdb_add, 1321 .port_fdb_del = mt7530_port_fdb_del, 1322 .port_fdb_dump = mt7530_port_fdb_dump, 1323 .port_vlan_filtering = mt7530_port_vlan_filtering, > 1324 .port_vlan_prepare = mt7530_port_vlan_prepare, > 1325 .port_vlan_add = mt7530_port_vlan_add, 1326 .port_vlan_del = mt7530_port_vlan_del, 1327 }; 1328 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Sean, I love your patch! Perhaps something to improve: [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/sean-wang-mediatek-com/add-VLAN-support-to-DSA-MT7530/20171215-214450 config: x86_64-randconfig-g0-12151942 (attached as .config) compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All warnings (new ones prefixed by >>): drivers/net/dsa/mt7530.c: In function 'mt7530_port_vlan_add': drivers/net/dsa/mt7530.c:1131:6: warning: unused variable 'ret' [-Wunused-variable] int ret; ^ drivers/net/dsa/mt7530.c: At top level: >> drivers/net/dsa/mt7530.c:1324:2: warning: initialization from incompatible pointer type .port_vlan_prepare = mt7530_port_vlan_prepare, ^ drivers/net/dsa/mt7530.c:1324:2: warning: (near initialization for 'mt7530_switch_ops.port_vlan_prepare') drivers/net/dsa/mt7530.c:1325:2: warning: initialization from incompatible pointer type .port_vlan_add = mt7530_port_vlan_add, ^ drivers/net/dsa/mt7530.c:1325:2: warning: (near initialization for 'mt7530_switch_ops.port_vlan_add') Cyclomatic Complexity 3 include/linux/string.h:strncpy Cyclomatic Complexity 1 include/linux/err.h:ERR_PTR Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR Cyclomatic Complexity 1 include/linux/err.h:IS_ERR Cyclomatic Complexity 3 include/linux/ktime.h:ktime_compare Cyclomatic Complexity 1 include/linux/ktime.h:ktime_add_us Cyclomatic Complexity 1 include/linux/device.h:devm_kzalloc Cyclomatic Complexity 1 include/linux/device.h:dev_get_drvdata Cyclomatic Complexity 1 include/linux/device.h:dev_set_drvdata Cyclomatic Complexity 5 include/linux/mii.h:mii_resolve_flowctrl_fdx Cyclomatic Complexity 1 include/linux/of.h:of_property_read_bool Cyclomatic Complexity 1 include/linux/phy.h:phy_is_pseudo_fixed_link Cyclomatic Complexity 1 include/linux/reset.h:reset_control_assert Cyclomatic Complexity 1 include/linux/reset.h:reset_control_deassert Cyclomatic Complexity 2 include/linux/reset.h:__devm_reset_control_get Cyclomatic Complexity 2 include/linux/reset.h:devm_reset_control_get_exclusive Cyclomatic Complexity 1 include/linux/reset.h:devm_reset_control_get Cyclomatic Complexity 1 include/net/dsa.h:dsa_to_port Cyclomatic Complexity 1 include/net/dsa.h:dsa_is_cpu_port Cyclomatic Complexity 1 include/net/dsa.h:dsa_is_user_port Cyclomatic Complexity 3 include/net/dsa.h:dsa_user_ports Cyclomatic Complexity 1 drivers/net/dsa/mt7530.h:mt7530_hw_vlan_entry_init Cyclomatic Complexity 1 drivers/net/dsa/mt7530.h:INIT_MT7530_DUMMY_POLL Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_get_strings Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_get_sset_count Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_port_vlan_prepare Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mdio_module_init Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_mii_read Cyclomatic Complexity 4 drivers/net/dsa/mt7530.c:mt7530_mii_write Cyclomatic Complexity 4 drivers/net/dsa/mt7530.c:core_read_mmd_indirect Cyclomatic Complexity 5 drivers/net/dsa/mt7530.c:core_write_mmd_indirect Cyclomatic Complexity 3 drivers/net/dsa/mt7530.c:mt7530_remove Cyclomatic Complexity 9 drivers/net/dsa/mt7530.c:mt7530_probe Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:_mt7530_read Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_read Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_fdb_read Cyclomatic Complexity 3 drivers/net/dsa/mt7530.c:mt7530_get_ethtool_stats Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_write Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_fdb_write Cyclomatic Complexity 3 drivers/net/dsa/mt7530.c:mt7530_hw_vlan_del Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_mib_reset Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_rmw Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_hw_vlan_add Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_port_set_vlan_aware Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_port_vlan_filtering Cyclomatic Complexity 5 drivers/net/dsa/mt7530.c:mt7530_stp_state_set Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_clear Cyclomatic Complexity 5 drivers/net/dsa/mt7530.c:mt7530_port_set_vlan_unaware Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_set Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7530_port_set_status Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_cpu_port_enable Cyclomatic Complexity 8 drivers/net/dsa/mt7530.c:mt7530_port_bridge_leave Cyclomatic Complexity 7 drivers/net/dsa/mt7530.c:mt7530_port_bridge_join Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_port_disable Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_port_enable Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:core_rmw Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:core_clear Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:core_set Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:core_write Cyclomatic Complexity 11 drivers/net/dsa/mt7530.c:mt7530_fdb_cmd Cyclomatic Complexity 8 drivers/net/dsa/mt7530.c:mt7530_port_fdb_dump Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_port_fdb_del Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_port_fdb_add Cyclomatic Complexity 9 drivers/net/dsa/mt7530.c:mt7530_vlan_cmd Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_hw_vlan_update Cyclomatic Complexity 4 drivers/net/dsa/mt7530.c:mt7530_port_vlan_del Cyclomatic Complexity 4 drivers/net/dsa/mt7530.c:mt7530_port_vlan_add Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7623_trgmii_read Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7623_trgmii_write Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7623_trgmii_rmw Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7623_trgmii_set Cyclomatic Complexity 7 drivers/net/dsa/mt7530.c:mt7530_pad_clk_setup Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7623_trgmii_clear Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mt7623_pad_clk_setup Cyclomatic Complexity 12 drivers/net/dsa/mt7530.c:mt7530_adjust_link Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_phy_write Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mt7530_phy_read Cyclomatic Complexity 16 drivers/net/dsa/mt7530.c:mt7530_setup Cyclomatic Complexity 2 drivers/net/dsa/mt7530.c:mtk_get_tag_protocol Cyclomatic Complexity 1 drivers/net/dsa/mt7530.c:mdio_module_exit vim +1324 drivers/net/dsa/mt7530.c 1121 1122 static void 1123 mt7530_port_vlan_add(struct dsa_switch *ds, int port, 1124 const struct switchdev_obj_port_vlan *vlan, 1125 struct switchdev_trans *trans) 1126 { 1127 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 1128 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 1129 struct mt7530_hw_vlan_entry new_entry; 1130 struct mt7530_priv *priv = ds->priv; > 1131 int ret; 1132 u16 vid; 1133 1134 /* The port is kept as VLAN-unaware if bridge with vlan_filtering not 1135 * being set. 1136 */ 1137 if (!priv->ports[port].vlan_filtering) 1138 return; 1139 1140 mutex_lock(&priv->reg_mutex); 1141 1142 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { 1143 mt7530_hw_vlan_entry_init(&new_entry, port, untagged); 1144 mt7530_hw_vlan_update(priv, vid, &new_entry, 1145 mt7530_hw_vlan_add); 1146 } 1147 1148 if (pvid) { 1149 mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, 1150 G0_PORT_VID(vlan->vid_end)); 1151 priv->ports[port].pvid = vlan->vid_end; 1152 } 1153 1154 mutex_unlock(&priv->reg_mutex); 1155 } 1156 1157 static int 1158 mt7530_port_vlan_del(struct dsa_switch *ds, int port, 1159 const struct switchdev_obj_port_vlan *vlan) 1160 { 1161 struct mt7530_hw_vlan_entry target_entry; 1162 struct mt7530_priv *priv = ds->priv; 1163 u16 vid, pvid; 1164 1165 /* The port is kept as VLAN-unaware if bridge with vlan_filtering not 1166 * being set. 1167 */ 1168 if (!priv->ports[port].vlan_filtering) 1169 return 0; 1170 1171 mutex_lock(&priv->reg_mutex); 1172 1173 pvid = priv->ports[port].pvid; 1174 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { 1175 mt7530_hw_vlan_entry_init(&target_entry, port, 0); 1176 mt7530_hw_vlan_update(priv, vid, &target_entry, 1177 mt7530_hw_vlan_del); 1178 1179 /* PVID is being restored to the default whenever the PVID port 1180 * is being removed from the VLAN. 1181 */ 1182 if (pvid == vid) 1183 pvid = G0_PORT_VID_DEF; 1184 } 1185 1186 mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, pvid); 1187 priv->ports[port].pvid = pvid; 1188 1189 mutex_unlock(&priv->reg_mutex); 1190 1191 return 0; 1192 } 1193 1194 static enum dsa_tag_protocol 1195 mtk_get_tag_protocol(struct dsa_switch *ds, int port) 1196 { 1197 struct mt7530_priv *priv = ds->priv; 1198 1199 if (port != MT7530_CPU_PORT) { 1200 dev_warn(priv->dev, 1201 "port not matched with tagging CPU port\n"); 1202 return DSA_TAG_PROTO_NONE; 1203 } else { 1204 return DSA_TAG_PROTO_MTK; 1205 } 1206 } 1207 1208 static int 1209 mt7530_setup(struct dsa_switch *ds) 1210 { 1211 struct mt7530_priv *priv = ds->priv; 1212 int ret, i; 1213 u32 id, val; 1214 struct device_node *dn; 1215 struct mt7530_dummy_poll p; 1216 1217 /* The parent node of master netdev which holds the common system 1218 * controller also is the container for two GMACs nodes representing 1219 * as two netdev instances. 1220 */ 1221 dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent; 1222 priv->ethernet = syscon_node_to_regmap(dn); 1223 if (IS_ERR(priv->ethernet)) 1224 return PTR_ERR(priv->ethernet); 1225 1226 regulator_set_voltage(priv->core_pwr, 1000000, 1000000); 1227 ret = regulator_enable(priv->core_pwr); 1228 if (ret < 0) { 1229 dev_err(priv->dev, 1230 "Failed to enable core power: %d\n", ret); 1231 return ret; 1232 } 1233 1234 regulator_set_voltage(priv->io_pwr, 3300000, 3300000); 1235 ret = regulator_enable(priv->io_pwr); 1236 if (ret < 0) { 1237 dev_err(priv->dev, "Failed to enable io pwr: %d\n", 1238 ret); 1239 return ret; 1240 } 1241 1242 /* Reset whole chip through gpio pin or memory-mapped registers for 1243 * different type of hardware 1244 */ 1245 if (priv->mcm) { 1246 reset_control_assert(priv->rstc); 1247 usleep_range(1000, 1100); 1248 reset_control_deassert(priv->rstc); 1249 } else { 1250 gpiod_set_value_cansleep(priv->reset, 0); 1251 usleep_range(1000, 1100); 1252 gpiod_set_value_cansleep(priv->reset, 1); 1253 } 1254 1255 /* Waiting for MT7530 got to stable */ 1256 INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); 1257 ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, 1258 20, 1000000); 1259 if (ret < 0) { 1260 dev_err(priv->dev, "reset timeout\n"); 1261 return ret; 1262 } 1263 1264 id = mt7530_read(priv, MT7530_CREV); 1265 id >>= CHIP_NAME_SHIFT; 1266 if (id != MT7530_ID) { 1267 dev_err(priv->dev, "chip %x can't be supported\n", id); 1268 return -ENODEV; 1269 } 1270 1271 /* Reset the switch through internal reset */ 1272 mt7530_write(priv, MT7530_SYS_CTRL, 1273 SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | 1274 SYS_CTRL_REG_RST); 1275 1276 /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ 1277 val = mt7530_read(priv, MT7530_MHWTRAP); 1278 val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; 1279 val |= MHWTRAP_MANUAL; 1280 mt7530_write(priv, MT7530_MHWTRAP, val); 1281 1282 /* Enable and reset MIB counters */ 1283 mt7530_mib_reset(ds); 1284 1285 mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK); 1286 1287 for (i = 0; i < MT7530_NUM_PORTS; i++) { 1288 /* Disable forwarding by default on all ports */ 1289 mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, 1290 PCR_MATRIX_CLR); 1291 1292 if (dsa_is_cpu_port(ds, i)) 1293 mt7530_cpu_port_enable(priv, i); 1294 else 1295 mt7530_port_disable(ds, i, NULL); 1296 } 1297 1298 /* Flush the FDB table */ 1299 ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, 0); 1300 if (ret < 0) 1301 return ret; 1302 1303 return 0; 1304 } 1305 1306 static const struct dsa_switch_ops mt7530_switch_ops = { 1307 .get_tag_protocol = mtk_get_tag_protocol, 1308 .setup = mt7530_setup, 1309 .get_strings = mt7530_get_strings, 1310 .phy_read = mt7530_phy_read, 1311 .phy_write = mt7530_phy_write, 1312 .get_ethtool_stats = mt7530_get_ethtool_stats, 1313 .get_sset_count = mt7530_get_sset_count, 1314 .adjust_link = mt7530_adjust_link, 1315 .port_enable = mt7530_port_enable, 1316 .port_disable = mt7530_port_disable, 1317 .port_stp_state_set = mt7530_stp_state_set, 1318 .port_bridge_join = mt7530_port_bridge_join, 1319 .port_bridge_leave = mt7530_port_bridge_leave, 1320 .port_fdb_add = mt7530_port_fdb_add, 1321 .port_fdb_del = mt7530_port_fdb_del, 1322 .port_fdb_dump = mt7530_port_fdb_dump, 1323 .port_vlan_filtering = mt7530_port_vlan_filtering, > 1324 .port_vlan_prepare = mt7530_port_vlan_prepare, 1325 .port_vlan_add = mt7530_port_vlan_add, 1326 .port_vlan_del = mt7530_port_vlan_del, 1327 }; 1328 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 2820d69..252e8ba 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -805,6 +805,69 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port, } static void +mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port) +{ + struct mt7530_priv *priv = ds->priv; + bool all_user_ports_removed = true; + int i; + + /* When a port is removed from the bridge, the port would be set up + * back to the default as is at initial boot which is a VLAN-unaware + * port. + */ + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, + MT7530_PORT_MATRIX_MODE); + mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK, + VLAN_ATTR(MT7530_VLAN_TRANSPARENT)); + + priv->ports[port].vlan_filtering = false; + + for (i = 0; i < MT7530_NUM_PORTS; i++) { + if (dsa_is_user_port(ds, i) && + priv->ports[i].vlan_filtering) { + all_user_ports_removed = false; + break; + } + } + + /* CPU port also does the same thing until all user ports belonging to + * the CPU port get out of VLAN filtering mode. + */ + if (all_user_ports_removed) { + mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT), + PCR_MATRIX(dsa_user_ports(priv->ds))); + mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT), + PORT_SPEC_TAG); + } +} + +static void +mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port) +{ + struct mt7530_priv *priv = ds->priv; + + /* The real fabric path would be decided on the membership in the + * entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS + * means potential VLAN can be consisting of certain subset of all + * ports. + */ + mt7530_rmw(priv, MT7530_PCR_P(port), + PCR_MATRIX_MASK, PCR_MATRIX(MT7530_ALL_MEMBERS)); + + /* Trapped into security mode allows packet forwarding through VLAN + * table lookup. + */ + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, + MT7530_PORT_SECURITY_MODE); + + /* Set the port as a user port which is to be able to recognize VID + * from incoming packets before fetching entry within the VLAN table. + */ + mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK, + VLAN_ATTR(MT7530_VLAN_USER)); +} + +static void mt7530_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *bridge) { @@ -817,8 +880,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, /* Remove this port from the port matrix of the other ports * in the same bridge. If the port is disabled, port matrix * is kept and not being setup until the port becomes enabled. + * And the other port's port matrix cannot be broken when the + * other port is still a VLAN-aware port. */ - if (dsa_is_user_port(ds, i) && i != port) { + if (!priv->ports[i].vlan_filtering && + dsa_is_user_port(ds, i) && i != port) { if (dsa_to_port(ds, i)->bridge_dev != bridge) continue; if (priv->ports[i].enable) @@ -836,6 +902,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, PCR_MATRIX(BIT(MT7530_CPU_PORT))); priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); + mt7530_port_set_vlan_unaware(ds, port); + mutex_unlock(&priv->reg_mutex); } @@ -906,6 +974,223 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port, return 0; } +static int +mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid) +{ + struct mt7530_dummy_poll p; + u32 val; + int ret; + + val = VTCR_BUSY | VTCR_FUNC(cmd) | vid; + mt7530_write(priv, MT7530_VTCR, val); + + INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR); + ret = readx_poll_timeout(_mt7530_read, &p, val, + !(val & VTCR_BUSY), 20, 20000); + if (ret < 0) { + dev_err(priv->dev, "poll timeout\n"); + return ret; + } + + val = mt7530_read(priv, MT7530_VTCR); + if (val & VTCR_INVALID) { + dev_err(priv->dev, "read VTCR invalid\n"); + return -EINVAL; + } + + return 0; +} + +static int +mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering) +{ + struct mt7530_priv *priv = ds->priv; + + priv->ports[port].vlan_filtering = vlan_filtering; + + if (vlan_filtering) { + /* The port is being kept as VLAN-unaware port when bridge is + * set up with vlan_filtering not being set, Otherwise, the + * port and the corresponding CPU port is required the setup + * for becoming a VLAN-aware port. + */ + mt7530_port_set_vlan_aware(ds, port); + mt7530_port_set_vlan_aware(ds, MT7530_CPU_PORT); + } + + return 0; +} + +static int +mt7530_port_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + /* nothing needed */ + + return 0; +} + +static void +mt7530_hw_vlan_add(struct mt7530_priv *priv, + struct mt7530_hw_vlan_entry *entry) +{ + u8 new_members; + u32 val; + + new_members = entry->old_members | BIT(entry->port) | + BIT(MT7530_CPU_PORT); + + /* Validate the entry with independent learning, create egress tag per + * VLAN and joining the port as one of the port members. + */ + val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID; + mt7530_write(priv, MT7530_VAWD1, val); + + /* Decide whether adding tag or not for those outgoing packets from the + * port inside the VLAN. + */ + val = entry->untagged ? MT7530_VLAN_EGRESS_UNTAG : + MT7530_VLAN_EGRESS_TAG; + mt7530_rmw(priv, MT7530_VAWD2, + ETAG_CTRL_P_MASK(entry->port), + ETAG_CTRL_P(entry->port, val)); + + /* CPU port is always taken as a tagged port for serving more than one + * VLANs across and also being applied with egress type stack mode for + * that VLAN tags would be appended after hardware special tag used as + * DSA tag. + */ + mt7530_rmw(priv, MT7530_VAWD2, + ETAG_CTRL_P_MASK(MT7530_CPU_PORT), + ETAG_CTRL_P(MT7530_CPU_PORT, + MT7530_VLAN_EGRESS_STACK)); +} + +static void +mt7530_hw_vlan_del(struct mt7530_priv *priv, + struct mt7530_hw_vlan_entry *entry) +{ + u8 new_members; + u32 val; + + new_members = entry->old_members & ~BIT(entry->port); + + val = mt7530_read(priv, MT7530_VAWD1); + if (!(val & VLAN_VALID)) { + dev_err(priv->dev, + "Cannot be deleted due to invalid entry\n"); + return; + } + + /* If certain member apart from CPU port is still alive in the VLAN, + * the entry would be kept valid. Otherwise, the entry is got to be + * disabled. + */ + if (new_members && new_members != BIT(MT7530_CPU_PORT)) { + val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | + VLAN_VALID; + mt7530_write(priv, MT7530_VAWD1, val); + } else { + mt7530_write(priv, MT7530_VAWD1, 0); + mt7530_write(priv, MT7530_VAWD2, 0); + } +} + +static void +mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid, + struct mt7530_hw_vlan_entry *entry, + mt7530_vlan_op vlan_op) +{ + u32 val; + + /* Fetch entry */ + mt7530_vlan_cmd(priv, MT7530_VTCR_RD_VID, vid); + + val = mt7530_read(priv, MT7530_VAWD1); + + entry->old_members = (val >> PORT_MEM_SHFT) & PORT_MEM_MASK; + + /* Manipulate entry */ + vlan_op(priv, entry); + + /* Flush result to hardware */ + mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, vid); +} + +static void +mt7530_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct mt7530_hw_vlan_entry new_entry; + struct mt7530_priv *priv = ds->priv; + int ret; + u16 vid; + + /* The port is kept as VLAN-unaware if bridge with vlan_filtering not + * being set. + */ + if (!priv->ports[port].vlan_filtering) + return; + + mutex_lock(&priv->reg_mutex); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + mt7530_hw_vlan_entry_init(&new_entry, port, untagged); + mt7530_hw_vlan_update(priv, vid, &new_entry, + mt7530_hw_vlan_add); + } + + if (pvid) { + mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, + G0_PORT_VID(vlan->vid_end)); + priv->ports[port].pvid = vlan->vid_end; + } + + mutex_unlock(&priv->reg_mutex); +} + +static int +mt7530_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct mt7530_hw_vlan_entry target_entry; + struct mt7530_priv *priv = ds->priv; + u16 vid, pvid; + + /* The port is kept as VLAN-unaware if bridge with vlan_filtering not + * being set. + */ + if (!priv->ports[port].vlan_filtering) + return 0; + + mutex_lock(&priv->reg_mutex); + + pvid = priv->ports[port].pvid; + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + mt7530_hw_vlan_entry_init(&target_entry, port, 0); + mt7530_hw_vlan_update(priv, vid, &target_entry, + mt7530_hw_vlan_del); + + /* PVID is being restored to the default whenever the PVID port + * is being removed from the VLAN. + */ + if (pvid == vid) + pvid = G0_PORT_VID_DEF; + } + + mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, pvid); + priv->ports[port].pvid = pvid; + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + static enum dsa_tag_protocol mtk_get_tag_protocol(struct dsa_switch *ds, int port) { @@ -1035,6 +1320,10 @@ static const struct dsa_switch_ops mt7530_switch_ops = { .port_fdb_add = mt7530_port_fdb_add, .port_fdb_del = mt7530_port_fdb_del, .port_fdb_dump = mt7530_port_fdb_dump, + .port_vlan_filtering = mt7530_port_vlan_filtering, + .port_vlan_prepare = mt7530_port_vlan_prepare, + .port_vlan_add = mt7530_port_vlan_add, + .port_vlan_del = mt7530_port_vlan_del, }; static int diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 74db982..d9b407a 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -17,6 +17,7 @@ #define MT7530_NUM_PORTS 7 #define MT7530_CPU_PORT 6 #define MT7530_NUM_FDB_RECORDS 2048 +#define MT7530_ALL_MEMBERS 0xff #define NUM_TRGMII_CTRL 5 @@ -88,21 +89,42 @@ enum mt7530_fdb_cmd { /* Register for vlan table control */ #define MT7530_VTCR 0x90 #define VTCR_BUSY BIT(31) -#define VTCR_FUNC (((x) & 0xf) << 12) -#define VTCR_FUNC_RD_VID 0x1 -#define VTCR_FUNC_WR_VID 0x2 -#define VTCR_FUNC_INV_VID 0x3 -#define VTCR_FUNC_VAL_VID 0x4 +#define VTCR_INVALID BIT(16) +#define VTCR_FUNC(x) (((x) & 0xf) << 12) #define VTCR_VID ((x) & 0xfff) +enum mt7530_vlan_cmd { + /* Read/Write the specified VID entry from VAWD register based + * on VID. + */ + MT7530_VTCR_RD_VID = 0, + MT7530_VTCR_WR_VID = 1, +}; + /* Register for setup vlan and acl write data */ #define MT7530_VAWD1 0x94 #define PORT_STAG BIT(31) +/* Independent VLAN Learning */ #define IVL_MAC BIT(30) +/* Per VLAN Egress Tag Control */ +#define VTAG_EN BIT(28) +/* VLAN Member Control */ #define PORT_MEM(x) (((x) & 0xff) << 16) -#define VALID BIT(1) +/* VLAN Entry Valid */ +#define VLAN_VALID BIT(0) +#define PORT_MEM_SHFT 16 +#define PORT_MEM_MASK 0xff #define MT7530_VAWD2 0x98 +/* Egress Tag Control */ +#define ETAG_CTRL_P(p, x) (((x) & 0x3) << ((p) << 1)) +#define ETAG_CTRL_P_MASK(p) ETAG_CTRL_P(p, 3) + +enum mt7530_vlan_egress_attr { + MT7530_VLAN_EGRESS_UNTAG = 0, + MT7530_VLAN_EGRESS_TAG = 2, + MT7530_VLAN_EGRESS_STACK = 3, +}; /* Register for port STP state control */ #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) @@ -120,11 +142,23 @@ enum mt7530_stp_state { /* Register for port control */ #define MT7530_PCR_P(x) (0x2004 + ((x) * 0x100)) #define PORT_VLAN(x) ((x) & 0x3) + +enum mt7530_port_mode { + /* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */ + MT7530_PORT_MATRIX_MODE = PORT_VLAN(0), + + /* Security Mode: Discard any frame due to ingress membership + * violation or VID missed on the VLAN table. + */ + MT7530_PORT_SECURITY_MODE = PORT_VLAN(3), +}; + #define PCR_MATRIX(x) (((x) & 0xff) << 16) #define PORT_PRI(x) (((x) & 0x7) << 24) #define EG_TAG(x) (((x) & 0x3) << 28) #define PCR_MATRIX_MASK PCR_MATRIX(0xff) #define PCR_MATRIX_CLR PCR_MATRIX(0) +#define PCR_PORT_VLAN_MASK PORT_VLAN(3) /* Register for port security control */ #define MT7530_PSC_P(x) (0x200c + ((x) * 0x100)) @@ -134,10 +168,20 @@ enum mt7530_stp_state { #define MT7530_PVC_P(x) (0x2010 + ((x) * 0x100)) #define PORT_SPEC_TAG BIT(5) #define VLAN_ATTR(x) (((x) & 0x3) << 6) +#define VLAN_ATTR_MASK VLAN_ATTR(3) + +enum mt7530_vlan_port_attr { + MT7530_VLAN_USER = 0, + MT7530_VLAN_TRANSPARENT = 3, +}; + #define STAG_VPID (((x) & 0xffff) << 16) /* Register for port port-and-protocol based vlan 1 control */ #define MT7530_PPBV1_P(x) (0x2014 + ((x) * 0x100)) +#define G0_PORT_VID(x) (((x) & 0xfff) << 0) +#define G0_PORT_VID_MASK G0_PORT_VID(0xfff) +#define G0_PORT_VID_DEF G0_PORT_VID(1) /* Register for port MAC control register */ #define MT7530_PMCR_P(x) (0x3000 + ((x) * 0x100)) @@ -345,9 +389,20 @@ struct mt7530_fdb { bool noarp; }; +/* struct mt7530_port - This is the main data structure for holding the state + * of the port. + * @enable: The status used for show port is enabled or not. + * @pm: The matrix used to show all connections with the port. + * @pvid: The VLAN specified is to be considered a PVID at ingress. Any + * untagged frames will be assigned to the related VLAN. + * @vlan_filtering: The flags indicating whether the port that can recognize + * VLAN-tagged frames. + */ struct mt7530_port { bool enable; u32 pm; + u16 pvid; + bool vlan_filtering; }; /* struct mt7530_priv - This is the main data structure for holding the state @@ -382,6 +437,22 @@ struct mt7530_priv { struct mutex reg_mutex; }; +struct mt7530_hw_vlan_entry { + int port; + u8 old_members; + bool untagged; +}; + +static inline void mt7530_hw_vlan_entry_init(struct mt7530_hw_vlan_entry *e, + int port, bool untagged) +{ + e->port = port; + e->untagged = untagged; +} + +typedef void (*mt7530_vlan_op)(struct mt7530_priv *, + struct mt7530_hw_vlan_entry *); + struct mt7530_hw_stats { const char *string; u16 reg;