Skip to content
/ linux Public

Commit 52e01c0

Browse files
vadimp-nvidiajwrdegoede
authored andcommitted
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: 62f9529 ("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>
1 parent 16b36a9 commit 52e01c0

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

drivers/platform/mellanox/mlxreg-lc.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,6 @@ static int mlxreg_lc_power_on_off(struct mlxreg_lc *mlxreg_lc, u8 action)
460460
u32 regval;
461461
int err;
462462

463-
mutex_lock(&mlxreg_lc->lock);
464-
465463
err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);
466464
if (err)
467465
goto regmap_read_fail;
@@ -474,7 +472,6 @@ static int mlxreg_lc_power_on_off(struct mlxreg_lc *mlxreg_lc, u8 action)
474472
err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, regval);
475473

476474
regmap_read_fail:
477-
mutex_unlock(&mlxreg_lc->lock);
478475
return err;
479476
}
480477

@@ -491,8 +488,6 @@ static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)
491488
* line card which is already has been enabled. Disabling does not affect the disabled line
492489
* card.
493490
*/
494-
mutex_lock(&mlxreg_lc->lock);
495-
496491
err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, &regval);
497492
if (err)
498493
goto regmap_read_fail;
@@ -505,7 +500,6 @@ static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)
505500
err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, regval);
506501

507502
regmap_read_fail:
508-
mutex_unlock(&mlxreg_lc->lock);
509503
return err;
510504
}
511505

@@ -537,6 +531,15 @@ mlxreg_lc_sn4800_c16_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,
537531

538532
static void
539533
mlxreg_lc_state_update(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
534+
{
535+
if (action)
536+
mlxreg_lc->state |= state;
537+
else
538+
mlxreg_lc->state &= ~state;
539+
}
540+
541+
static void
542+
mlxreg_lc_state_update_locked(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
540543
{
541544
mutex_lock(&mlxreg_lc->lock);
542545

@@ -560,8 +563,11 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
560563
dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n",
561564
mlxreg_lc->data->slot, mlxreg_lc->state, kind, action);
562565

563-
if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED))
566+
mutex_lock(&mlxreg_lc->lock);
567+
if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED)) {
568+
mutex_unlock(&mlxreg_lc->lock);
564569
return 0;
570+
}
565571

566572
switch (kind) {
567573
case MLXREG_HOTPLUG_LC_SYNCED:
@@ -574,7 +580,7 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
574580
if (!(mlxreg_lc->state & MLXREG_LC_POWERED) && action) {
575581
err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
576582
if (err)
577-
return err;
583+
goto mlxreg_lc_power_on_off_fail;
578584
}
579585
/* In case line card is configured - enable it. */
580586
if (mlxreg_lc->state & MLXREG_LC_CONFIGURED && action)
@@ -588,12 +594,13 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
588594
/* In case line card is configured - enable it. */
589595
if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
590596
err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
597+
mutex_unlock(&mlxreg_lc->lock);
591598
return err;
592599
}
593600
err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
594601
mlxreg_lc->main_devs_num);
595602
if (err)
596-
return err;
603+
goto mlxreg_lc_create_static_devices_fail;
597604

598605
/* In case line card is already in ready state - enable it. */
599606
if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
@@ -620,6 +627,10 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
620627
break;
621628
}
622629

630+
mlxreg_lc_power_on_off_fail:
631+
mlxreg_lc_create_static_devices_fail:
632+
mutex_unlock(&mlxreg_lc->lock);
633+
623634
return err;
624635
}
625636

@@ -665,7 +676,7 @@ static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
665676
if (err)
666677
goto mlxreg_lc_create_static_devices_failed;
667678

668-
mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, 1);
679+
mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_POWERED, 1);
669680
}
670681

671682
/* Verify if line card is synchronized. */
@@ -676,15 +687,15 @@ static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
676687
/* Power on line card if necessary. */
677688
if (regval & mlxreg_lc->data->mask) {
678689
mlxreg_lc->state |= MLXREG_LC_SYNCED;
679-
mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, 1);
690+
mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_SYNCED, 1);
680691
if (mlxreg_lc->state & ~MLXREG_LC_POWERED) {
681692
err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
682693
if (err)
683694
goto mlxreg_lc_regmap_power_on_off_fail;
684695
}
685696
}
686697

687-
mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);
698+
mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);
688699

689700
return 0;
690701

@@ -904,6 +915,8 @@ static int mlxreg_lc_remove(struct platform_device *pdev)
904915
struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
905916
struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev);
906917

918+
mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 0);
919+
907920
/*
908921
* Probing and removing are invoked by hotplug events raised upon line card insertion and
909922
* removing. If probing procedure fails all data is cleared. However, hotplug event still

0 commit comments

Comments
 (0)