* [PATCH 2/2] pwm: correct pwm->state.enabled handling to allow fops control @ 2024-11-26 21:24 Rafael V. Volkmer 2024-11-27 8:56 ` Uwe Kleine-König 0 siblings, 1 reply; 7+ messages in thread From: Rafael V. Volkmer @ 2024-11-26 21:24 UTC (permalink / raw) To: Uwe Kleine-König; +Cc: linux-pwm, linux-kernel, Rafael V. Volkmer Ensure pwm->state.enabled is consistently updated during enable and disable operations in ehrpwm_pwm_apply() to resolve this issue. Previously, when attempting to interact with the ti PWM driver through fops, the pwm->state.enabled field was not updated correctly after applying enable or disable. This led to a state mismatch where the driver's state detection logic prevented disabling the PWM through fops once it had been activated. Signed-off-by: Rafael V. Volkmer <rafael.v.volkmer@gmail.com> --- drivers/pwm/pwm-tiehrpwm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 0125e73b98df..9f939d535440 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -420,6 +420,7 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (!state->enabled) { if (enabled) ehrpwm_pwm_disable(chip, pwm); + pwm->state.enabled = false; return 0; } @@ -429,6 +430,7 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (!enabled) err = ehrpwm_pwm_enable(chip, pwm); + pwm->state.enabled = true; return err; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] pwm: correct pwm->state.enabled handling to allow fops control 2024-11-26 21:24 [PATCH 2/2] pwm: correct pwm->state.enabled handling to allow fops control Rafael V. Volkmer @ 2024-11-27 8:56 ` Uwe Kleine-König 2024-11-27 22:26 ` [PATCH v2] pwm: improve state handling in ehrpwm driver Rafael V. Volkmer 0 siblings, 1 reply; 7+ messages in thread From: Uwe Kleine-König @ 2024-11-27 8:56 UTC (permalink / raw) To: Rafael V. Volkmer; +Cc: linux-pwm, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1245 bytes --] Hello, On Tue, Nov 26, 2024 at 06:24:14PM -0300, Rafael V. Volkmer wrote: > Ensure pwm->state.enabled is consistently updated during enable and > disable operations in ehrpwm_pwm_apply() to resolve this issue. > > Previously, when attempting to interact with the ti PWM driver through > fops, the pwm->state.enabled field was not updated correctly after > applying enable or disable. This led to a state mismatch where the > driver's state detection logic prevented disabling the PWM through > fops once it had been activated. > > Signed-off-by: Rafael V. Volkmer <rafael.v.volkmer@gmail.com> > --- > drivers/pwm/pwm-tiehrpwm.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c > index 0125e73b98df..9f939d535440 100644 > --- a/drivers/pwm/pwm-tiehrpwm.c > +++ b/drivers/pwm/pwm-tiehrpwm.c > @@ -420,6 +420,7 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, > if (!state->enabled) { > if (enabled) > ehrpwm_pwm_disable(chip, pwm); > + pwm->state.enabled = false; This is a layer violation (pwm->state is under control of core.c only) and uses irritating indention. Please rethink! Best regards Uwe [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2] pwm: improve state handling in ehrpwm driver 2024-11-27 8:56 ` Uwe Kleine-König @ 2024-11-27 22:26 ` Rafael V. Volkmer 2024-11-28 9:59 ` Uwe Kleine-König 0 siblings, 1 reply; 7+ messages in thread From: Rafael V. Volkmer @ 2024-11-27 22:26 UTC (permalink / raw) To: ukleinek; +Cc: linux-kernel, linux-pwm, rafael.v.volkmer Introduce ehrpwm_is_enabled() to verify the module's enable/disable state by checking the AQCSFRC and AQCTLA registers, instead of relying solely on pwm->state.enabled. This ensures a more accurate representation of the ePWM state in the kernel. Previously, when performing fops operations directly in kernel space after retrieving the platform device (pdev)—bypassing the sysfs interface— pwm->state.enabled could incorrectly signal transitions between active and inactive states, leading to inconsistent behavior. Signed-off-by: Rafael V. Volkmer <rafael.v.volkmer@gmail.com> --- Hello Uwe, Thank you very much for the feedback. I understand your concern about the kernel layer structure, so I took a new approach that also fixes my problem, but this time without directly manipulating `pwm->state`, but rather through a double check of the registers within `apply`. I hope you can see the implementation and tell me, again, what you think. Best regards Changes in v2: - Implemented `ehrpwm_is_enabled()` to check hardware registers instead of relying on `pwm->state.enabled`. - Removed direct manipulation of `pwm->state` in `ehrpwm_pwm_apply()`. - Addressed your feedback regarding kernel layer structure. drivers/pwm/pwm-tiehrpwm.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 9f939d535440..fdcda0ffc9db 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -387,6 +387,25 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) pm_runtime_put_sync(pwmchip_parent(chip)); } +static bool ehrpwm_is_enabled(struct pwm_chip *chip) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + bool ret; + u16 aqcsfrc_reg; + u16 aqctla_reg; + u8 csfa_bits; + + aqcsfrc_reg = readw(pc->mmio_base + AQCSFRC); + csfa_bits = (u8)(aqcsfrc_reg & AQCSFRC_CSFA_MASK); + + aqctla_reg= readw(pc->mmio_base + AQCTLA); + + ret = (csfa_bits != 0u) ? false : + (aqctla_reg == 0u) ? false : true; + + return ret; +} + static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); @@ -404,7 +423,9 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { int err; - bool enabled = pwm->state.enabled; + bool enabled; + + enabled = (ehrpwm_is_enabled(chip) | pwm->state.enabled); if (state->polarity != pwm->state.polarity) { if (enabled) { @@ -417,10 +438,8 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return err; } - if (!state->enabled) { - if (enabled) - ehrpwm_pwm_disable(chip, pwm); + if ((state->enabled != enabled) && (state->enabled == false)) { + ehrpwm_pwm_disable(chip, pwm); return 0; } @@ -428,9 +447,10 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (err) return err; - if (!enabled) + if ((state->enabled != enabled) && (state->enabled == true)) { err = ehrpwm_pwm_enable(chip, pwm); + return err; + } return err; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2] pwm: improve state handling in ehrpwm driver 2024-11-27 22:26 ` [PATCH v2] pwm: improve state handling in ehrpwm driver Rafael V. Volkmer @ 2024-11-28 9:59 ` Uwe Kleine-König 2024-11-29 3:43 ` [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() Rafael V. Volkmer 0 siblings, 1 reply; 7+ messages in thread From: Uwe Kleine-König @ 2024-11-28 9:59 UTC (permalink / raw) To: Rafael V. Volkmer; +Cc: linux-kernel, linux-pwm [-- Attachment #1: Type: text/plain, Size: 2077 bytes --] Hello, Subject should use "pwm: tiehrpwm:" as prefix, then drop "in ehrpwm driver". On Wed, Nov 27, 2024 at 07:26:49PM -0300, Rafael V. Volkmer wrote: > Introduce ehrpwm_is_enabled() to verify the module's enable/disable state > by checking the AQCSFRC and AQCTLA registers, instead of relying solely > on pwm->state.enabled. This ensures a more accurate representation of > the ePWM state in the kernel. > > Previously, when performing fops operations directly in kernel space > after retrieving the platform device (pdev)—bypassing the sysfs interface— > pwm->state.enabled could incorrectly signal transitions between active > and inactive states, leading to inconsistent behavior. I don't see a problem in this driver but I wonder what you do trigger the problem you're describing. Are you saying some other driver calls ehrpwm_pwm_apply() directly bypassing the pwm core? If so: Don't. Otherwise I'd claim the only place where state.enabled can get out of sync is during .probe(). The driver might need something like: if (hw_is_enabled) { clk_enable(...) pm_runtime_get(...) } there and an implementation of .get_state(). BTW, .free() looks wrong; a driver isn't supposed to make up for a consumer failing to disable the hardware before it releases the pwm handle (but that's orthogonal to your problem I think). Am I missing something? > [...] > static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) > { > struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); > @@ -404,7 +423,9 @@ static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, > const struct pwm_state *state) > { > int err; > - bool enabled = pwm->state.enabled; > + bool enabled; > + > + enabled = (ehrpwm_is_enabled(chip) | pwm->state.enabled); || is the right operator for bools. No parenthesis are needed. ehrpwm_is_enabled() should never return something different than pwm->state.enabled. This is the thing you need to address. Don't paper over this. Best regards Uwe [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() 2024-11-28 9:59 ` Uwe Kleine-König @ 2024-11-29 3:43 ` Rafael V. Volkmer 2024-11-29 11:30 ` kernel test robot 2024-11-29 18:40 ` kernel test robot 0 siblings, 2 replies; 7+ messages in thread From: Rafael V. Volkmer @ 2024-11-29 3:43 UTC (permalink / raw) To: ukleinek; +Cc: linux-kernel, linux-pwm, rafael.v.volkmer Fixes potential desynchronization of state.enabled in the .probe() method by suggesting proper handling of hardware state initialization. Adds considerations for implementing .get_hw_state() to check the current state of the module by checking physical registers. Signed-off-by: Rafael V. Volkmer <rafael.v.volkmer@gmail.com> --- Hi, Uwe! Thanks again for the feedback! I have taken your findings into consideration again and am working on getting my application up and running. Regarding the points you mentioned earlier about the driver, I made this small patch, using some hardware validation functions I had in my possession, to check for occasionality. Best regards, Rafael V. Volkmer drivers/pwm/pwm-tiehrpwm.c | 162 ++++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 0125e73b98df..693704406f25 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -91,6 +91,15 @@ #define AQCSFRC_CSFA_FRCHIGH BIT(1) #define AQCSFRC_CSFA_DISSWFRC (BIT(1) | BIT(0)) +#define AQCTLA_CAU_MASK (BIT(5) | BIT(4)) +#define AQCTLA_CAU_SHIFT 4U + +#define AQCTLA_CAD_MASK (BIT(7) | BIT(6)) +#define AQCTLA_CAD_SHIFT 6U + +#define AQ_SET 0x1 +#define AQ_CLEAR 0x2 + #define NUM_PWM_CHANNEL 2 /* EHRPWM channels */ struct ehrpwm_context { @@ -400,6 +409,134 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) pc->period_cycles[pwm->hwpwm] = 0; } +static bool ehrpwm_is_enabled(struct pwm_chip *chip) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + + bool ret; + + u16 aqcsfrc_reg; + u8 csfa_bits; + + u16 aqctla_reg; + + if(chip == NULL) { + return -EINVAL; + } + + aqcsfrc_reg = readw(pc->mmio_base + AQCSFRC); + csfa_bits = (u8)(aqcsfrc_reg & AQCSFRC_CSFA_MASK); + + aqctla_reg = readw(pc->mmio_base + AQCTLA); + + ret = (csfa_bits != 0u) ? false : + (aqctla_reg == 0u) ? false : true; + + return ret; +} + +static u64 ehrpwm_read_period(struct pwm_chip *chip) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + + u64 ret; + + unsigned long tbclk_rate; + + u16 tbprd_reg; + u64 period_cycles; + u64 period_ns; + + if(chip == NULL) { + return -EINVAL; + } + + tbprd_reg = readw(pc->mmio_base + TBPRD); + tbclk_rate = clk_get_rate(pc->tbclk); + + period_cycles = tbprd_reg + 1u; + + /* period_ns = (period_cycles * 1e9) / tblck_rate */ + period_ns = DIV_ROUND_UP_ULL(period_cycles * NSEC_PER_SEC, tbclk_rate); + + ret = period_ns; + + return ret; +} + +static u64 ehrpwm_read_duty_cycle(struct pwm_chip *chip) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + + u64 ret; + + u16 cmpa_reg; + u64 duty_cycles; + u64 duty_ns; + + unsigned long tbclk_rate; + + if(chip == NULL) { + return -EINVAL; + } + + cmpa_reg = readw(pc->mmio_base + CMPA); + + tbclk_rate = clk_get_rate(pc->tbclk); + + duty_cycles = cmpa_reg; + + /* duty_ns = (duty_cycles * 1e9) / tblck_rate */ + duty_ns = DIV_ROUND_UP_ULL(duty_cycles * NSEC_PER_SEC, tbclk_rate); + + ret = duty_ns; + + return ret; +} + +static enum pwm_polarity ehrpwm_read_polarity(struct pwm_chip *chip) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + + enum pwm_polarity ret; + + u16 aqctla_reg; + u8 cau_action; + u8 cad_action; + + if(chip == NULL) { + return -EINVAL; + } + + aqctla_reg = readw(pc->mmio_base + AQCTLA); + + cau_action = (aqctla_reg & AQCTLA_CAU_MASK) >> AQCTLA_CAU_SHIFT; + cad_action = (aqctla_reg & AQCTLA_CAD_MASK) >> AQCTLA_CAD_SHIFT; + + ret = (cau_action == AQ_SET && cad_action == AQ_CLEAR) ? PWM_POLARITY_NORMAL : + (cau_action == AQ_CLEAR && cad_action == AQ_SET) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL; + + return ret; +} + +static int ehrpwm_get_hw_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + int ret; + + if(chip == NULL || pwm == NULL || state == NULL){ + return -EINVAL; + } + + state->enabled = ehrpwm_is_enabled(chip); + + state->period = ehrpwm_read_period(chip); + state->duty_cycle = ehrpwm_read_duty_cycle(chip); + state->polarity = ehrpwm_read_polarity(chip); + + return ret; +} + static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { @@ -450,6 +587,7 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct ehrpwm_pwm_chip *pc; struct pwm_chip *chip; + bool tbclk_enabled; struct clk *clk; int ret; @@ -501,10 +639,32 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); pm_runtime_enable(&pdev->dev); + ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); + + if(state.enabled == true) { + ret = clk_prepare_enable(pc->tbclk); + if (ret) { + dev_err(&pdev->dev, "clk_prepare_enable() failed: %d\n", ret); + goto err_pwmchip_remove; + } + + tbclk_enabled = true; + + ret = pm_runtime_get_sync(&pdev->dev); + if(ret < 0) { + dev_err(&pdev->dev, "pm_runtime_get_sync() failed: %d\n", ret); + clk_disable_unprepare(pc->tbclk); + goto err_pwmchip_remove; + } + } + return 0; +err_pwmchip_remove: + pwmchip_remove(&pc->chip); err_clk_unprepare: - clk_unprepare(pc->tbclk); + if(tbclk_enabled) + clk_unprepare(pc->tbclk); return ret; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() 2024-11-29 3:43 ` [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() Rafael V. Volkmer @ 2024-11-29 11:30 ` kernel test robot 2024-11-29 18:40 ` kernel test robot 1 sibling, 0 replies; 7+ messages in thread From: kernel test robot @ 2024-11-29 11:30 UTC (permalink / raw) To: Rafael V. Volkmer, ukleinek Cc: oe-kbuild-all, linux-kernel, linux-pwm, rafael.v.volkmer Hi Rafael, kernel test robot noticed the following build errors: [auto build test ERROR on linus/master] [also build test ERROR on v6.12 next-20241128] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Rafael-V-Volkmer/pwm-tiehrpwm-ensures-that-state-enabled-is-synchronized-during-probe/20241129-114649 base: linus/master patch link: https://lore.kernel.org/r/20241129034334.27203-1-rafael.v.volkmer%40gmail.com patch subject: [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() config: alpha-randconfig-r053-20241129 (https://download.01.org/0day-ci/archive/20241129/202411291940.6T4OMy3k-lkp@intel.com/config) compiler: alpha-linux-gcc (GCC) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241129/202411291940.6T4OMy3k-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202411291940.6T4OMy3k-lkp@intel.com/ All errors (new ones prefixed by >>): drivers/pwm/pwm-tiehrpwm.c: In function 'ehrpwm_pwm_probe': >> drivers/pwm/pwm-tiehrpwm.c:642:32: error: 'struct ehrpwm_pwm_chip' has no member named 'chip' 642 | ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); | ^~ drivers/pwm/pwm-tiehrpwm.c:642:43: error: 'struct ehrpwm_pwm_chip' has no member named 'chip' 642 | ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); | ^~ >> drivers/pwm/pwm-tiehrpwm.c:642:60: error: 'state' undeclared (first use in this function); did you mean 'statx'? 642 | ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); | ^~~~~ | statx drivers/pwm/pwm-tiehrpwm.c:642:60: note: each undeclared identifier is reported only once for each function it appears in drivers/pwm/pwm-tiehrpwm.c:664:27: error: 'struct ehrpwm_pwm_chip' has no member named 'chip' 664 | pwmchip_remove(&pc->chip); | ^~ vim +642 drivers/pwm/pwm-tiehrpwm.c 584 585 static int ehrpwm_pwm_probe(struct platform_device *pdev) 586 { 587 struct device_node *np = pdev->dev.of_node; 588 struct ehrpwm_pwm_chip *pc; 589 struct pwm_chip *chip; 590 bool tbclk_enabled; 591 struct clk *clk; 592 int ret; 593 594 chip = devm_pwmchip_alloc(&pdev->dev, NUM_PWM_CHANNEL, sizeof(*pc)); 595 if (IS_ERR(chip)) 596 return PTR_ERR(chip); 597 pc = to_ehrpwm_pwm_chip(chip); 598 599 clk = devm_clk_get(&pdev->dev, "fck"); 600 if (IS_ERR(clk)) { 601 if (of_device_is_compatible(np, "ti,am33xx-ecap")) { 602 dev_warn(&pdev->dev, "Binding is obsolete.\n"); 603 clk = devm_clk_get(pdev->dev.parent, "fck"); 604 } 605 } 606 607 if (IS_ERR(clk)) 608 return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Failed to get fck\n"); 609 610 pc->clk_rate = clk_get_rate(clk); 611 if (!pc->clk_rate) { 612 dev_err(&pdev->dev, "failed to get clock rate\n"); 613 return -EINVAL; 614 } 615 616 chip->ops = &ehrpwm_pwm_ops; 617 618 pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); 619 if (IS_ERR(pc->mmio_base)) 620 return PTR_ERR(pc->mmio_base); 621 622 /* Acquire tbclk for Time Base EHRPWM submodule */ 623 pc->tbclk = devm_clk_get(&pdev->dev, "tbclk"); 624 if (IS_ERR(pc->tbclk)) 625 return dev_err_probe(&pdev->dev, PTR_ERR(pc->tbclk), "Failed to get tbclk\n"); 626 627 ret = clk_prepare(pc->tbclk); 628 if (ret < 0) { 629 dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret); 630 return ret; 631 } 632 633 ret = pwmchip_add(chip); 634 if (ret < 0) { 635 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 636 goto err_clk_unprepare; 637 } 638 639 platform_set_drvdata(pdev, chip); 640 pm_runtime_enable(&pdev->dev); 641 > 642 ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); 643 644 if(state.enabled == true) { 645 ret = clk_prepare_enable(pc->tbclk); 646 if (ret) { 647 dev_err(&pdev->dev, "clk_prepare_enable() failed: %d\n", ret); 648 goto err_pwmchip_remove; 649 } 650 651 tbclk_enabled = true; 652 653 ret = pm_runtime_get_sync(&pdev->dev); 654 if(ret < 0) { 655 dev_err(&pdev->dev, "pm_runtime_get_sync() failed: %d\n", ret); 656 clk_disable_unprepare(pc->tbclk); 657 goto err_pwmchip_remove; 658 } 659 } 660 661 return 0; 662 663 err_pwmchip_remove: 664 pwmchip_remove(&pc->chip); 665 err_clk_unprepare: 666 if(tbclk_enabled) 667 clk_unprepare(pc->tbclk); 668 669 return ret; 670 } 671 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() 2024-11-29 3:43 ` [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() Rafael V. Volkmer 2024-11-29 11:30 ` kernel test robot @ 2024-11-29 18:40 ` kernel test robot 1 sibling, 0 replies; 7+ messages in thread From: kernel test robot @ 2024-11-29 18:40 UTC (permalink / raw) To: Rafael V. Volkmer, ukleinek Cc: llvm, oe-kbuild-all, linux-kernel, linux-pwm, rafael.v.volkmer Hi Rafael, kernel test robot noticed the following build errors: [auto build test ERROR on linus/master] [also build test ERROR on v6.12 next-20241128] [cannot apply to thierry-reding-pwm/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Rafael-V-Volkmer/pwm-tiehrpwm-ensures-that-state-enabled-is-synchronized-during-probe/20241129-114649 base: linus/master patch link: https://lore.kernel.org/r/20241129034334.27203-1-rafael.v.volkmer%40gmail.com patch subject: [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() config: x86_64-buildonly-randconfig-002-20241129 (https://download.01.org/0day-ci/archive/20241130/202411300250.wkH4Isc0-lkp@intel.com/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241130/202411300250.wkH4Isc0-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202411300250.wkH4Isc0-lkp@intel.com/ All error/warnings (new ones prefixed by >>): >> drivers/pwm/pwm-tiehrpwm.c:537:9: warning: variable 'ret' is uninitialized when used here [-Wuninitialized] 537 | return ret; | ^~~ drivers/pwm/pwm-tiehrpwm.c:525:9: note: initialize the variable 'ret' to silence this warning 525 | int ret; | ^ | = 0 >> drivers/pwm/pwm-tiehrpwm.c:642:27: error: no member named 'chip' in 'struct ehrpwm_pwm_chip' 642 | ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); | ~~ ^ drivers/pwm/pwm-tiehrpwm.c:642:38: error: no member named 'chip' in 'struct ehrpwm_pwm_chip' 642 | ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); | ~~ ^ >> drivers/pwm/pwm-tiehrpwm.c:642:53: error: use of undeclared identifier 'state'; did you mean 'stac'? 642 | ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); | ^~~~~ | stac arch/x86/include/asm/smap.h:36:29: note: 'stac' declared here 36 | static __always_inline void stac(void) | ^ drivers/pwm/pwm-tiehrpwm.c:644:5: error: use of undeclared identifier 'state' 644 | if(state.enabled == true) { | ^ drivers/pwm/pwm-tiehrpwm.c:664:22: error: no member named 'chip' in 'struct ehrpwm_pwm_chip' 664 | pwmchip_remove(&pc->chip); | ~~ ^ 1 warning and 5 errors generated. vim +642 drivers/pwm/pwm-tiehrpwm.c 521 522 static int ehrpwm_get_hw_state(struct pwm_chip *chip, struct pwm_device *pwm, 523 struct pwm_state *state) 524 { 525 int ret; 526 527 if(chip == NULL || pwm == NULL || state == NULL){ 528 return -EINVAL; 529 } 530 531 state->enabled = ehrpwm_is_enabled(chip); 532 533 state->period = ehrpwm_read_period(chip); 534 state->duty_cycle = ehrpwm_read_duty_cycle(chip); 535 state->polarity = ehrpwm_read_polarity(chip); 536 > 537 return ret; 538 } 539 540 static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 541 const struct pwm_state *state) 542 { 543 int err; 544 bool enabled = pwm->state.enabled; 545 546 if (state->polarity != pwm->state.polarity) { 547 if (enabled) { 548 ehrpwm_pwm_disable(chip, pwm); 549 enabled = false; 550 } 551 552 err = ehrpwm_pwm_set_polarity(chip, pwm, state->polarity); 553 if (err) 554 return err; 555 } 556 557 if (!state->enabled) { 558 if (enabled) 559 ehrpwm_pwm_disable(chip, pwm); 560 return 0; 561 } 562 563 err = ehrpwm_pwm_config(chip, pwm, state->duty_cycle, state->period); 564 if (err) 565 return err; 566 567 if (!enabled) 568 err = ehrpwm_pwm_enable(chip, pwm); 569 570 return err; 571 } 572 573 static const struct pwm_ops ehrpwm_pwm_ops = { 574 .free = ehrpwm_pwm_free, 575 .apply = ehrpwm_pwm_apply, 576 }; 577 578 static const struct of_device_id ehrpwm_of_match[] = { 579 { .compatible = "ti,am3352-ehrpwm" }, 580 { .compatible = "ti,am33xx-ehrpwm" }, 581 {}, 582 }; 583 MODULE_DEVICE_TABLE(of, ehrpwm_of_match); 584 585 static int ehrpwm_pwm_probe(struct platform_device *pdev) 586 { 587 struct device_node *np = pdev->dev.of_node; 588 struct ehrpwm_pwm_chip *pc; 589 struct pwm_chip *chip; 590 bool tbclk_enabled; 591 struct clk *clk; 592 int ret; 593 594 chip = devm_pwmchip_alloc(&pdev->dev, NUM_PWM_CHANNEL, sizeof(*pc)); 595 if (IS_ERR(chip)) 596 return PTR_ERR(chip); 597 pc = to_ehrpwm_pwm_chip(chip); 598 599 clk = devm_clk_get(&pdev->dev, "fck"); 600 if (IS_ERR(clk)) { 601 if (of_device_is_compatible(np, "ti,am33xx-ecap")) { 602 dev_warn(&pdev->dev, "Binding is obsolete.\n"); 603 clk = devm_clk_get(pdev->dev.parent, "fck"); 604 } 605 } 606 607 if (IS_ERR(clk)) 608 return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Failed to get fck\n"); 609 610 pc->clk_rate = clk_get_rate(clk); 611 if (!pc->clk_rate) { 612 dev_err(&pdev->dev, "failed to get clock rate\n"); 613 return -EINVAL; 614 } 615 616 chip->ops = &ehrpwm_pwm_ops; 617 618 pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); 619 if (IS_ERR(pc->mmio_base)) 620 return PTR_ERR(pc->mmio_base); 621 622 /* Acquire tbclk for Time Base EHRPWM submodule */ 623 pc->tbclk = devm_clk_get(&pdev->dev, "tbclk"); 624 if (IS_ERR(pc->tbclk)) 625 return dev_err_probe(&pdev->dev, PTR_ERR(pc->tbclk), "Failed to get tbclk\n"); 626 627 ret = clk_prepare(pc->tbclk); 628 if (ret < 0) { 629 dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret); 630 return ret; 631 } 632 633 ret = pwmchip_add(chip); 634 if (ret < 0) { 635 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 636 goto err_clk_unprepare; 637 } 638 639 platform_set_drvdata(pdev, chip); 640 pm_runtime_enable(&pdev->dev); 641 > 642 ehrpwm_get_hw_state(&pc->chip, &pc->chip.pwms[0], &state); 643 644 if(state.enabled == true) { 645 ret = clk_prepare_enable(pc->tbclk); 646 if (ret) { 647 dev_err(&pdev->dev, "clk_prepare_enable() failed: %d\n", ret); 648 goto err_pwmchip_remove; 649 } 650 651 tbclk_enabled = true; 652 653 ret = pm_runtime_get_sync(&pdev->dev); 654 if(ret < 0) { 655 dev_err(&pdev->dev, "pm_runtime_get_sync() failed: %d\n", ret); 656 clk_disable_unprepare(pc->tbclk); 657 goto err_pwmchip_remove; 658 } 659 } 660 661 return 0; 662 663 err_pwmchip_remove: 664 pwmchip_remove(&pc->chip); 665 err_clk_unprepare: 666 if(tbclk_enabled) 667 clk_unprepare(pc->tbclk); 668 669 return ret; 670 } 671 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-11-29 18:40 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-11-26 21:24 [PATCH 2/2] pwm: correct pwm->state.enabled handling to allow fops control Rafael V. Volkmer 2024-11-27 8:56 ` Uwe Kleine-König 2024-11-27 22:26 ` [PATCH v2] pwm: improve state handling in ehrpwm driver Rafael V. Volkmer 2024-11-28 9:59 ` Uwe Kleine-König 2024-11-29 3:43 ` [PATCH] pwm: tiehrpwm: ensures that state.enabled is synchronized during .probe() Rafael V. Volkmer 2024-11-29 11:30 ` kernel test robot 2024-11-29 18:40 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox