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.

platform/mellanox: mlxreg-lc: Fix locking issue

Fix locking issues:
- mlxreg_lc_state_update() takes a lock when set or clear
"MLXREG_LC_POWERED".
- All the devices can be deleted before MLXREG_LC_POWERED flag is cleared.

To fix it:
- Add lock() / unlock() at the beginning / end of
mlxreg_lc_event_handler() and remove locking from
mlxreg_lc_power_on_off() and mlxreg_lc_enable_disable()
- Add locked version of mlxreg_lc_state_update() -
mlxreg_lc_state_update_locked() for using outside
mlxreg_lc_event_handler().

(2) Remove redundant NULL check for of if 'data->notifier'.

Fixes: 62f9529b8d5c87b ("platform/mellanox: mlxreg-lc: Add initial support for Nvidia line card devices")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Link: https://lore.kernel.org/r/20220823201937.46855-3-vadimp@nvidia.com
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Vadim Pasternak and committed by
Hans de Goede
52e01c0b 16b36a95

+25 -12
+25 -12
drivers/platform/mellanox/mlxreg-lc.c
··· 460 460 u32 regval; 461 461 int err; 462 462 463 - mutex_lock(&mlxreg_lc->lock); 464 - 465 463 err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval); 466 464 if (err) 467 465 goto regmap_read_fail; ··· 472 474 err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, regval); 473 475 474 476 regmap_read_fail: 475 - mutex_unlock(&mlxreg_lc->lock); 476 477 return err; 477 478 } 478 479 ··· 488 491 * line card which is already has been enabled. Disabling does not affect the disabled line 489 492 * card. 490 493 */ 491 - mutex_lock(&mlxreg_lc->lock); 492 - 493 494 err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, &regval); 494 495 if (err) 495 496 goto regmap_read_fail; ··· 500 505 err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, regval); 501 506 502 507 regmap_read_fail: 503 - mutex_unlock(&mlxreg_lc->lock); 504 508 return err; 505 509 } 506 510 ··· 532 538 static void 533 539 mlxreg_lc_state_update(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action) 534 540 { 541 + if (action) 542 + mlxreg_lc->state |= state; 543 + else 544 + mlxreg_lc->state &= ~state; 545 + } 546 + 547 + static void 548 + mlxreg_lc_state_update_locked(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action) 549 + { 535 550 mutex_lock(&mlxreg_lc->lock); 536 551 537 552 if (action) ··· 563 560 dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n", 564 561 mlxreg_lc->data->slot, mlxreg_lc->state, kind, action); 565 562 566 - if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED)) 563 + mutex_lock(&mlxreg_lc->lock); 564 + if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED)) { 565 + mutex_unlock(&mlxreg_lc->lock); 567 566 return 0; 567 + } 568 568 569 569 switch (kind) { 570 570 case MLXREG_HOTPLUG_LC_SYNCED: ··· 580 574 if (!(mlxreg_lc->state & MLXREG_LC_POWERED) && action) { 581 575 err = mlxreg_lc_power_on_off(mlxreg_lc, 1); 582 576 if (err) 583 - return err; 577 + goto mlxreg_lc_power_on_off_fail; 584 578 } 585 579 /* In case line card is configured - enable it. */ 586 580 if (mlxreg_lc->state & MLXREG_LC_CONFIGURED && action) ··· 594 588 /* In case line card is configured - enable it. */ 595 589 if (mlxreg_lc->state & MLXREG_LC_CONFIGURED) 596 590 err = mlxreg_lc_enable_disable(mlxreg_lc, 1); 591 + mutex_unlock(&mlxreg_lc->lock); 597 592 return err; 598 593 } 599 594 err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs, 600 595 mlxreg_lc->main_devs_num); 601 596 if (err) 602 - return err; 597 + goto mlxreg_lc_create_static_devices_fail; 603 598 604 599 /* In case line card is already in ready state - enable it. */ 605 600 if (mlxreg_lc->state & MLXREG_LC_CONFIGURED) ··· 626 619 default: 627 620 break; 628 621 } 622 + 623 + mlxreg_lc_power_on_off_fail: 624 + mlxreg_lc_create_static_devices_fail: 625 + mutex_unlock(&mlxreg_lc->lock); 629 626 630 627 return err; 631 628 } ··· 676 665 if (err) 677 666 goto mlxreg_lc_create_static_devices_failed; 678 667 679 - mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, 1); 668 + mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_POWERED, 1); 680 669 } 681 670 682 671 /* Verify if line card is synchronized. */ ··· 687 676 /* Power on line card if necessary. */ 688 677 if (regval & mlxreg_lc->data->mask) { 689 678 mlxreg_lc->state |= MLXREG_LC_SYNCED; 690 - mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, 1); 679 + mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_SYNCED, 1); 691 680 if (mlxreg_lc->state & ~MLXREG_LC_POWERED) { 692 681 err = mlxreg_lc_power_on_off(mlxreg_lc, 1); 693 682 if (err) ··· 695 684 } 696 685 } 697 686 698 - mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_INITIALIZED, 1); 687 + mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 1); 699 688 700 689 return 0; 701 690 ··· 914 903 { 915 904 struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev); 916 905 struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev); 906 + 907 + mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 0); 917 908 918 909 /* 919 910 * Probing and removing are invoked by hotplug events raised upon line card insertion and