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

nfp: ethtool: fix the bug of setting unsupported port speed

Unsupported port speed can be set and cause error. Now fixing it
and return an error if setting unsupported speed.

This fix depends on the following, which was included in v6.2-rc1:
commit a61474c41e8c ("nfp: ethtool: support reporting link modes").

Fixes: 7c698737270f ("nfp: add support for .set_link_ksettings()")
Signed-off-by: Yu Xiao <yu.xiao@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yu Xiao and committed by
David S. Miller
821de68c c11204c7

+170 -36
+158 -36
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
··· 293 293 } 294 294 } 295 295 296 - static const u16 nfp_eth_media_table[] = { 297 - [NFP_MEDIA_1000BASE_CX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 298 - [NFP_MEDIA_1000BASE_KX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 299 - [NFP_MEDIA_10GBASE_KX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 300 - [NFP_MEDIA_10GBASE_KR] = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 301 - [NFP_MEDIA_10GBASE_CX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 302 - [NFP_MEDIA_10GBASE_CR] = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 303 - [NFP_MEDIA_10GBASE_SR] = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 304 - [NFP_MEDIA_10GBASE_ER] = ETHTOOL_LINK_MODE_10000baseER_Full_BIT, 305 - [NFP_MEDIA_25GBASE_KR] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 306 - [NFP_MEDIA_25GBASE_KR_S] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 307 - [NFP_MEDIA_25GBASE_CR] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 308 - [NFP_MEDIA_25GBASE_CR_S] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 309 - [NFP_MEDIA_25GBASE_SR] = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 310 - [NFP_MEDIA_40GBASE_CR4] = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 311 - [NFP_MEDIA_40GBASE_KR4] = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 312 - [NFP_MEDIA_40GBASE_SR4] = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 313 - [NFP_MEDIA_40GBASE_LR4] = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 314 - [NFP_MEDIA_50GBASE_KR] = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 315 - [NFP_MEDIA_50GBASE_SR] = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 316 - [NFP_MEDIA_50GBASE_CR] = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 317 - [NFP_MEDIA_50GBASE_LR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 318 - [NFP_MEDIA_50GBASE_ER] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 319 - [NFP_MEDIA_50GBASE_FR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 320 - [NFP_MEDIA_100GBASE_KR4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 321 - [NFP_MEDIA_100GBASE_SR4] = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 322 - [NFP_MEDIA_100GBASE_CR4] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 323 - [NFP_MEDIA_100GBASE_KP4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 324 - [NFP_MEDIA_100GBASE_CR10] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 296 + static const struct nfp_eth_media_link_mode { 297 + u16 ethtool_link_mode; 298 + u16 speed; 299 + } nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = { 300 + [NFP_MEDIA_1000BASE_CX] = { 301 + .ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 302 + .speed = NFP_SPEED_1G, 303 + }, 304 + [NFP_MEDIA_1000BASE_KX] = { 305 + .ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 306 + .speed = NFP_SPEED_1G, 307 + }, 308 + [NFP_MEDIA_10GBASE_KX4] = { 309 + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 310 + .speed = NFP_SPEED_10G, 311 + }, 312 + [NFP_MEDIA_10GBASE_KR] = { 313 + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 314 + .speed = NFP_SPEED_10G, 315 + }, 316 + [NFP_MEDIA_10GBASE_CX4] = { 317 + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 318 + .speed = NFP_SPEED_10G, 319 + }, 320 + [NFP_MEDIA_10GBASE_CR] = { 321 + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 322 + .speed = NFP_SPEED_10G, 323 + }, 324 + [NFP_MEDIA_10GBASE_SR] = { 325 + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 326 + .speed = NFP_SPEED_10G, 327 + }, 328 + [NFP_MEDIA_10GBASE_ER] = { 329 + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseER_Full_BIT, 330 + .speed = NFP_SPEED_10G, 331 + }, 332 + [NFP_MEDIA_25GBASE_KR] = { 333 + .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 334 + .speed = NFP_SPEED_25G, 335 + }, 336 + [NFP_MEDIA_25GBASE_KR_S] = { 337 + .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 338 + .speed = NFP_SPEED_25G, 339 + }, 340 + [NFP_MEDIA_25GBASE_CR] = { 341 + .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 342 + .speed = NFP_SPEED_25G, 343 + }, 344 + [NFP_MEDIA_25GBASE_CR_S] = { 345 + .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 346 + .speed = NFP_SPEED_25G, 347 + }, 348 + [NFP_MEDIA_25GBASE_SR] = { 349 + .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 350 + .speed = NFP_SPEED_25G, 351 + }, 352 + [NFP_MEDIA_40GBASE_CR4] = { 353 + .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 354 + .speed = NFP_SPEED_40G, 355 + }, 356 + [NFP_MEDIA_40GBASE_KR4] = { 357 + .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 358 + .speed = NFP_SPEED_40G, 359 + }, 360 + [NFP_MEDIA_40GBASE_SR4] = { 361 + .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 362 + .speed = NFP_SPEED_40G, 363 + }, 364 + [NFP_MEDIA_40GBASE_LR4] = { 365 + .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 366 + .speed = NFP_SPEED_40G, 367 + }, 368 + [NFP_MEDIA_50GBASE_KR] = { 369 + .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 370 + .speed = NFP_SPEED_50G, 371 + }, 372 + [NFP_MEDIA_50GBASE_SR] = { 373 + .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 374 + .speed = NFP_SPEED_50G, 375 + }, 376 + [NFP_MEDIA_50GBASE_CR] = { 377 + .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 378 + .speed = NFP_SPEED_50G, 379 + }, 380 + [NFP_MEDIA_50GBASE_LR] = { 381 + .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 382 + .speed = NFP_SPEED_50G, 383 + }, 384 + [NFP_MEDIA_50GBASE_ER] = { 385 + .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 386 + .speed = NFP_SPEED_50G, 387 + }, 388 + [NFP_MEDIA_50GBASE_FR] = { 389 + .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 390 + .speed = NFP_SPEED_50G, 391 + }, 392 + [NFP_MEDIA_100GBASE_KR4] = { 393 + .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 394 + .speed = NFP_SPEED_100G, 395 + }, 396 + [NFP_MEDIA_100GBASE_SR4] = { 397 + .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 398 + .speed = NFP_SPEED_100G, 399 + }, 400 + [NFP_MEDIA_100GBASE_CR4] = { 401 + .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 402 + .speed = NFP_SPEED_100G, 403 + }, 404 + [NFP_MEDIA_100GBASE_KP4] = { 405 + .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 406 + .speed = NFP_SPEED_100G, 407 + }, 408 + [NFP_MEDIA_100GBASE_CR10] = { 409 + .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 410 + .speed = NFP_SPEED_100G, 411 + }, 412 + }; 413 + 414 + static const unsigned int nfp_eth_speed_map[NFP_SUP_SPEED_NUMBER] = { 415 + [NFP_SPEED_1G] = SPEED_1000, 416 + [NFP_SPEED_10G] = SPEED_10000, 417 + [NFP_SPEED_25G] = SPEED_25000, 418 + [NFP_SPEED_40G] = SPEED_40000, 419 + [NFP_SPEED_50G] = SPEED_50000, 420 + [NFP_SPEED_100G] = SPEED_100000, 325 421 }; 326 422 327 423 static void nfp_add_media_link_mode(struct nfp_port *port, ··· 430 334 }; 431 335 struct nfp_cpp *cpp = port->app->cpp; 432 336 433 - if (nfp_eth_read_media(cpp, &ethm)) 337 + if (nfp_eth_read_media(cpp, &ethm)) { 338 + bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); 434 339 return; 340 + } 341 + 342 + bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); 435 343 436 344 for (u32 i = 0; i < 2; i++) { 437 345 supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]); ··· 444 344 445 345 for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) { 446 346 if (i < 64) { 447 - if (supported_modes[0] & BIT_ULL(i)) 448 - __set_bit(nfp_eth_media_table[i], 347 + if (supported_modes[0] & BIT_ULL(i)) { 348 + __set_bit(nfp_eth_media_table[i].ethtool_link_mode, 449 349 cmd->link_modes.supported); 350 + __set_bit(nfp_eth_media_table[i].speed, 351 + port->speed_bitmap); 352 + } 450 353 451 354 if (advertised_modes[0] & BIT_ULL(i)) 452 - __set_bit(nfp_eth_media_table[i], 355 + __set_bit(nfp_eth_media_table[i].ethtool_link_mode, 453 356 cmd->link_modes.advertising); 454 357 } else { 455 - if (supported_modes[1] & BIT_ULL(i - 64)) 456 - __set_bit(nfp_eth_media_table[i], 358 + if (supported_modes[1] & BIT_ULL(i - 64)) { 359 + __set_bit(nfp_eth_media_table[i].ethtool_link_mode, 457 360 cmd->link_modes.supported); 361 + __set_bit(nfp_eth_media_table[i].speed, 362 + port->speed_bitmap); 363 + } 458 364 459 365 if (advertised_modes[1] & BIT_ULL(i - 64)) 460 - __set_bit(nfp_eth_media_table[i], 366 + __set_bit(nfp_eth_media_table[i].ethtool_link_mode, 461 367 cmd->link_modes.advertising); 462 368 } 463 369 } ··· 574 468 575 469 if (cmd->base.speed != SPEED_UNKNOWN) { 576 470 u32 speed = cmd->base.speed / eth_port->lanes; 471 + bool is_supported = false; 472 + 473 + for (u32 i = 0; i < NFP_SUP_SPEED_NUMBER; i++) { 474 + if (cmd->base.speed == nfp_eth_speed_map[i] && 475 + test_bit(i, port->speed_bitmap)) { 476 + is_supported = true; 477 + break; 478 + } 479 + } 480 + 481 + if (!is_supported) { 482 + netdev_err(netdev, "Speed %u is not supported.\n", 483 + cmd->base.speed); 484 + err = -EINVAL; 485 + goto err_bad_set; 486 + } 577 487 578 488 if (req_aneg) { 579 489 netdev_err(netdev, "Speed changing is not allowed when working on autoneg mode.\n");
+12
drivers/net/ethernet/netronome/nfp/nfp_port.h
··· 38 38 NFP_PORT_CHANGED = 0, 39 39 }; 40 40 41 + enum { 42 + NFP_SPEED_1G, 43 + NFP_SPEED_10G, 44 + NFP_SPEED_25G, 45 + NFP_SPEED_40G, 46 + NFP_SPEED_50G, 47 + NFP_SPEED_100G, 48 + NFP_SUP_SPEED_NUMBER 49 + }; 50 + 41 51 /** 42 52 * struct nfp_port - structure representing NFP port 43 53 * @netdev: backpointer to associated netdev ··· 62 52 * @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change 63 53 * @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry 64 54 * @eth_stats: for %NFP_PORT_PHYS_PORT MAC stats if available 55 + * @speed_bitmap: for %NFP_PORT_PHYS_PORT supported speed bitmap 65 56 * @pf_id: for %NFP_PORT_PF_PORT, %NFP_PORT_VF_PORT ID of the PCI PF (0-3) 66 57 * @vf_id: for %NFP_PORT_VF_PORT ID of the PCI VF within @pf_id 67 58 * @pf_split: for %NFP_PORT_PF_PORT %true if PCI PF has more than one vNIC ··· 89 78 bool eth_forced; 90 79 struct nfp_eth_table_port *eth_port; 91 80 u8 __iomem *eth_stats; 81 + DECLARE_BITMAP(speed_bitmap, NFP_SUP_SPEED_NUMBER); 92 82 }; 93 83 /* NFP_PORT_PF_PORT, NFP_PORT_VF_PORT */ 94 84 struct {