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: yt921x: Add LAG offloading support

Add offloading for a link aggregation group supported by the YT921x
switches.

Signed-off-by: David Yang <mmyangfl@gmail.com>
Link: https://patch.msgid.link/20260117162116.1063043-1-mmyangfl@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

David Yang and committed by
Paolo Abeni
0b42aeb4 a7c708dc

+206
+186
drivers/net/dsa/yt921x.c
··· 1117 1117 return res; 1118 1118 } 1119 1119 1120 + static int yt921x_lag_hash(struct yt921x_priv *priv, u32 ctrl, bool unique_lag, 1121 + struct netlink_ext_ack *extack) 1122 + { 1123 + u32 val; 1124 + int res; 1125 + 1126 + /* Hash Mode is global. Make sure the same Hash Mode is set to all the 1127 + * 2 possible lags. 1128 + * If we are the unique LAG we can set whatever hash mode we want. 1129 + * To change hash mode it's needed to remove all LAG and change the mode 1130 + * with the latest. 1131 + */ 1132 + if (unique_lag) { 1133 + res = yt921x_reg_write(priv, YT921X_LAG_HASH, ctrl); 1134 + if (res) 1135 + return res; 1136 + } else { 1137 + res = yt921x_reg_read(priv, YT921X_LAG_HASH, &val); 1138 + if (res) 1139 + return res; 1140 + 1141 + if (val != ctrl) { 1142 + NL_SET_ERR_MSG_MOD(extack, 1143 + "Mismatched Hash Mode across different lags is not supported"); 1144 + return -EOPNOTSUPP; 1145 + } 1146 + } 1147 + 1148 + return 0; 1149 + } 1150 + 1151 + static int yt921x_lag_set(struct yt921x_priv *priv, u8 index, u16 ports_mask) 1152 + { 1153 + unsigned long targets_mask = ports_mask; 1154 + unsigned int cnt; 1155 + u32 ctrl; 1156 + int port; 1157 + int res; 1158 + 1159 + cnt = 0; 1160 + for_each_set_bit(port, &targets_mask, YT921X_PORT_NUM) { 1161 + ctrl = YT921X_LAG_MEMBER_PORT(port); 1162 + res = yt921x_reg_write(priv, YT921X_LAG_MEMBERnm(index, cnt), 1163 + ctrl); 1164 + if (res) 1165 + return res; 1166 + 1167 + cnt++; 1168 + } 1169 + 1170 + ctrl = YT921X_LAG_GROUP_PORTS(ports_mask) | 1171 + YT921X_LAG_GROUP_MEMBER_NUM(cnt); 1172 + return yt921x_reg_write(priv, YT921X_LAG_GROUPn(index), ctrl); 1173 + } 1174 + 1175 + static int 1176 + yt921x_dsa_port_lag_leave(struct dsa_switch *ds, int port, struct dsa_lag lag) 1177 + { 1178 + struct yt921x_priv *priv = to_yt921x_priv(ds); 1179 + struct dsa_port *dp; 1180 + u32 ctrl; 1181 + int res; 1182 + 1183 + if (!lag.id) 1184 + return -EINVAL; 1185 + 1186 + ctrl = 0; 1187 + dsa_lag_foreach_port(dp, ds->dst, &lag) 1188 + ctrl |= BIT(dp->index); 1189 + 1190 + mutex_lock(&priv->reg_lock); 1191 + res = yt921x_lag_set(priv, lag.id - 1, ctrl); 1192 + mutex_unlock(&priv->reg_lock); 1193 + 1194 + return res; 1195 + } 1196 + 1197 + static int 1198 + yt921x_dsa_port_lag_check(struct dsa_switch *ds, struct dsa_lag lag, 1199 + struct netdev_lag_upper_info *info, 1200 + struct netlink_ext_ack *extack) 1201 + { 1202 + unsigned int members; 1203 + struct dsa_port *dp; 1204 + 1205 + if (!lag.id) 1206 + return -EINVAL; 1207 + 1208 + members = 0; 1209 + dsa_lag_foreach_port(dp, ds->dst, &lag) 1210 + /* Includes the port joining the LAG */ 1211 + members++; 1212 + 1213 + if (members > YT921X_LAG_PORT_NUM) { 1214 + NL_SET_ERR_MSG_MOD(extack, 1215 + "Cannot offload more than 4 LAG ports"); 1216 + return -EOPNOTSUPP; 1217 + } 1218 + 1219 + if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) { 1220 + NL_SET_ERR_MSG_MOD(extack, 1221 + "Can only offload LAG using hash TX type"); 1222 + return -EOPNOTSUPP; 1223 + } 1224 + 1225 + if (info->hash_type != NETDEV_LAG_HASH_L2 && 1226 + info->hash_type != NETDEV_LAG_HASH_L23 && 1227 + info->hash_type != NETDEV_LAG_HASH_L34) { 1228 + NL_SET_ERR_MSG_MOD(extack, 1229 + "Can only offload L2 or L2+L3 or L3+L4 TX hash"); 1230 + return -EOPNOTSUPP; 1231 + } 1232 + 1233 + return 0; 1234 + } 1235 + 1236 + static int 1237 + yt921x_dsa_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag, 1238 + struct netdev_lag_upper_info *info, 1239 + struct netlink_ext_ack *extack) 1240 + { 1241 + struct yt921x_priv *priv = to_yt921x_priv(ds); 1242 + struct dsa_port *dp; 1243 + bool unique_lag; 1244 + unsigned int i; 1245 + u32 ctrl; 1246 + int res; 1247 + 1248 + res = yt921x_dsa_port_lag_check(ds, lag, info, extack); 1249 + if (res) 1250 + return res; 1251 + 1252 + ctrl = 0; 1253 + switch (info->hash_type) { 1254 + case NETDEV_LAG_HASH_L34: 1255 + ctrl |= YT921X_LAG_HASH_IP_DST; 1256 + ctrl |= YT921X_LAG_HASH_IP_SRC; 1257 + ctrl |= YT921X_LAG_HASH_IP_PROTO; 1258 + 1259 + ctrl |= YT921X_LAG_HASH_L4_DPORT; 1260 + ctrl |= YT921X_LAG_HASH_L4_SPORT; 1261 + break; 1262 + case NETDEV_LAG_HASH_L23: 1263 + ctrl |= YT921X_LAG_HASH_MAC_DA; 1264 + ctrl |= YT921X_LAG_HASH_MAC_SA; 1265 + 1266 + ctrl |= YT921X_LAG_HASH_IP_DST; 1267 + ctrl |= YT921X_LAG_HASH_IP_SRC; 1268 + ctrl |= YT921X_LAG_HASH_IP_PROTO; 1269 + break; 1270 + case NETDEV_LAG_HASH_L2: 1271 + ctrl |= YT921X_LAG_HASH_MAC_DA; 1272 + ctrl |= YT921X_LAG_HASH_MAC_SA; 1273 + break; 1274 + default: 1275 + return -EOPNOTSUPP; 1276 + } 1277 + 1278 + /* Check if we are the unique configured LAG */ 1279 + unique_lag = true; 1280 + dsa_lags_foreach_id(i, ds->dst) 1281 + if (i != lag.id && dsa_lag_by_id(ds->dst, i)) { 1282 + unique_lag = false; 1283 + break; 1284 + } 1285 + 1286 + mutex_lock(&priv->reg_lock); 1287 + do { 1288 + res = yt921x_lag_hash(priv, ctrl, unique_lag, extack); 1289 + if (res) 1290 + break; 1291 + 1292 + ctrl = 0; 1293 + dsa_lag_foreach_port(dp, ds->dst, &lag) 1294 + ctrl |= BIT(dp->index); 1295 + res = yt921x_lag_set(priv, lag.id - 1, ctrl); 1296 + } while (0); 1297 + mutex_unlock(&priv->reg_lock); 1298 + 1299 + return res; 1300 + } 1301 + 1120 1302 static int yt921x_fdb_wait(struct yt921x_priv *priv, u32 *valp) 1121 1303 { 1122 1304 struct device *dev = to_device(priv); ··· 3062 2880 /* mirror */ 3063 2881 .port_mirror_del = yt921x_dsa_port_mirror_del, 3064 2882 .port_mirror_add = yt921x_dsa_port_mirror_add, 2883 + /* lag */ 2884 + .port_lag_leave = yt921x_dsa_port_lag_leave, 2885 + .port_lag_join = yt921x_dsa_port_lag_join, 3065 2886 /* fdb */ 3066 2887 .port_fdb_dump = yt921x_dsa_port_fdb_dump, 3067 2888 .port_fast_age = yt921x_dsa_port_fast_age, ··· 3161 2976 ds->ageing_time_min = 1 * 5000; 3162 2977 ds->ageing_time_max = U16_MAX * 5000; 3163 2978 ds->phylink_mac_ops = &yt921x_phylink_mac_ops; 2979 + ds->num_lag_ids = YT921X_LAG_NUM; 3164 2980 ds->num_ports = YT921X_PORT_NUM; 3165 2981 3166 2982 mdiodev_set_drvdata(mdiodev, priv);
+20
drivers/net/dsa/yt921x.h
··· 370 370 #define YT921X_FILTER_PORTn(port) BIT(port) 371 371 #define YT921X_VLAN_EGR_FILTER 0x180598 372 372 #define YT921X_VLAN_EGR_FILTER_PORTn(port) BIT(port) 373 + #define YT921X_LAG_GROUPn(n) (0x1805a8 + 4 * (n)) 374 + #define YT921X_LAG_GROUP_PORTS_M GENMASK(13, 3) 375 + #define YT921X_LAG_GROUP_PORTS(x) FIELD_PREP(YT921X_LAG_GROUP_PORTS_M, (x)) 376 + #define YT921X_LAG_GROUP_MEMBER_NUM_M GENMASK(2, 0) 377 + #define YT921X_LAG_GROUP_MEMBER_NUM(x) FIELD_PREP(YT921X_LAG_GROUP_MEMBER_NUM_M, (x)) 378 + #define YT921X_LAG_MEMBERnm(n, m) (0x1805b0 + 4 * (4 * (n) + (m))) 379 + #define YT921X_LAG_MEMBER_PORT_M GENMASK(3, 0) 380 + #define YT921X_LAG_MEMBER_PORT(x) FIELD_PREP(YT921X_LAG_MEMBER_PORT_M, (x)) 373 381 #define YT921X_CPU_COPY 0x180690 374 382 #define YT921X_CPU_COPY_FORCE_INT_PORT BIT(2) 375 383 #define YT921X_CPU_COPY_TO_INT_CPU BIT(1) ··· 422 414 #define YT921X_PORT_IGR_TPIDn_STAG(x) BIT((x) + 4) 423 415 #define YT921X_PORT_IGR_TPIDn_CTAG_M GENMASK(3, 0) 424 416 #define YT921X_PORT_IGR_TPIDn_CTAG(x) BIT(x) 417 + #define YT921X_LAG_HASH 0x210090 418 + #define YT921X_LAG_HASH_L4_SPORT BIT(7) 419 + #define YT921X_LAG_HASH_L4_DPORT BIT(6) 420 + #define YT921X_LAG_HASH_IP_PROTO BIT(5) 421 + #define YT921X_LAG_HASH_IP_SRC BIT(4) 422 + #define YT921X_LAG_HASH_IP_DST BIT(3) 423 + #define YT921X_LAG_HASH_MAC_SA BIT(2) 424 + #define YT921X_LAG_HASH_MAC_DA BIT(1) 425 + #define YT921X_LAG_HASH_SRC_PORT BIT(0) 425 426 426 427 #define YT921X_PORTn_VLAN_CTRL(port) (0x230010 + 4 * (port)) 427 428 #define YT921X_PORT_VLAN_CTRL_SVLAN_PRI_EN BIT(31) ··· 474 457 }; 475 458 476 459 #define YT921X_MSTI_NUM 16 460 + 461 + #define YT921X_LAG_NUM 2 462 + #define YT921X_LAG_PORT_NUM 4 477 463 478 464 #define YT9215_MAJOR 0x9002 479 465 #define YT9218_MAJOR 0x9001