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

Merge branch 'dsa-mv88e6xxx-g2-cleanup-stp'

Vivien Didelot says:

====================
net: dsa: mv88e6xxx: Global2 cleanup and STP

The Marvell switches registers are organized in distinct internal SMI
devices, such as PHY, Port, Global 1 or Global 2 registers sets.

Since not all chips support every registers sets or have slightly
differences in them (such as old 88E6060 or new 88E6390 likely to be
supported soon), make the setup code clearer now by removing a few
family checks and adding flags to describe the Global 2 registers map.

This patchset enables basic STP support and bridging on most chips when
getting rid of a few inconsistencies in chip descriptions (patch 1) and
add bridge Ageing Time support to DSA and the mv88e6xxx driver.

Changes v2 -> v3:
- rename mv88e6xxx_update_write to mv88e6xxx_update
- set fastest ageing time in use in the chip for multiple bridges,
tested with a few printk

Changes v1 -> v2:
- add a write helper for pointer-data Update registers
- add ageing time support
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+496 -259
+362 -202
drivers/net/dsa/mv88e6xxx/chip.c
··· 216 216 return 0; 217 217 } 218 218 219 + /* Indirect write to single pointer-data register with an Update bit */ 220 + static int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, 221 + u16 update) 222 + { 223 + u16 val; 224 + int i, err; 225 + 226 + /* Wait until the previous operation is completed */ 227 + for (i = 0; i < 16; ++i) { 228 + err = mv88e6xxx_read(chip, addr, reg, &val); 229 + if (err) 230 + return err; 231 + 232 + if (!(val & BIT(15))) 233 + break; 234 + } 235 + 236 + if (i == 16) 237 + return -ETIMEDOUT; 238 + 239 + /* Set the Update bit to trigger a write operation */ 240 + val = BIT(15) | update; 241 + 242 + return mv88e6xxx_write(chip, addr, reg, val); 243 + } 244 + 219 245 static int _mv88e6xxx_reg_read(struct mv88e6xxx_chip *chip, int addr, int reg) 220 246 { 221 247 u16 val; ··· 281 255 mutex_unlock(&chip->reg_lock); 282 256 283 257 return ret; 284 - } 285 - 286 - static int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr) 287 - { 288 - struct mv88e6xxx_chip *chip = ds_to_priv(ds); 289 - int err; 290 - 291 - err = mv88e6xxx_reg_write(chip, REG_GLOBAL, GLOBAL_MAC_01, 292 - (addr[0] << 8) | addr[1]); 293 - if (err) 294 - return err; 295 - 296 - err = mv88e6xxx_reg_write(chip, REG_GLOBAL, GLOBAL_MAC_23, 297 - (addr[2] << 8) | addr[3]); 298 - if (err) 299 - return err; 300 - 301 - return mv88e6xxx_reg_write(chip, REG_GLOBAL, GLOBAL_MAC_45, 302 - (addr[4] << 8) | addr[5]); 303 - } 304 - 305 - static int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) 306 - { 307 - struct mv88e6xxx_chip *chip = ds_to_priv(ds); 308 - int ret; 309 - int i; 310 - 311 - for (i = 0; i < 6; i++) { 312 - int j; 313 - 314 - /* Write the MAC address byte. */ 315 - ret = mv88e6xxx_reg_write(chip, REG_GLOBAL2, GLOBAL2_SWITCH_MAC, 316 - GLOBAL2_SWITCH_MAC_BUSY | 317 - (i << 8) | addr[i]); 318 - if (ret) 319 - return ret; 320 - 321 - /* Wait for the write to complete. */ 322 - for (j = 0; j < 16; j++) { 323 - ret = mv88e6xxx_reg_read(chip, REG_GLOBAL2, 324 - GLOBAL2_SWITCH_MAC); 325 - if (ret < 0) 326 - return ret; 327 - 328 - if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0) 329 - break; 330 - } 331 - if (j == 16) 332 - return -ETIMEDOUT; 333 - } 334 - 335 - return 0; 336 - } 337 - 338 - static int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr) 339 - { 340 - struct mv88e6xxx_chip *chip = ds_to_priv(ds); 341 - 342 - if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_SWITCH_MAC)) 343 - return mv88e6xxx_set_addr_indirect(ds, addr); 344 - else 345 - return mv88e6xxx_set_addr_direct(ds, addr); 346 258 } 347 259 348 260 static int mv88e6xxx_mdio_read_direct(struct mv88e6xxx_chip *chip, ··· 1424 1460 int stp_state; 1425 1461 int err; 1426 1462 1427 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_PORTSTATE)) 1428 - return; 1429 - 1430 1463 switch (state) { 1431 1464 case BR_STATE_DISABLED: 1432 1465 stp_state = PORT_CONTROL_STATE_DISABLED; ··· 2359 2398 const struct switchdev_obj_port_fdb *fdb, 2360 2399 struct switchdev_trans *trans) 2361 2400 { 2362 - struct mv88e6xxx_chip *chip = ds_to_priv(ds); 2363 - 2364 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_ATU)) 2365 - return -EOPNOTSUPP; 2366 - 2367 2401 /* We don't need any dynamic resource from the kernel (yet), 2368 2402 * so skip the prepare phase. 2369 2403 */ ··· 2374 2418 GLOBAL_ATU_DATA_STATE_UC_STATIC; 2375 2419 struct mv88e6xxx_chip *chip = ds_to_priv(ds); 2376 2420 2377 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_ATU)) 2378 - return; 2379 - 2380 2421 mutex_lock(&chip->reg_lock); 2381 2422 if (_mv88e6xxx_port_fdb_load(chip, port, fdb->addr, fdb->vid, state)) 2382 2423 netdev_err(ds->ports[port].netdev, ··· 2386 2433 { 2387 2434 struct mv88e6xxx_chip *chip = ds_to_priv(ds); 2388 2435 int ret; 2389 - 2390 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_ATU)) 2391 - return -EOPNOTSUPP; 2392 2436 2393 2437 mutex_lock(&chip->reg_lock); 2394 2438 ret = _mv88e6xxx_port_fdb_load(chip, port, fdb->addr, fdb->vid, ··· 2492 2542 u16 fid; 2493 2543 int err; 2494 2544 2495 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_ATU)) 2496 - return -EOPNOTSUPP; 2497 - 2498 2545 mutex_lock(&chip->reg_lock); 2499 2546 2500 2547 /* Dump port's default Filtering Information Database (VLAN ID 0) */ ··· 2534 2587 struct mv88e6xxx_chip *chip = ds_to_priv(ds); 2535 2588 int i, err = 0; 2536 2589 2537 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VLANTABLE)) 2538 - return -EOPNOTSUPP; 2539 - 2540 2590 mutex_lock(&chip->reg_lock); 2541 2591 2542 2592 /* Assign the bridge and remap each port's VLANTable */ ··· 2557 2613 struct mv88e6xxx_chip *chip = ds_to_priv(ds); 2558 2614 struct net_device *bridge = chip->ports[port].bridge_dev; 2559 2615 int i; 2560 - 2561 - if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VLANTABLE)) 2562 - return; 2563 2616 2564 2617 mutex_lock(&chip->reg_lock); 2565 2618 ··· 2957 3016 return 0; 2958 3017 } 2959 3018 2960 - static int mv88e6xxx_setup_global(struct mv88e6xxx_chip *chip) 3019 + static int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) 3020 + { 3021 + int err; 3022 + 3023 + err = mv88e6xxx_write(chip, REG_GLOBAL, GLOBAL_MAC_01, 3024 + (addr[0] << 8) | addr[1]); 3025 + if (err) 3026 + return err; 3027 + 3028 + err = mv88e6xxx_write(chip, REG_GLOBAL, GLOBAL_MAC_23, 3029 + (addr[2] << 8) | addr[3]); 3030 + if (err) 3031 + return err; 3032 + 3033 + return mv88e6xxx_write(chip, REG_GLOBAL, GLOBAL_MAC_45, 3034 + (addr[4] << 8) | addr[5]); 3035 + } 3036 + 3037 + static int mv88e6xxx_g1_set_age_time(struct mv88e6xxx_chip *chip, 3038 + unsigned int msecs) 3039 + { 3040 + const unsigned int coeff = chip->info->age_time_coeff; 3041 + const unsigned int min = 0x01 * coeff; 3042 + const unsigned int max = 0xff * coeff; 3043 + u8 age_time; 3044 + u16 val; 3045 + int err; 3046 + 3047 + if (msecs < min || msecs > max) 3048 + return -ERANGE; 3049 + 3050 + /* Round to nearest multiple of coeff */ 3051 + age_time = (msecs + coeff / 2) / coeff; 3052 + 3053 + err = mv88e6xxx_read(chip, REG_GLOBAL, GLOBAL_ATU_CONTROL, &val); 3054 + if (err) 3055 + return err; 3056 + 3057 + /* AgeTime is 11:4 bits */ 3058 + val &= ~0xff0; 3059 + val |= age_time << 4; 3060 + 3061 + return mv88e6xxx_write(chip, REG_GLOBAL, GLOBAL_ATU_CONTROL, val); 3062 + } 3063 + 3064 + static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds, 3065 + unsigned int ageing_time) 3066 + { 3067 + struct mv88e6xxx_chip *chip = ds_to_priv(ds); 3068 + int err; 3069 + 3070 + mutex_lock(&chip->reg_lock); 3071 + err = mv88e6xxx_g1_set_age_time(chip, ageing_time); 3072 + mutex_unlock(&chip->reg_lock); 3073 + 3074 + return err; 3075 + } 3076 + 3077 + static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) 2961 3078 { 2962 3079 struct dsa_switch *ds = chip->ds; 2963 3080 u32 upstream_port = dsa_upstream_port(ds); 2964 3081 u16 reg; 2965 3082 int err; 2966 - int i; 2967 3083 2968 3084 /* Enable the PHY Polling Unit if present, don't discard any packets, 2969 3085 * and mask all interrupt sources. ··· 3052 3054 if (err) 3053 3055 return err; 3054 3056 3057 + /* Clear all the VTU and STU entries */ 3058 + err = _mv88e6xxx_vtu_stu_flush(chip); 3059 + if (err < 0) 3060 + return err; 3061 + 3055 3062 /* Set the default address aging time to 5 minutes, and 3056 3063 * enable address learn messages to be sent to all message 3057 3064 * ports. 3058 3065 */ 3059 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL, GLOBAL_ATU_CONTROL, 3060 - 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL); 3066 + err = mv88e6xxx_write(chip, REG_GLOBAL, GLOBAL_ATU_CONTROL, 3067 + GLOBAL_ATU_CONTROL_LEARN2ALL); 3068 + if (err) 3069 + return err; 3070 + 3071 + err = mv88e6xxx_g1_set_age_time(chip, 300000); 3072 + if (err) 3073 + return err; 3074 + 3075 + /* Clear all ATU entries */ 3076 + err = _mv88e6xxx_atu_flush(chip, 0, true); 3061 3077 if (err) 3062 3078 return err; 3063 3079 ··· 3106 3094 if (err) 3107 3095 return err; 3108 3096 3109 - /* Send all frames with destination addresses matching 3110 - * 01:80:c2:00:00:0x to the CPU port. 3111 - */ 3112 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 3113 - 0xffff); 3114 - if (err) 3115 - return err; 3116 - 3117 - /* Ignore removed tag data on doubly tagged packets, disable 3118 - * flow control messages, force flow control priority to the 3119 - * highest, and send all special multicast frames to the CPU 3120 - * port at the highest priority. 3121 - */ 3122 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT, 3123 - 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 | 3124 - GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI); 3125 - if (err) 3126 - return err; 3127 - 3128 - /* Program the DSA routing table. */ 3129 - for (i = 0; i < 32; i++) { 3130 - int nexthop = 0x1f; 3131 - 3132 - if (i != ds->index && i < DSA_MAX_SWITCHES) 3133 - nexthop = ds->rtable[i] & 0x1f; 3134 - 3135 - err = _mv88e6xxx_reg_write( 3136 - chip, REG_GLOBAL2, 3137 - GLOBAL2_DEVICE_MAPPING, 3138 - GLOBAL2_DEVICE_MAPPING_UPDATE | 3139 - (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop); 3140 - if (err) 3141 - return err; 3142 - } 3143 - 3144 - /* Clear all trunk masks. */ 3145 - for (i = 0; i < 8; i++) { 3146 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, 3147 - GLOBAL2_TRUNK_MASK, 3148 - 0x8000 | 3149 - (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) | 3150 - ((1 << chip->info->num_ports) - 1)); 3151 - if (err) 3152 - return err; 3153 - } 3154 - 3155 - /* Clear all trunk mappings. */ 3156 - for (i = 0; i < 16; i++) { 3157 - err = _mv88e6xxx_reg_write( 3158 - chip, REG_GLOBAL2, 3159 - GLOBAL2_TRUNK_MAPPING, 3160 - GLOBAL2_TRUNK_MAPPING_UPDATE | 3161 - (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT)); 3162 - if (err) 3163 - return err; 3164 - } 3165 - 3166 - if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) || 3167 - mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) || 3168 - mv88e6xxx_6320_family(chip)) { 3169 - /* Send all frames with destination addresses matching 3170 - * 01:80:c2:00:00:2x to the CPU port. 3171 - */ 3172 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, 3173 - GLOBAL2_MGMT_EN_2X, 0xffff); 3174 - if (err) 3175 - return err; 3176 - 3177 - /* Initialise cross-chip port VLAN table to reset 3178 - * defaults. 3179 - */ 3180 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, 3181 - GLOBAL2_PVT_ADDR, 0x9000); 3182 - if (err) 3183 - return err; 3184 - 3185 - /* Clear the priority override table. */ 3186 - for (i = 0; i < 16; i++) { 3187 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, 3188 - GLOBAL2_PRIO_OVERRIDE, 3189 - 0x8000 | (i << 8)); 3190 - if (err) 3191 - return err; 3192 - } 3193 - } 3194 - 3195 - if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) || 3196 - mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) || 3197 - mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip) || 3198 - mv88e6xxx_6320_family(chip)) { 3199 - /* Disable ingress rate limiting by resetting all 3200 - * ingress rate limit registers to their initial 3201 - * state. 3202 - */ 3203 - for (i = 0; i < chip->info->num_ports; i++) { 3204 - err = _mv88e6xxx_reg_write(chip, REG_GLOBAL2, 3205 - GLOBAL2_INGRESS_OP, 3206 - 0x9000 | (i << 8)); 3207 - if (err) 3208 - return err; 3209 - } 3210 - } 3211 - 3212 3097 /* Clear the statistics counters for all ports */ 3213 3098 err = _mv88e6xxx_reg_write(chip, REG_GLOBAL, GLOBAL_STATS_OP, 3214 3099 GLOBAL_STATS_OP_FLUSH_ALL); ··· 3117 3208 if (err) 3118 3209 return err; 3119 3210 3120 - /* Clear all ATU entries */ 3121 - err = _mv88e6xxx_atu_flush(chip, 0, true); 3211 + return 0; 3212 + } 3213 + 3214 + static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, 3215 + int target, int port) 3216 + { 3217 + u16 val = (target << 8) | (port & 0xf); 3218 + 3219 + return mv88e6xxx_update(chip, REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING, val); 3220 + } 3221 + 3222 + static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip) 3223 + { 3224 + int target, port; 3225 + int err; 3226 + 3227 + /* Initialize the routing port to the 32 possible target devices */ 3228 + for (target = 0; target < 32; ++target) { 3229 + port = 0xf; 3230 + 3231 + if (target < DSA_MAX_SWITCHES) { 3232 + port = chip->ds->rtable[target]; 3233 + if (port == DSA_RTABLE_NONE) 3234 + port = 0xf; 3235 + } 3236 + 3237 + err = mv88e6xxx_g2_device_mapping_write(chip, target, port); 3238 + if (err) 3239 + break; 3240 + } 3241 + 3242 + return err; 3243 + } 3244 + 3245 + static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, 3246 + bool hask, u16 mask) 3247 + { 3248 + const u16 port_mask = BIT(chip->info->num_ports) - 1; 3249 + u16 val = (num << 12) | (mask & port_mask); 3250 + 3251 + if (hask) 3252 + val |= GLOBAL2_TRUNK_MASK_HASK; 3253 + 3254 + return mv88e6xxx_update(chip, REG_GLOBAL2, GLOBAL2_TRUNK_MASK, val); 3255 + } 3256 + 3257 + static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, 3258 + u16 map) 3259 + { 3260 + const u16 port_mask = BIT(chip->info->num_ports) - 1; 3261 + u16 val = (id << 11) | (map & port_mask); 3262 + 3263 + return mv88e6xxx_update(chip, REG_GLOBAL2, GLOBAL2_TRUNK_MAPPING, val); 3264 + } 3265 + 3266 + static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip) 3267 + { 3268 + const u16 port_mask = BIT(chip->info->num_ports) - 1; 3269 + int i, err; 3270 + 3271 + /* Clear all eight possible Trunk Mask vectors */ 3272 + for (i = 0; i < 8; ++i) { 3273 + err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask); 3274 + if (err) 3275 + return err; 3276 + } 3277 + 3278 + /* Clear all sixteen possible Trunk ID routing vectors */ 3279 + for (i = 0; i < 16; ++i) { 3280 + err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0); 3281 + if (err) 3282 + return err; 3283 + } 3284 + 3285 + return 0; 3286 + } 3287 + 3288 + static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip) 3289 + { 3290 + int port, err; 3291 + 3292 + /* Init all Ingress Rate Limit resources of all ports */ 3293 + for (port = 0; port < chip->info->num_ports; ++port) { 3294 + /* XXX newer chips (like 88E6390) have different 2-bit ops */ 3295 + err = mv88e6xxx_write(chip, REG_GLOBAL2, GLOBAL2_IRL_CMD, 3296 + GLOBAL2_IRL_CMD_OP_INIT_ALL | 3297 + (port << 8)); 3298 + if (err) 3299 + break; 3300 + 3301 + /* Wait for the operation to complete */ 3302 + err = _mv88e6xxx_wait(chip, REG_GLOBAL2, GLOBAL2_IRL_CMD, 3303 + GLOBAL2_IRL_CMD_BUSY); 3304 + if (err) 3305 + break; 3306 + } 3307 + 3308 + return err; 3309 + } 3310 + 3311 + /* Indirect write to the Switch MAC/WoL/WoF register */ 3312 + static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip, 3313 + unsigned int pointer, u8 data) 3314 + { 3315 + u16 val = (pointer << 8) | data; 3316 + 3317 + return mv88e6xxx_update(chip, REG_GLOBAL2, GLOBAL2_SWITCH_MAC, val); 3318 + } 3319 + 3320 + static int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) 3321 + { 3322 + int i, err; 3323 + 3324 + for (i = 0; i < 6; i++) { 3325 + err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]); 3326 + if (err) 3327 + break; 3328 + } 3329 + 3330 + return err; 3331 + } 3332 + 3333 + static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer, 3334 + u8 data) 3335 + { 3336 + u16 val = (pointer << 8) | (data & 0x7); 3337 + 3338 + return mv88e6xxx_update(chip, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE, val); 3339 + } 3340 + 3341 + static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip) 3342 + { 3343 + int i, err; 3344 + 3345 + /* Clear all sixteen possible Priority Override entries */ 3346 + for (i = 0; i < 16; i++) { 3347 + err = mv88e6xxx_g2_pot_write(chip, i, 0); 3348 + if (err) 3349 + break; 3350 + } 3351 + 3352 + return err; 3353 + } 3354 + 3355 + static int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) 3356 + { 3357 + u16 reg; 3358 + int err; 3359 + 3360 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) { 3361 + /* Consider the frames with reserved multicast destination 3362 + * addresses matching 01:80:c2:00:00:2x as MGMT. 3363 + */ 3364 + err = mv88e6xxx_write(chip, REG_GLOBAL2, GLOBAL2_MGMT_EN_2X, 3365 + 0xffff); 3366 + if (err) 3367 + return err; 3368 + } 3369 + 3370 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) { 3371 + /* Consider the frames with reserved multicast destination 3372 + * addresses matching 01:80:c2:00:00:0x as MGMT. 3373 + */ 3374 + err = mv88e6xxx_write(chip, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 3375 + 0xffff); 3376 + if (err) 3377 + return err; 3378 + } 3379 + 3380 + /* Ignore removed tag data on doubly tagged packets, disable 3381 + * flow control messages, force flow control priority to the 3382 + * highest, and send all special multicast frames to the CPU 3383 + * port at the highest priority. 3384 + */ 3385 + reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4); 3386 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) || 3387 + mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) 3388 + reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7; 3389 + err = mv88e6xxx_write(chip, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT, reg); 3122 3390 if (err) 3123 3391 return err; 3124 3392 3125 - /* Clear all the VTU and STU entries */ 3126 - err = _mv88e6xxx_vtu_stu_flush(chip); 3127 - if (err < 0) 3393 + /* Program the DSA routing table. */ 3394 + err = mv88e6xxx_g2_set_device_mapping(chip); 3395 + if (err) 3128 3396 return err; 3129 3397 3130 - return err; 3398 + /* Clear all trunk masks and mapping. */ 3399 + err = mv88e6xxx_g2_clear_trunk(chip); 3400 + if (err) 3401 + return err; 3402 + 3403 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) { 3404 + /* Disable ingress rate limiting by resetting all per port 3405 + * ingress rate limit resources to their initial state. 3406 + */ 3407 + err = mv88e6xxx_g2_clear_irl(chip); 3408 + if (err) 3409 + return err; 3410 + } 3411 + 3412 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) { 3413 + /* Initialize Cross-chip Port VLAN Table to reset defaults */ 3414 + err = mv88e6xxx_write(chip, REG_GLOBAL2, GLOBAL2_PVT_ADDR, 3415 + GLOBAL2_PVT_ADDR_OP_INIT_ONES); 3416 + if (err) 3417 + return err; 3418 + } 3419 + 3420 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) { 3421 + /* Clear the priority override table. */ 3422 + err = mv88e6xxx_g2_clear_pot(chip); 3423 + if (err) 3424 + return err; 3425 + } 3426 + 3427 + return 0; 3131 3428 } 3132 3429 3133 3430 static int mv88e6xxx_setup(struct dsa_switch *ds) ··· 3354 3239 if (err) 3355 3240 goto unlock; 3356 3241 3357 - err = mv88e6xxx_setup_global(chip); 3358 - if (err) 3359 - goto unlock; 3360 - 3242 + /* Setup Switch Port Registers */ 3361 3243 for (i = 0; i < chip->info->num_ports; i++) { 3362 3244 err = mv88e6xxx_setup_port(chip, i); 3363 3245 if (err) 3364 3246 goto unlock; 3365 3247 } 3366 3248 3249 + /* Setup Switch Global 1 Registers */ 3250 + err = mv88e6xxx_g1_setup(chip); 3251 + if (err) 3252 + goto unlock; 3253 + 3254 + /* Setup Switch Global 2 Registers */ 3255 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_GLOBAL2)) { 3256 + err = mv88e6xxx_g2_setup(chip); 3257 + if (err) 3258 + goto unlock; 3259 + } 3260 + 3367 3261 unlock: 3262 + mutex_unlock(&chip->reg_lock); 3263 + 3264 + return err; 3265 + } 3266 + 3267 + static int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr) 3268 + { 3269 + struct mv88e6xxx_chip *chip = ds_to_priv(ds); 3270 + int err; 3271 + 3272 + mutex_lock(&chip->reg_lock); 3273 + 3274 + /* Has an indirect Switch MAC/WoL/WoF register in Global 2? */ 3275 + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_SWITCH_MAC)) 3276 + err = mv88e6xxx_g2_set_switch_mac(chip, addr); 3277 + else 3278 + err = mv88e6xxx_g1_set_switch_mac(chip, addr); 3279 + 3368 3280 mutex_unlock(&chip->reg_lock); 3369 3281 3370 3282 return err; ··· 3678 3536 .num_databases = 4096, 3679 3537 .num_ports = 10, 3680 3538 .port_base_addr = 0x10, 3539 + .age_time_coeff = 15000, 3681 3540 .flags = MV88E6XXX_FLAGS_FAMILY_6097, 3682 3541 }, 3683 3542 ··· 3689 3546 .num_databases = 256, 3690 3547 .num_ports = 11, 3691 3548 .port_base_addr = 0x10, 3549 + .age_time_coeff = 15000, 3692 3550 .flags = MV88E6XXX_FLAGS_FAMILY_6095, 3693 3551 }, 3694 3552 ··· 3700 3556 .num_databases = 4096, 3701 3557 .num_ports = 3, 3702 3558 .port_base_addr = 0x10, 3559 + .age_time_coeff = 15000, 3703 3560 .flags = MV88E6XXX_FLAGS_FAMILY_6165, 3704 3561 }, 3705 3562 ··· 3711 3566 .num_databases = 256, 3712 3567 .num_ports = 8, 3713 3568 .port_base_addr = 0x10, 3569 + .age_time_coeff = 15000, 3714 3570 .flags = MV88E6XXX_FLAGS_FAMILY_6185, 3715 3571 }, 3716 3572 ··· 3722 3576 .num_databases = 4096, 3723 3577 .num_ports = 6, 3724 3578 .port_base_addr = 0x10, 3579 + .age_time_coeff = 15000, 3725 3580 .flags = MV88E6XXX_FLAGS_FAMILY_6165, 3726 3581 }, 3727 3582 ··· 3733 3586 .num_databases = 4096, 3734 3587 .num_ports = 6, 3735 3588 .port_base_addr = 0x10, 3589 + .age_time_coeff = 15000, 3736 3590 .flags = MV88E6XXX_FLAGS_FAMILY_6165, 3737 3591 }, 3738 3592 ··· 3744 3596 .num_databases = 4096, 3745 3597 .num_ports = 7, 3746 3598 .port_base_addr = 0x10, 3599 + .age_time_coeff = 15000, 3747 3600 .flags = MV88E6XXX_FLAGS_FAMILY_6351, 3748 3601 }, 3749 3602 ··· 3755 3606 .num_databases = 4096, 3756 3607 .num_ports = 7, 3757 3608 .port_base_addr = 0x10, 3609 + .age_time_coeff = 15000, 3758 3610 .flags = MV88E6XXX_FLAGS_FAMILY_6352, 3759 3611 }, 3760 3612 ··· 3766 3616 .num_databases = 4096, 3767 3617 .num_ports = 7, 3768 3618 .port_base_addr = 0x10, 3619 + .age_time_coeff = 15000, 3769 3620 .flags = MV88E6XXX_FLAGS_FAMILY_6351, 3770 3621 }, 3771 3622 ··· 3777 3626 .num_databases = 4096, 3778 3627 .num_ports = 7, 3779 3628 .port_base_addr = 0x10, 3629 + .age_time_coeff = 15000, 3780 3630 .flags = MV88E6XXX_FLAGS_FAMILY_6352, 3781 3631 }, 3782 3632 ··· 3788 3636 .num_databases = 256, 3789 3637 .num_ports = 10, 3790 3638 .port_base_addr = 0x10, 3639 + .age_time_coeff = 15000, 3791 3640 .flags = MV88E6XXX_FLAGS_FAMILY_6185, 3792 3641 }, 3793 3642 ··· 3799 3646 .num_databases = 4096, 3800 3647 .num_ports = 7, 3801 3648 .port_base_addr = 0x10, 3649 + .age_time_coeff = 15000, 3802 3650 .flags = MV88E6XXX_FLAGS_FAMILY_6352, 3803 3651 }, 3804 3652 ··· 3810 3656 .num_databases = 4096, 3811 3657 .num_ports = 7, 3812 3658 .port_base_addr = 0x10, 3659 + .age_time_coeff = 15000, 3813 3660 .flags = MV88E6XXX_FLAGS_FAMILY_6320, 3814 3661 }, 3815 3662 ··· 3821 3666 .num_databases = 4096, 3822 3667 .num_ports = 7, 3823 3668 .port_base_addr = 0x10, 3669 + .age_time_coeff = 15000, 3824 3670 .flags = MV88E6XXX_FLAGS_FAMILY_6320, 3825 3671 }, 3826 3672 ··· 3832 3676 .num_databases = 4096, 3833 3677 .num_ports = 7, 3834 3678 .port_base_addr = 0x10, 3679 + .age_time_coeff = 15000, 3835 3680 .flags = MV88E6XXX_FLAGS_FAMILY_6351, 3836 3681 }, 3837 3682 ··· 3843 3686 .num_databases = 4096, 3844 3687 .num_ports = 7, 3845 3688 .port_base_addr = 0x10, 3689 + .age_time_coeff = 15000, 3846 3690 .flags = MV88E6XXX_FLAGS_FAMILY_6351, 3847 3691 }, 3848 3692 ··· 3854 3696 .num_databases = 4096, 3855 3697 .num_ports = 7, 3856 3698 .port_base_addr = 0x10, 3699 + .age_time_coeff = 15000, 3857 3700 .flags = MV88E6XXX_FLAGS_FAMILY_6352, 3858 3701 }, 3859 3702 }; ··· 3993 3834 .set_eeprom = mv88e6xxx_set_eeprom, 3994 3835 .get_regs_len = mv88e6xxx_get_regs_len, 3995 3836 .get_regs = mv88e6xxx_get_regs, 3837 + .set_ageing_time = mv88e6xxx_set_ageing_time, 3996 3838 .port_bridge_join = mv88e6xxx_port_bridge_join, 3997 3839 .port_bridge_leave = mv88e6xxx_port_bridge_leave, 3998 3840 .port_stp_state_set = mv88e6xxx_port_stp_state_set,
+91 -57
drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
··· 294 294 #define GLOBAL2_TRUNK_MASK 0x07 295 295 #define GLOBAL2_TRUNK_MASK_UPDATE BIT(15) 296 296 #define GLOBAL2_TRUNK_MASK_NUM_SHIFT 12 297 + #define GLOBAL2_TRUNK_MASK_HASK BIT(11) 297 298 #define GLOBAL2_TRUNK_MAPPING 0x08 298 299 #define GLOBAL2_TRUNK_MAPPING_UPDATE BIT(15) 299 300 #define GLOBAL2_TRUNK_MAPPING_ID_SHIFT 11 300 - #define GLOBAL2_INGRESS_OP 0x09 301 - #define GLOBAL2_INGRESS_DATA 0x0a 301 + #define GLOBAL2_IRL_CMD 0x09 302 + #define GLOBAL2_IRL_CMD_BUSY BIT(15) 303 + #define GLOBAL2_IRL_CMD_OP_INIT_ALL ((0x001 << 12) | GLOBAL2_IRL_CMD_BUSY) 304 + #define GLOBAL2_IRL_CMD_OP_INIT_SEL ((0x010 << 12) | GLOBAL2_IRL_CMD_BUSY) 305 + #define GLOBAL2_IRL_CMD_OP_WRITE_SEL ((0x011 << 12) | GLOBAL2_IRL_CMD_BUSY) 306 + #define GLOBAL2_IRL_CMD_OP_READ_SEL ((0x100 << 12) | GLOBAL2_IRL_CMD_BUSY) 307 + #define GLOBAL2_IRL_DATA 0x0a 302 308 #define GLOBAL2_PVT_ADDR 0x0b 309 + #define GLOBAL2_PVT_ADDR_BUSY BIT(15) 310 + #define GLOBAL2_PVT_ADDR_OP_INIT_ONES ((0x01 << 12) | GLOBAL2_PVT_ADDR_BUSY) 311 + #define GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN ((0x03 << 12) | GLOBAL2_PVT_ADDR_BUSY) 312 + #define GLOBAL2_PVT_ADDR_OP_READ ((0x04 << 12) | GLOBAL2_PVT_ADDR_BUSY) 303 313 #define GLOBAL2_PVT_DATA 0x0c 304 314 #define GLOBAL2_SWITCH_MAC 0x0d 305 - #define GLOBAL2_SWITCH_MAC_BUSY BIT(15) 306 315 #define GLOBAL2_ATU_STATS 0x0e 307 316 #define GLOBAL2_PRIO_OVERRIDE 0x0f 308 317 #define GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP BIT(7) ··· 383 374 }; 384 375 385 376 enum mv88e6xxx_cap { 386 - /* Address Translation Unit. 387 - * The ATU is used to lookup and learn MAC addresses. See GLOBAL_ATU_OP. 388 - */ 389 - MV88E6XXX_CAP_ATU, 390 - 391 377 /* Energy Efficient Ethernet. 392 378 */ 393 379 MV88E6XXX_CAP_EEE, ··· 392 388 */ 393 389 MV88E6XXX_CAP_EEPROM, 394 390 391 + /* Switch Global 2 Registers. 392 + * The device contains a second set of global 16-bit registers. 393 + */ 394 + MV88E6XXX_CAP_GLOBAL2, 395 + MV88E6XXX_CAP_G2_MGMT_EN_2X, /* (0x02) MGMT Enable Register 2x */ 396 + MV88E6XXX_CAP_G2_MGMT_EN_0X, /* (0x03) MGMT Enable Register 0x */ 397 + MV88E6XXX_CAP_G2_IRL_CMD, /* (0x09) Ingress Rate Command */ 398 + MV88E6XXX_CAP_G2_IRL_DATA, /* (0x0a) Ingress Rate Data */ 399 + MV88E6XXX_CAP_G2_PVT_ADDR, /* (0x0b) Cross Chip Port VLAN Addr */ 400 + MV88E6XXX_CAP_G2_PVT_DATA, /* (0x0c) Cross Chip Port VLAN Data */ 401 + MV88E6XXX_CAP_G2_SWITCH_MAC, /* (0x0d) Switch MAC/WoL/WoF */ 402 + MV88E6XXX_CAP_G2_POT, /* (0x0f) Priority Override Table */ 403 + 395 404 /* Multi-chip Addressing Mode. 396 405 * Some chips require an indirect SMI access when their SMI device 397 406 * address is not zero. See SMI_CMD and SMI_DATA. 398 407 */ 399 408 MV88E6XXX_CAP_MULTI_CHIP, 400 - 401 - /* Port State Filtering for 802.1D Spanning Tree. 402 - * See PORT_CONTROL_STATE_* values in the PORT_CONTROL register. 403 - */ 404 - MV88E6XXX_CAP_PORTSTATE, 405 409 406 410 /* PHY Polling Unit. 407 411 * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING. ··· 429 417 */ 430 418 MV88E6XXX_CAP_STU, 431 419 432 - /* Switch MAC/WoL/WoF register. 433 - * This requires an indirect access to set the switch MAC address 434 - * through GLOBAL2_SWITCH_MAC, otherwise GLOBAL_MAC_01, GLOBAL_MAC_23, 435 - * and GLOBAL_MAC_45 are used with a direct access. 436 - */ 437 - MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF, 438 - 439 420 /* Internal temperature sensor. 440 421 * Available from any enabled port's PHY register 26, page 6. 441 422 */ 442 423 MV88E6XXX_CAP_TEMP, 443 424 MV88E6XXX_CAP_TEMP_LIMIT, 444 - 445 - /* In-chip Port Based VLANs. 446 - * Each port VLANTable register (see PORT_BASE_VLAN) is used to restrict 447 - * the output (or egress) ports to which it is allowed to send frames. 448 - */ 449 - MV88E6XXX_CAP_VLANTABLE, 450 425 451 426 /* VLAN Table Unit. 452 427 * The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP. ··· 442 443 }; 443 444 444 445 /* Bitmask of capabilities */ 445 - #define MV88E6XXX_FLAG_ATU BIT(MV88E6XXX_CAP_ATU) 446 446 #define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE) 447 447 #define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM) 448 + #define MV88E6XXX_FLAG_GLOBAL2 BIT(MV88E6XXX_CAP_GLOBAL2) 449 + #define MV88E6XXX_FLAG_G2_MGMT_EN_2X BIT(MV88E6XXX_CAP_G2_MGMT_EN_2X) 450 + #define MV88E6XXX_FLAG_G2_MGMT_EN_0X BIT(MV88E6XXX_CAP_G2_MGMT_EN_0X) 451 + #define MV88E6XXX_FLAG_G2_IRL_CMD BIT(MV88E6XXX_CAP_G2_IRL_CMD) 452 + #define MV88E6XXX_FLAG_G2_IRL_DATA BIT(MV88E6XXX_CAP_G2_IRL_DATA) 453 + #define MV88E6XXX_FLAG_G2_PVT_ADDR BIT(MV88E6XXX_CAP_G2_PVT_ADDR) 454 + #define MV88E6XXX_FLAG_G2_PVT_DATA BIT(MV88E6XXX_CAP_G2_PVT_DATA) 455 + #define MV88E6XXX_FLAG_G2_SWITCH_MAC BIT(MV88E6XXX_CAP_G2_SWITCH_MAC) 456 + #define MV88E6XXX_FLAG_G2_POT BIT(MV88E6XXX_CAP_G2_POT) 448 457 #define MV88E6XXX_FLAG_MULTI_CHIP BIT(MV88E6XXX_CAP_MULTI_CHIP) 449 - #define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE) 450 458 #define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU) 451 459 #define MV88E6XXX_FLAG_PPU_ACTIVE BIT(MV88E6XXX_CAP_PPU_ACTIVE) 452 460 #define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY) 453 461 #define MV88E6XXX_FLAG_STU BIT(MV88E6XXX_CAP_STU) 454 - #define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF) 455 462 #define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP) 456 463 #define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT) 457 - #define MV88E6XXX_FLAG_VLANTABLE BIT(MV88E6XXX_CAP_VLANTABLE) 458 464 #define MV88E6XXX_FLAG_VTU BIT(MV88E6XXX_CAP_VTU) 459 465 466 + /* Ingress Rate Limit unit */ 467 + #define MV88E6XXX_FLAGS_IRL \ 468 + (MV88E6XXX_FLAG_G2_IRL_CMD | \ 469 + MV88E6XXX_FLAG_G2_IRL_DATA) 470 + 471 + /* Cross-chip Port VLAN Table */ 472 + #define MV88E6XXX_FLAGS_PVT \ 473 + (MV88E6XXX_FLAG_G2_PVT_ADDR | \ 474 + MV88E6XXX_FLAG_G2_PVT_DATA) 475 + 460 476 #define MV88E6XXX_FLAGS_FAMILY_6095 \ 461 - (MV88E6XXX_FLAG_ATU | \ 477 + (MV88E6XXX_FLAG_GLOBAL2 | \ 478 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 462 479 MV88E6XXX_FLAG_MULTI_CHIP | \ 463 480 MV88E6XXX_FLAG_PPU | \ 464 - MV88E6XXX_FLAG_VLANTABLE | \ 465 481 MV88E6XXX_FLAG_VTU) 466 482 467 483 #define MV88E6XXX_FLAGS_FAMILY_6097 \ 468 - (MV88E6XXX_FLAG_ATU | \ 484 + (MV88E6XXX_FLAG_GLOBAL2 | \ 485 + MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ 486 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 487 + MV88E6XXX_FLAG_G2_POT | \ 469 488 MV88E6XXX_FLAG_MULTI_CHIP | \ 470 489 MV88E6XXX_FLAG_PPU | \ 471 490 MV88E6XXX_FLAG_STU | \ 472 - MV88E6XXX_FLAG_VLANTABLE | \ 473 - MV88E6XXX_FLAG_VTU) 491 + MV88E6XXX_FLAG_VTU | \ 492 + MV88E6XXX_FLAGS_IRL | \ 493 + MV88E6XXX_FLAGS_PVT) 474 494 475 495 #define MV88E6XXX_FLAGS_FAMILY_6165 \ 476 - (MV88E6XXX_FLAG_MULTI_CHIP | \ 496 + (MV88E6XXX_FLAG_GLOBAL2 | \ 497 + MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ 498 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 499 + MV88E6XXX_FLAG_G2_SWITCH_MAC | \ 500 + MV88E6XXX_FLAG_G2_POT | \ 501 + MV88E6XXX_FLAG_MULTI_CHIP | \ 477 502 MV88E6XXX_FLAG_STU | \ 478 - MV88E6XXX_FLAG_SWITCH_MAC | \ 479 503 MV88E6XXX_FLAG_TEMP | \ 480 - MV88E6XXX_FLAG_VTU) 504 + MV88E6XXX_FLAG_VTU | \ 505 + MV88E6XXX_FLAGS_IRL | \ 506 + MV88E6XXX_FLAGS_PVT) 481 507 482 508 #define MV88E6XXX_FLAGS_FAMILY_6185 \ 483 - (MV88E6XXX_FLAG_ATU | \ 509 + (MV88E6XXX_FLAG_GLOBAL2 | \ 510 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 484 511 MV88E6XXX_FLAG_MULTI_CHIP | \ 485 512 MV88E6XXX_FLAG_PPU | \ 486 - MV88E6XXX_FLAG_VLANTABLE | \ 487 513 MV88E6XXX_FLAG_VTU) 488 514 489 515 #define MV88E6XXX_FLAGS_FAMILY_6320 \ 490 - (MV88E6XXX_FLAG_ATU | \ 491 - MV88E6XXX_FLAG_EEE | \ 516 + (MV88E6XXX_FLAG_EEE | \ 492 517 MV88E6XXX_FLAG_EEPROM | \ 518 + MV88E6XXX_FLAG_GLOBAL2 | \ 519 + MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ 520 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 521 + MV88E6XXX_FLAG_G2_SWITCH_MAC | \ 522 + MV88E6XXX_FLAG_G2_POT | \ 493 523 MV88E6XXX_FLAG_MULTI_CHIP | \ 494 - MV88E6XXX_FLAG_PORTSTATE | \ 495 524 MV88E6XXX_FLAG_PPU_ACTIVE | \ 496 525 MV88E6XXX_FLAG_SMI_PHY | \ 497 - MV88E6XXX_FLAG_SWITCH_MAC | \ 498 526 MV88E6XXX_FLAG_TEMP | \ 499 527 MV88E6XXX_FLAG_TEMP_LIMIT | \ 500 - MV88E6XXX_FLAG_VLANTABLE | \ 501 - MV88E6XXX_FLAG_VTU) 528 + MV88E6XXX_FLAG_VTU | \ 529 + MV88E6XXX_FLAGS_IRL | \ 530 + MV88E6XXX_FLAGS_PVT) 502 531 503 532 #define MV88E6XXX_FLAGS_FAMILY_6351 \ 504 - (MV88E6XXX_FLAG_ATU | \ 533 + (MV88E6XXX_FLAG_GLOBAL2 | \ 534 + MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ 535 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 536 + MV88E6XXX_FLAG_G2_SWITCH_MAC | \ 537 + MV88E6XXX_FLAG_G2_POT | \ 505 538 MV88E6XXX_FLAG_MULTI_CHIP | \ 506 - MV88E6XXX_FLAG_PORTSTATE | \ 507 539 MV88E6XXX_FLAG_PPU_ACTIVE | \ 508 540 MV88E6XXX_FLAG_SMI_PHY | \ 509 541 MV88E6XXX_FLAG_STU | \ 510 - MV88E6XXX_FLAG_SWITCH_MAC | \ 511 542 MV88E6XXX_FLAG_TEMP | \ 512 - MV88E6XXX_FLAG_VLANTABLE | \ 513 - MV88E6XXX_FLAG_VTU) 543 + MV88E6XXX_FLAG_VTU | \ 544 + MV88E6XXX_FLAGS_IRL | \ 545 + MV88E6XXX_FLAGS_PVT) 514 546 515 547 #define MV88E6XXX_FLAGS_FAMILY_6352 \ 516 - (MV88E6XXX_FLAG_ATU | \ 517 - MV88E6XXX_FLAG_EEE | \ 548 + (MV88E6XXX_FLAG_EEE | \ 518 549 MV88E6XXX_FLAG_EEPROM | \ 550 + MV88E6XXX_FLAG_GLOBAL2 | \ 551 + MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ 552 + MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 553 + MV88E6XXX_FLAG_G2_SWITCH_MAC | \ 554 + MV88E6XXX_FLAG_G2_POT | \ 519 555 MV88E6XXX_FLAG_MULTI_CHIP | \ 520 - MV88E6XXX_FLAG_PORTSTATE | \ 521 556 MV88E6XXX_FLAG_PPU_ACTIVE | \ 522 557 MV88E6XXX_FLAG_SMI_PHY | \ 523 558 MV88E6XXX_FLAG_STU | \ 524 - MV88E6XXX_FLAG_SWITCH_MAC | \ 525 559 MV88E6XXX_FLAG_TEMP | \ 526 560 MV88E6XXX_FLAG_TEMP_LIMIT | \ 527 - MV88E6XXX_FLAG_VLANTABLE | \ 528 - MV88E6XXX_FLAG_VTU) 561 + MV88E6XXX_FLAG_VTU | \ 562 + MV88E6XXX_FLAGS_IRL | \ 563 + MV88E6XXX_FLAGS_PVT) 529 564 530 565 struct mv88e6xxx_info { 531 566 enum mv88e6xxx_family family; ··· 568 535 unsigned int num_databases; 569 536 unsigned int num_ports; 570 537 unsigned int port_base_addr; 538 + unsigned int age_time_coeff; 571 539 unsigned long flags; 572 540 }; 573 541
+2
include/net/dsa.h
··· 141 141 struct dsa_port { 142 142 struct net_device *netdev; 143 143 struct device_node *dn; 144 + unsigned int ageing_time; 144 145 }; 145 146 146 147 struct dsa_switch { ··· 330 329 /* 331 330 * Bridge integration 332 331 */ 332 + int (*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs); 333 333 int (*port_bridge_join)(struct dsa_switch *ds, int port, 334 334 struct net_device *bridge); 335 335 void (*port_bridge_leave)(struct dsa_switch *ds, int port);
+41
net/dsa/slave.c
··· 333 333 return 0; 334 334 } 335 335 336 + static int dsa_fastest_ageing_time(struct dsa_switch *ds, 337 + unsigned int ageing_time) 338 + { 339 + int i; 340 + 341 + for (i = 0; i < DSA_MAX_PORTS; ++i) { 342 + struct dsa_port *dp = &ds->ports[i]; 343 + 344 + if (dp && dp->ageing_time && dp->ageing_time < ageing_time) 345 + ageing_time = dp->ageing_time; 346 + } 347 + 348 + return ageing_time; 349 + } 350 + 351 + static int dsa_slave_ageing_time(struct net_device *dev, 352 + const struct switchdev_attr *attr, 353 + struct switchdev_trans *trans) 354 + { 355 + struct dsa_slave_priv *p = netdev_priv(dev); 356 + struct dsa_switch *ds = p->parent; 357 + unsigned long ageing_jiffies = clock_t_to_jiffies(attr->u.ageing_time); 358 + unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); 359 + 360 + /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ 361 + if (switchdev_trans_ph_prepare(trans)) 362 + return 0; 363 + 364 + /* Keep the fastest ageing time in case of multiple bridges */ 365 + ds->ports[p->port].ageing_time = ageing_time; 366 + ageing_time = dsa_fastest_ageing_time(ds, ageing_time); 367 + 368 + if (ds->drv->set_ageing_time) 369 + return ds->drv->set_ageing_time(ds, ageing_time); 370 + 371 + return 0; 372 + } 373 + 336 374 static int dsa_slave_port_attr_set(struct net_device *dev, 337 375 const struct switchdev_attr *attr, 338 376 struct switchdev_trans *trans) ··· 383 345 break; 384 346 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 385 347 ret = dsa_slave_vlan_filtering(dev, attr, trans); 348 + break; 349 + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 350 + ret = dsa_slave_ageing_time(dev, attr, trans); 386 351 break; 387 352 default: 388 353 ret = -EOPNOTSUPP;