lists.linaro.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
List overview
Download
linaro-toolchain
----- 2024 -----
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
linaro-toolchain@lists.linaro.org
9 participants
5482 discussions
Start a n
N
ew thread
[CI-NOTIFY]: TCWG Bisect tcwg_kernel/gnu-release-arm-stable-allyesconfig - Build # 1 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *linux* in CI configuration tcwg_kernel/gnu-release-arm-stable-allyesconfig. So far, this commit has regressed CI configurations: - tcwg_kernel/gnu-release-arm-stable-allyesconfig Culprit: <cut> commit 341db343768bc44f3512facc464021730d64071c Author: Linus Walleij <linus.walleij(a)linaro.org> Date: Sun May 23 00:50:39 2021 +0200 power: supply: ab8500: Move to componentized binding [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ] The driver has problems with the different components of the charging code racing with each other to probe(). This results in all four subdrivers populating battery information to ascertain that it is populated for their own needs for example. Fix this by using component probing and thus expressing to the kernel that these are dependent components. The probes can happen in any order and will only acquire resources such as state container, regulators and interrupts and initialize the data structures, but no execution happens until the .bind() callback is called. The charging driver is the main component and binds first, then bind in order the three subcomponents: ab8500-fg, ab8500-btemp and ab8500-chargalg. Do some housekeeping while we are moving the code around. Like use devm_* for IRQs so as to cut down on some boilerplate. Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel(a)collabora.com> Signed-off-by: Sasha Levin <sashal(a)kernel.org> </cut> Results regressed to (for first_bad == 341db343768bc44f3512facc464021730d64071c) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1: -5 # build_abe qemu: -2 # linux_n_obj: 19543 # First few build errors in logs: # 00:19:53 drivers/power/supply/ab8500_fg.c:3061:39: error: ‘np’ undeclared (first use in this function); did you mean ‘up’? # 00:19:53 make[3]: *** [drivers/power/supply/ab8500_fg.o] Error 1 # 00:21:11 make[2]: *** [drivers/power/supply] Error 2 # 00:21:11 make[1]: *** [drivers/power] Error 2 # 00:28:45 make: *** [drivers] Error 2 from (for last_good == dc72a15859b2e604abb8a4bff123fbac8a0be92a) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1: -5 # build_abe qemu: -2 # linux_n_obj: 19631 # linux build successful: all Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
Build top page/logs:
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
Configuration details: Reproduce builds: <cut> mkdir investigate-linux-341db343768bc44f3512facc464021730d64071c cd investigate-linux-341db343768bc44f3512facc464021730d64071c git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /linux/ ./ ./bisect/baseline/ cd linux # Reproduce first_bad build git checkout --detach 341db343768bc44f3512facc464021730d64071c ../artifacts/test.sh # Reproduce last_good build git checkout --detach dc72a15859b2e604abb8a4bff123fbac8a0be92a ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
Build log:
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-release-arm-stable-all…
Full commit (up to 1000 lines): <cut> commit 341db343768bc44f3512facc464021730d64071c Author: Linus Walleij <linus.walleij(a)linaro.org> Date: Sun May 23 00:50:39 2021 +0200 power: supply: ab8500: Move to componentized binding [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ] The driver has problems with the different components of the charging code racing with each other to probe(). This results in all four subdrivers populating battery information to ascertain that it is populated for their own needs for example. Fix this by using component probing and thus expressing to the kernel that these are dependent components. The probes can happen in any order and will only acquire resources such as state container, regulators and interrupts and initialize the data structures, but no execution happens until the .bind() callback is called. The charging driver is the main component and binds first, then bind in order the three subcomponents: ab8500-fg, ab8500-btemp and ab8500-chargalg. Do some housekeeping while we are moving the code around. Like use devm_* for IRQs so as to cut down on some boilerplate. Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel(a)collabora.com> Signed-off-by: Sasha Levin <sashal(a)kernel.org> --- drivers/power/supply/ab8500-bm.h | 4 + drivers/power/supply/ab8500_btemp.c | 118 +++++------- drivers/power/supply/ab8500_charger.c | 339 +++++++++++++++++++-------------- drivers/power/supply/ab8500_fg.c | 136 +++++++------ drivers/power/supply/abx500_chargalg.c | 116 ++++++----- 5 files changed, 379 insertions(+), 334 deletions(-) diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h index 41c69a4f2a1f..012595a9d269 100644 --- a/drivers/power/supply/ab8500-bm.h +++ b/drivers/power/supply/ab8500-bm.h @@ -730,4 +730,8 @@ int ab8500_bm_of_probe(struct device *dev, struct device_node *np, struct abx500_bm_data *bm); +extern struct platform_driver ab8500_fg_driver; +extern struct platform_driver ab8500_btemp_driver; +extern struct platform_driver abx500_chargalg_driver; + #endif /* _AB8500_CHARGER_H_ */ diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index fdfcd59fc43e..3598b5a748e7 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> @@ -932,26 +933,6 @@ static int __maybe_unused ab8500_btemp_suspend(struct device *dev) return 0; } -static int ab8500_btemp_remove(struct platform_device *pdev) -{ - struct ab8500_btemp *di = platform_get_drvdata(pdev); - int i, irq; - - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } - - /* Delete the work queue */ - destroy_workqueue(di->btemp_wq); - - flush_scheduled_work(); - power_supply_unregister(di->btemp_psy); - - return 0; -} - static char *supply_interface[] = { "ab8500_chargalg", "ab8500_fg", @@ -966,6 +947,40 @@ static const struct power_supply_desc ab8500_btemp_desc = { .external_power_changed = ab8500_btemp_external_power_changed, }; +static int ab8500_btemp_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Create a work queue for the btemp */ + di->btemp_wq = + alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); + if (di->btemp_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Kick off periodic temperature measurements */ + ab8500_btemp_periodic(di, true); + + return 0; +} + +static void ab8500_btemp_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Delete the work queue */ + destroy_workqueue(di->btemp_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_btemp_component_ops = { + .bind = ab8500_btemp_bind, + .unbind = ab8500_btemp_unbind, +}; + static int ab8500_btemp_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1011,14 +1026,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); psy_cfg.drv_data = di; - /* Create a work queue for the btemp */ - di->btemp_wq = - alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); - if (di->btemp_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for measuring temperature periodically */ INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, ab8500_btemp_periodic_work); @@ -1031,7 +1038,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) AB8500_BTEMP_HIGH_TH, &val); if (ret < 0) { dev_err(dev, "%s ab8500 read failed\n", __func__); - goto free_btemp_wq; + return ret; } switch (val) { case BTEMP_HIGH_TH_57_0: @@ -1050,30 +1057,28 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } /* Register BTEMP power supply class */ - di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc, - &psy_cfg); + di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc, + &psy_cfg); if (IS_ERR(di->btemp_psy)) { dev_err(dev, "failed to register BTEMP psy\n"); - ret = PTR_ERR(di->btemp_psy); - goto free_btemp_wq; + return PTR_ERR(di->btemp_psy); } /* Register interrupts */ for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_btemp_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_btemp_irq[i].name, di); if (ret) { dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_btemp_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_btemp_irq[i].name, irq, ret); @@ -1081,23 +1086,16 @@ static int ab8500_btemp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, di); - /* Kick off periodic temperature measurements */ - ab8500_btemp_periodic(di, true); list_add_tail(&di->node, &ab8500_btemp_list); - return ret; + return component_add(dev, &ab8500_btemp_component_ops); +} -free_irq: - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } +static int ab8500_btemp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &ab8500_btemp_component_ops); - power_supply_unregister(di->btemp_psy); -free_btemp_wq: - destroy_workqueue(di->btemp_wq); - return ret; + return 0; } static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); @@ -1107,7 +1105,7 @@ static const struct of_device_id ab8500_btemp_match[] = { { }, }; -static struct platform_driver ab8500_btemp_driver = { +struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = ab8500_btemp_remove, .driver = { @@ -1116,20 +1114,6 @@ static struct platform_driver ab8500_btemp_driver = { .pm = &ab8500_btemp_pm_ops, }, }; - -static int __init ab8500_btemp_init(void) -{ - return platform_driver_register(&ab8500_btemp_driver); -} - -static void __exit ab8500_btemp_exit(void) -{ - platform_driver_unregister(&ab8500_btemp_driver); -} - -device_initcall(ab8500_btemp_init); -module_exit(ab8500_btemp_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); MODULE_ALIAS("platform:ab8500-btemp"); diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index a9be10eb2c22..af32cfae9f19 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/notifier.h> @@ -3276,10 +3277,74 @@ static struct notifier_block charger_nb = { .notifier_call = ab8500_external_charger_prepare, }; -static int ab8500_charger_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static const struct power_supply_desc ab8500_ac_chg_desc = { + .name = "ab8500_ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = ab8500_charger_ac_props, + .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), + .get_property = ab8500_charger_ac_get_property, +}; + +static const struct power_supply_desc ab8500_usb_chg_desc = { + .name = "ab8500_usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = ab8500_charger_usb_props, + .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), + .get_property = ab8500_charger_usb_get_property, +}; + +static int ab8500_charger_bind(struct device *dev) { - struct ab8500_charger *di = platform_get_drvdata(pdev); - int i, irq, ret; + struct ab8500_charger *di = dev_get_drvdata(dev); + int ch_stat; + int ret; + + /* Create a work queue for the charger */ + di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", + WQ_MEM_RECLAIM); + if (di->charger_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + ch_stat = ab8500_charger_detect_chargers(di, false); + + if (ch_stat & AC_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->ac_charger_attached_work, + HZ); + } + if (ch_stat & USB_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->usb_charger_attached_work, + HZ); + di->vbus_detected = true; + di->vbus_detected_start = true; + queue_work(di->charger_wq, + &di->detect_usb_type_work); + } + + ret = component_bind_all(dev, di); + if (ret) { + dev_err(dev, "can't bind component devices\n"); + return ret; + } + + return 0; +} + +static void ab8500_charger_unbind(struct device *dev) +{ + struct ab8500_charger *di = dev_get_drvdata(dev); + int ret; /* Disable AC charging */ ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); @@ -3287,68 +3352,47 @@ static int ab8500_charger_remove(struct platform_device *pdev) /* Disable USB charging */ ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } - /* Backup battery voltage and current disable */ ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); if (ret < 0) dev_err(di->dev, "%s mask and set failed\n", __func__); - usb_unregister_notifier(di->usb_phy, &di->nb); - usb_put_phy(di->usb_phy); - /* Delete the work queue */ destroy_workqueue(di->charger_wq); - /* Unregister external charger enable notifier */ - if (!di->ac_chg.enabled) - blocking_notifier_chain_unregister( - &charger_notifier_list, &charger_nb); - flush_scheduled_work(); - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); - - if (di->ac_chg.enabled && !di->ac_chg.external) - power_supply_unregister(di->ac_chg.psy); - return 0; + /* Unbind fg, btemp, algorithm */ + component_unbind_all(dev, di); } -static char *supply_interface[] = { - "ab8500_chargalg", - "ab8500_fg", - "ab8500_btemp", +static const struct component_master_ops ab8500_charger_comp_ops = { + .bind = ab8500_charger_bind, + .unbind = ab8500_charger_unbind, }; -static const struct power_supply_desc ab8500_ac_chg_desc = { - .name = "ab8500_ac", - .type = POWER_SUPPLY_TYPE_MAINS, - .properties = ab8500_charger_ac_props, - .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), - .get_property = ab8500_charger_ac_get_property, +static struct platform_driver *const ab8500_charger_component_drivers[] = { + &ab8500_fg_driver, + &ab8500_btemp_driver, + &abx500_chargalg_driver, }; -static const struct power_supply_desc ab8500_usb_chg_desc = { - .name = "ab8500_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = ab8500_charger_usb_props, - .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), - .get_property = ab8500_charger_usb_get_property, -}; +static int ab8500_charger_compare_dev(struct device *dev, void *data) +{ + return dev == data; +} static int ab8500_charger_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct component_match *match = NULL; struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; struct ab8500_charger *di; - int irq, i, charger_status, ret = 0, ch_stat; - struct device *dev = &pdev->dev; + int charger_status; + int i, irq; + int ret; di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); if (!di) @@ -3393,6 +3437,38 @@ static int ab8500_charger_probe(struct platform_device *pdev) return ret; } + /* + * VDD ADC supply needs to be enabled from this driver when there + * is a charger connected to avoid erroneous BTEMP_HIGH/LOW + * interrupts during charging + */ + di->regu = devm_regulator_get(dev, "vddadc"); + if (IS_ERR(di->regu)) { + ret = PTR_ERR(di->regu); + dev_err(dev, "failed to get vddadc regulator\n"); + return ret; + } + + /* Request interrupts */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { + irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, + irq, NULL, ab8500_charger_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_charger_irq[i].name, di); + + if (ret != 0) { + dev_err(dev, "failed to request %s IRQ %d: %d\n" + , ab8500_charger_irq[i].name, irq, ret); + return ret; + } + dev_dbg(dev, "Requested %s IRQ %d: %d\n", + ab8500_charger_irq[i].name, irq, ret); + } + /* initialize lock */ spin_lock_init(&di->usb_state.usb_lock); mutex_init(&di->usb_ipt_crnt_lock); @@ -3422,11 +3498,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->ac_chg.enabled = di->bm->ac_enabled; di->ac_chg.external = false; - /*notifier for external charger enabling*/ - if (!di->ac_chg.enabled) - blocking_notifier_chain_register( - &charger_notifier_list, &charger_nb); - /* USB supply */ /* ux500_charger sub-class */ di->usb_chg.ops.enable = &ab8500_charger_usb_en; @@ -3442,14 +3513,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->usb_chg.external = false; di->usb_state.usb_current = -1; - /* Create a work queue for the charger */ - di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", - WQ_MEM_RECLAIM); - if (di->charger_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - mutex_init(&di->charger_attached_mutex); /* Init work for HW failure check */ @@ -3500,63 +3563,36 @@ static int ab8500_charger_probe(struct platform_device *pdev) INIT_WORK(&di->check_usb_thermal_prot_work, ab8500_charger_check_usb_thermal_prot_work); - /* - * VDD ADC supply needs to be enabled from this driver when there - * is a charger connected to avoid erroneous BTEMP_HIGH/LOW - * interrupts during charging - */ - di->regu = devm_regulator_get(dev, "vddadc"); - if (IS_ERR(di->regu)) { - ret = PTR_ERR(di->regu); - dev_err(dev, "failed to get vddadc regulator\n"); - goto free_charger_wq; - } - /* Initialize OVV, and other registers */ ret = ab8500_charger_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize ABB registers\n"); - goto free_charger_wq; + return ret; } /* Register AC charger class */ if (di->ac_chg.enabled) { - di->ac_chg.psy = power_supply_register(dev, + di->ac_chg.psy = devm_power_supply_register(dev, &ab8500_ac_chg_desc, &ac_psy_cfg); if (IS_ERR(di->ac_chg.psy)) { dev_err(dev, "failed to register AC charger\n"); - ret = PTR_ERR(di->ac_chg.psy); - goto free_charger_wq; + return PTR_ERR(di->ac_chg.psy); } } /* Register USB charger class */ if (di->usb_chg.enabled) { - di->usb_chg.psy = power_supply_register(dev, + di->usb_chg.psy = devm_power_supply_register(dev, &ab8500_usb_chg_desc, &usb_psy_cfg); if (IS_ERR(di->usb_chg.psy)) { dev_err(dev, "failed to register USB charger\n"); - ret = PTR_ERR(di->usb_chg.psy); - goto free_ac; + return PTR_ERR(di->usb_chg.psy); } } - di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(di->usb_phy)) { - dev_err(dev, "failed to get usb transceiver\n"); - ret = -EINVAL; - goto free_usb; - } - di->nb.notifier_call = ab8500_charger_usb_notifier_call; - ret = usb_register_notifier(di->usb_phy, &di->nb); - if (ret) { - dev_err(dev, "failed to register usb notifier\n"); - goto put_usb_phy; - } - /* Identify the connected charger types during startup */ charger_status = ab8500_charger_detect_chargers(di, true); if (charger_status & AC_PW_CONN) { @@ -3566,78 +3602,86 @@ static int ab8500_charger_probe(struct platform_device *pdev) sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); } - if (charger_status & USB_PW_CONN) { - di->vbus_detected = true; - di->vbus_detected_start = true; - queue_work(di->charger_wq, - &di->detect_usb_type_work); - } - - /* Register interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + platform_set_drvdata(pdev, di); - ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_charger_irq[i].name, di); + /* Create something that will match the subdrivers when we bind */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) { + struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver; + struct device *p = NULL, *d; - if (ret != 0) { - dev_err(dev, "failed to request %s IRQ %d: %d\n" - , ab8500_charger_irq[i].name, irq, ret); - goto free_irq; + while ((d = platform_find_device_by_driver(p, drv))) { + put_device(p); + component_match_add(dev, &match, + ab8500_charger_compare_dev, d); + p = d; } - dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_charger_irq[i].name, irq, ret); + put_device(p); + } + if (!match) { + dev_err(dev, "no matching components\n"); + return -ENODEV; + } + if (IS_ERR(match)) { + dev_err(dev, "could not create component match\n"); + return PTR_ERR(match); } - platform_set_drvdata(pdev, di); + /* Notifier for external charger enabling */ + if (!di->ac_chg.enabled) + blocking_notifier_chain_register( + &charger_notifier_list, &charger_nb); - mutex_lock(&di->charger_attached_mutex); - ch_stat = ab8500_charger_detect_chargers(di, false); - - if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->ac_charger_attached_work, - HZ); + di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(di->usb_phy)) { + dev_err(dev, "failed to get usb transceiver\n"); + ret = -EINVAL; + goto out_charger_notifier; } - if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->usb_charger_attached_work, - HZ); + di->nb.notifier_call = ab8500_charger_usb_notifier_call; + ret = usb_register_notifier(di->usb_phy, &di->nb); + if (ret) { + dev_err(dev, "failed to register usb notifier\n"); + goto put_usb_phy; } - mutex_unlock(&di->charger_attached_mutex); - return ret; + ret = component_master_add_with_match(&pdev->dev, + &ab8500_charger_comp_ops, + match); + if (ret) { + dev_err(dev, "failed to add component master\n"); + goto free_notifier; + } -free_irq: - usb_unregister_notifier(di->usb_phy, &di->nb); + return 0; - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } +free_notifier: + usb_unregister_notifier(di->usb_phy, &di->nb); put_usb_phy: usb_put_phy(di->usb_phy); -free_usb: - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); -free_ac: - if (di->ac_chg.enabled) - power_supply_unregister(di->ac_chg.psy); -free_charger_wq: - destroy_workqueue(di->charger_wq); +out_charger_notifier: + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); return ret; } +static int ab8500_charger_remove(struct platform_device *pdev) +{ + struct ab8500_charger *di = platform_get_drvdata(pdev); + + component_master_del(&pdev->dev, &ab8500_charger_comp_ops); + + usb_unregister_notifier(di->usb_phy, &di->nb); + usb_put_phy(di->usb_phy); + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); + + return 0; +} + static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); static const struct of_device_id ab8500_charger_match[] = { @@ -3657,15 +3701,24 @@ static struct platform_driver ab8500_charger_driver = { static int __init ab8500_charger_init(void) { + int ret; + + ret = platform_register_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); + if (ret) + return ret; + return platform_driver_register(&ab8500_charger_driver); } static void __exit ab8500_charger_exit(void) { + platform_unregister_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); platform_driver_unregister(&ab8500_charger_driver); } -subsys_initcall_sync(ab8500_charger_init); +module_init(ab8500_charger_init); module_exit(ab8500_charger_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 0c7c01a0d979..acf0f2471c0b 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/component.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -2980,27 +2981,6 @@ static int __maybe_unused ab8500_fg_suspend(struct device *dev) return 0; } -static int ab8500_fg_remove(struct platform_device *pdev) -{ - int ret = 0; - struct ab8500_fg *di = platform_get_drvdata(pdev); - - list_del(&di->node); - - /* Disable coulomb counter */ - ret = ab8500_fg_coulomb_counter(di, false); - if (ret) - dev_err(di->dev, "failed to disable coulomb counter\n"); - - destroy_workqueue(di->fg_wq); - ab8500_fg_sysfs_exit(di); - - flush_scheduled_work(); - ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); - return ret; -} - /* ab8500 fg driver interrupts and their respective isr */ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, @@ -3024,11 +3004,50 @@ static const struct power_supply_desc ab8500_fg_desc = { .external_power_changed = ab8500_fg_external_power_changed, }; +static int ab8500_fg_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + + /* Create a work queue for running the FG algorithm */ + di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); + if (di->fg_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Start the coulomb counter */ + ab8500_fg_coulomb_counter(di, true); + /* Run the FG algorithm */ + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + return 0; +} + +static void ab8500_fg_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + int ret; + + /* Disable coulomb counter */ + ret = ab8500_fg_coulomb_counter(di, false); + if (ret) + dev_err(dev, "failed to disable coulomb counter\n"); + + destroy_workqueue(di->fg_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_fg_component_ops = { + .bind = ab8500_fg_bind, + .unbind = ab8500_fg_unbind, +}; + static int ab8500_fg_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct power_supply_config psy_cfg = {}; struct device *dev = &pdev->dev; + struct power_supply_config psy_cfg = {}; struct ab8500_fg *di; int i, irq; int ret = 0; @@ -3074,13 +3093,6 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); - /* Create a work queue for running the FG algorithm */ - di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); - if (di->fg_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for running the fg algorithm instantly */ INIT_WORK(&di->fg_work, ab8500_fg_instant_work); @@ -3113,7 +3125,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize registers\n"); - goto free_inst_curr_wq; + return ret; } /* Consider battery unknown until we're informed otherwise */ @@ -3121,15 +3133,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->flags.batt_id_received = false; /* Register FG power supply class */ - di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); + di->fg_psy = devm_power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); if (IS_ERR(di->fg_psy)) { dev_err(dev, "failed to register FG psy\n"); - ret = PTR_ERR(di->fg_psy); - goto free_inst_curr_wq; + return PTR_ERR(di->fg_psy); } di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); - ab8500_fg_coulomb_counter(di, true); /* * Initialize completion used to notify completion and start @@ -3141,19 +3151,18 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Register primary interrupt handlers */ for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_fg_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_fg_irq[i].name, di); if (ret != 0) { dev_err(dev, "failed to request %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); @@ -3168,14 +3177,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_sysfs_init(di); if (ret) { dev_err(dev, "failed to create sysfs entry\n"); - goto free_irq; + return ret; } ret = ab8500_fg_sysfs_psy_create_attrs(di); if (ret) { dev_err(dev, "failed to create FG psy\n"); ab8500_fg_sysfs_exit(di); - goto free_irq; + return ret; } /* Calibrate the fg first time */ @@ -3185,24 +3194,21 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Use room temp as default value until we get an update from driver. */ di->bat_temp = 210; - /* Run the FG algorithm */ - queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); - list_add_tail(&di->node, &ab8500_fg_list); - return ret; + return component_add(dev, &ab8500_fg_component_ops); +} -free_irq: - /* We also have to free all registered irqs */ - while (--i >= 0) { - /* Last assignment of i from primary interrupt handlers */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - free_irq(irq, di); - } +static int ab8500_fg_remove(struct platform_device *pdev) +{ + int ret = 0; + struct ab8500_fg *di = platform_get_drvdata(pdev); + + component_del(&pdev->dev, &ab8500_fg_component_ops); + list_del(&di->node); + ab8500_fg_sysfs_exit(di); + ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); -free_inst_curr_wq: - destroy_workqueue(di->fg_wq); return ret; } @@ -3213,7 +3219,7 @@ static const struct of_device_id ab8500_fg_match[] = { { }, }; -static struct platform_driver ab8500_fg_driver = { +struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, .remove = ab8500_fg_remove, .driver = { @@ -3222,20 +3228,6 @@ static struct platform_driver ab8500_fg_driver = { .pm = &ab8500_fg_pm_ops, }, }; - -static int __init ab8500_fg_init(void) -{ - return platform_driver_register(&ab8500_fg_driver); -} - -static void __exit ab8500_fg_exit(void) -{ - platform_driver_unregister(&ab8500_fg_driver); -} - -subsys_initcall_sync(ab8500_fg_init); -module_exit(ab8500_fg_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); MODULE_ALIAS("platform:ab8500-fg"); diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c index f5b792243727..599684ce0e4b 100644 --- a/drivers/power/supply/abx500_chargalg.c +++ b/drivers/power/supply/abx500_chargalg.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/hrtimer.h> #include <linux/interrupt.h> #include <linux/delay.h> @@ -1943,13 +1944,44 @@ static int __maybe_unused abx500_chargalg_suspend(struct device *dev) return 0; } -static int abx500_chargalg_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_fg", +}; + </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_gnu/gnu-master-aarch64-check_gcc - Build # 2 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *gcc* in CI configuration tcwg_gnu/gnu-master-aarch64-check_gcc. So far, this commit has regressed CI configurations: - tcwg_gnu/gnu-master-aarch64-check_gcc Culprit: <cut> commit 261d5a4a459bd49942e53bc83334ccc7154a09d5 Author: Jonathan Wakely <jwakely(a)redhat.com> Date: Thu Jul 22 14:48:27 2021 +0100 libstdc++: Reduce header dependencies on <array> and <utility> This refactoring reduces the memory usage and compilation time to parse a number of headers that depend on std::pair, std::tuple or std::array. Previously the headers for these class templates were all intertwined, due to the common dependency on std::tuple_size, std::tuple_element and their std::get overloads. This decouples the headers by moving some parts of <utility> into a new <bits/utility.h> header. This means that <array> and <tuple> no longer need to include the whole of <utility>, and <tuple> no longer needs to include <array>. This decoupling benefits headers such as <thread> and <scoped_allocator> which only need std::tuple, and so no longer have to parse std::array. Some other headers such as <any>, <optional> and <variant> no longer need to include <utility> just for the std::in_place tag types, so do not have to parse the std::pair definitions. Removing direct uses of <utility> also means that the std::rel_ops namespace is not transitively declared by other headers. Signed-off-by: Jonathan Wakely <jwakely(a)redhat.com> libstdc++-v3/ChangeLog: * include/Makefile.am: Add bits/utility.h header. * include/Makefile.in: Regenerate. * include/bits/utility.h: New file. * include/std/utility (tuple_size, tuple_element): Move to new header. * include/std/type_traits (__is_tuple_like_impl<tuple<T...>>): Move to <tuple>. (_Index_tuple, _Build_index_tuple, integer_sequence): Likewise. (in_place_t, in_place_index_t, in_place_type_t): Likewise. * include/bits/ranges_util.h: Include new header instead of <utility>. * include/bits/stl_pair.h (tuple_size, tuple_element): Move partial specializations for std::pair here. (get): Move overloads for std::pair here. * include/std/any: Include new header instead of <utility>. * include/std/array: Likewise. * include/std/memory_resource: Likewise. * include/std/optional: Likewise. * include/std/variant: Likewise. * include/std/tuple: Likewise. (__is_tuple_like_impl<tuple<T...>>): Move here. (get) Declare overloads for std::array. * include/std/version (__cpp_lib_tuples_by_type): Change type to long. * testsuite/20_util/optional/84601.cc: Include <utility>. * testsuite/20_util/specialized_algorithms/uninitialized_fill/constrained.cc: Likewise. * testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust dg-error line numbers. * testsuite/std/ranges/access/cbegin.cc: Include <utility>. * testsuite/std/ranges/access/cend.cc: Likewise. * testsuite/std/ranges/access/end.cc: Likewise. * testsuite/std/ranges/single_view.cc: Likewise. </cut> Results regressed to (for first_bad == 261d5a4a459bd49942e53bc83334ccc7154a09d5) # reset_artifacts: -10 # build_abe binutils: -2 # build_abe gcc: -1 # build_abe dejagnu: 0 # build_abe check_gcc -- --set runtestflags=g++.dg/dg.exp: 1 # Getting actual results from build directory /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/libstdc++.sum # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/gfortran.sum # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/libitm.sum # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/libgomp.sum # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/libatomic.sum # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/g++.sum # /home/tcwg-buildslave/workspace/tcwg_gnu_5/artifacts/build-261d5a4a459bd49942e53bc83334ccc7154a09d5/sumfiles/gcc.sum # Manifest: gcc-compare-results/contrib/testsuite-management/flaky/gnu-master-aarch64-check_gcc.xfail # Getting actual results from build directory base-artifacts/sumfiles # base-artifacts/sumfiles/libstdc++.sum # base-artifacts/sumfiles/gfortran.sum # base-artifacts/sumfiles/libitm.sum # base-artifacts/sumfiles/libgomp.sum # base-artifacts/sumfiles/libatomic.sum # base-artifacts/sumfiles/g++.sum # base-artifacts/sumfiles/gcc.sum # # # Unexpected results in this build (new failures) # === g++ tests === # # Running g++.dg/dg.exp ... # FAIL: g++.dg/pr71655.C (test for excess errors) # === gcc tests === # FAIL: g++.dg/pr71655.C (test for excess errors) # # === Results Summary === from (for last_good == fcc7c6369f7fbf293f502d3d207a90b76cc2c62f) # reset_artifacts: -10 # build_abe binutils: -2 # build_abe gcc: -1 # build_abe dejagnu: 0 # build_abe check_gcc -- --set runtestflags=g++.dg/dg.exp: 1 Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/ar…
Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/ar…
Build top page/logs:
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/
Configuration details: Reproduce builds: <cut> mkdir investigate-gcc-261d5a4a459bd49942e53bc83334ccc7154a09d5 cd investigate-gcc-261d5a4a459bd49942e53bc83334ccc7154a09d5 git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/ar…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/ar…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/ar…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_gnu-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/ cd gcc # Reproduce first_bad build git checkout --detach 261d5a4a459bd49942e53bc83334ccc7154a09d5 ../artifacts/test.sh # Reproduce last_good build git checkout --detach fcc7c6369f7fbf293f502d3d207a90b76cc2c62f ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/ar…
Build log:
https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-aarch64-check_gcc/2/co…
Full commit (up to 1000 lines): <cut> commit 261d5a4a459bd49942e53bc83334ccc7154a09d5 Author: Jonathan Wakely <jwakely(a)redhat.com> Date: Thu Jul 22 14:48:27 2021 +0100 libstdc++: Reduce header dependencies on <array> and <utility> This refactoring reduces the memory usage and compilation time to parse a number of headers that depend on std::pair, std::tuple or std::array. Previously the headers for these class templates were all intertwined, due to the common dependency on std::tuple_size, std::tuple_element and their std::get overloads. This decouples the headers by moving some parts of <utility> into a new <bits/utility.h> header. This means that <array> and <tuple> no longer need to include the whole of <utility>, and <tuple> no longer needs to include <array>. This decoupling benefits headers such as <thread> and <scoped_allocator> which only need std::tuple, and so no longer have to parse std::array. Some other headers such as <any>, <optional> and <variant> no longer need to include <utility> just for the std::in_place tag types, so do not have to parse the std::pair definitions. Removing direct uses of <utility> also means that the std::rel_ops namespace is not transitively declared by other headers. Signed-off-by: Jonathan Wakely <jwakely(a)redhat.com> libstdc++-v3/ChangeLog: * include/Makefile.am: Add bits/utility.h header. * include/Makefile.in: Regenerate. * include/bits/utility.h: New file. * include/std/utility (tuple_size, tuple_element): Move to new header. * include/std/type_traits (__is_tuple_like_impl<tuple<T...>>): Move to <tuple>. (_Index_tuple, _Build_index_tuple, integer_sequence): Likewise. (in_place_t, in_place_index_t, in_place_type_t): Likewise. * include/bits/ranges_util.h: Include new header instead of <utility>. * include/bits/stl_pair.h (tuple_size, tuple_element): Move partial specializations for std::pair here. (get): Move overloads for std::pair here. * include/std/any: Include new header instead of <utility>. * include/std/array: Likewise. * include/std/memory_resource: Likewise. * include/std/optional: Likewise. * include/std/variant: Likewise. * include/std/tuple: Likewise. (__is_tuple_like_impl<tuple<T...>>): Move here. (get) Declare overloads for std::array. * include/std/version (__cpp_lib_tuples_by_type): Change type to long. * testsuite/20_util/optional/84601.cc: Include <utility>. * testsuite/20_util/specialized_algorithms/uninitialized_fill/constrained.cc: Likewise. * testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust dg-error line numbers. * testsuite/std/ranges/access/cbegin.cc: Include <utility>. * testsuite/std/ranges/access/cend.cc: Likewise. * testsuite/std/ranges/access/end.cc: Likewise. * testsuite/std/ranges/single_view.cc: Likewise. --- libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/bits/ranges_util.h | 1 + libstdc++-v3/include/bits/stl_pair.h | 155 ++++++++++- libstdc++-v3/include/bits/utility.h | 205 ++++++++++++++ libstdc++-v3/include/std/any | 3 +- libstdc++-v3/include/std/array | 30 +- libstdc++-v3/include/std/memory_resource | 6 +- libstdc++-v3/include/std/optional | 4 +- libstdc++-v3/include/std/tuple | 36 ++- libstdc++-v3/include/std/type_traits | 7 - libstdc++-v3/include/std/utility | 308 +-------------------- libstdc++-v3/include/std/variant | 6 +- libstdc++-v3/include/std/version | 2 +- libstdc++-v3/testsuite/20_util/optional/84601.cc | 1 + .../uninitialized_fill/constrained.cc | 1 + .../23_containers/array/tuple_interface/get_neg.cc | 6 +- libstdc++-v3/testsuite/std/ranges/access/cbegin.cc | 1 + libstdc++-v3/testsuite/std/ranges/access/cend.cc | 1 + libstdc++-v3/testsuite/std/ranges/access/end.cc | 1 + libstdc++-v3/testsuite/std/ranges/single_view.cc | 1 + 21 files changed, 433 insertions(+), 344 deletions(-) diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 40a41ef2a1c..99eec558116 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -233,6 +233,7 @@ bits_headers = \ ${bits_srcdir}/unordered_set.h \ ${bits_srcdir}/uses_allocator.h \ ${bits_srcdir}/uses_allocator_args.h \ + ${bits_srcdir}/utility.h \ ${bits_srcdir}/valarray_array.h \ ${bits_srcdir}/valarray_array.tcc \ ${bits_srcdir}/valarray_before.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index fcd2b5b2d40..7e668b86bbb 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -583,6 +583,7 @@ bits_headers = \ ${bits_srcdir}/unordered_set.h \ ${bits_srcdir}/uses_allocator.h \ ${bits_srcdir}/uses_allocator_args.h \ + ${bits_srcdir}/utility.h \ ${bits_srcdir}/valarray_array.h \ ${bits_srcdir}/valarray_array.tcc \ ${bits_srcdir}/valarray_before.h \ diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 9a07079ac13..0ca203dd4b0 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -32,6 +32,7 @@ #if __cplusplus > 201703L # include <bits/ranges_base.h> +# include <bits/utility.h> #ifdef __cpp_lib_ranges namespace std _GLIBCXX_VISIBILITY(default) diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index c89f377fddc..329485ce3b2 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -56,12 +56,12 @@ #ifndef _STL_PAIR_H #define _STL_PAIR_H 1 -#include <bits/move.h> // for std::move / std::forward, and std::swap - #if __cplusplus >= 201103L -# include <type_traits> // for std::__decay_and_strip, std::is_reference_v +# include <type_traits> // for std::__decay_and_strip +# include <bits/move.h> // for std::move / std::forward, and std::swap +# include <bits/utility.h> // for std::tuple_element, std::tuple_size #endif -#if __cplusplus > 201703L +#if __cplusplus >= 202002L # include <compare> # define __cpp_lib_constexpr_utility 201811L #endif @@ -752,6 +752,153 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @} +#if __cplusplus >= 201103L + // Various functions which give std::pair a tuple-like interface. + + template<typename _T1, typename _T2> + struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type + { }; + + /// Partial specialization for std::pair + template<class _Tp1, class _Tp2> + struct tuple_size<pair<_Tp1, _Tp2>> + : public integral_constant<size_t, 2> { }; + + /// Partial specialization for std::pair + template<class _Tp1, class _Tp2> + struct tuple_element<0, pair<_Tp1, _Tp2>> + { typedef _Tp1 type; }; + + /// Partial specialization for std::pair + template<class _Tp1, class _Tp2> + struct tuple_element<1, pair<_Tp1, _Tp2>> + { typedef _Tp2 type; }; + + /// @cond undocumented + template<size_t _Int> + struct __pair_get; + + template<> + struct __pair_get<0> + { + template<typename _Tp1, typename _Tp2> + static constexpr _Tp1& + __get(pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template<typename _Tp1, typename _Tp2> + static constexpr _Tp1&& + __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp1>(__pair.first); } + + template<typename _Tp1, typename _Tp2> + static constexpr const _Tp1& + __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template<typename _Tp1, typename _Tp2> + static constexpr const _Tp1&& + __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<const _Tp1>(__pair.first); } + }; + + template<> + struct __pair_get<1> + { + template<typename _Tp1, typename _Tp2> + static constexpr _Tp2& + __get(pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template<typename _Tp1, typename _Tp2> + static constexpr _Tp2&& + __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp2>(__pair.second); } + + template<typename _Tp1, typename _Tp2> + static constexpr const _Tp2& + __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template<typename _Tp1, typename _Tp2> + static constexpr const _Tp2&& + __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<const _Tp2>(__pair.second); } + }; + /// @endcond + + /** @{ + * std::get overloads for accessing members of std::pair + */ + + template<size_t _Int, class _Tp1, class _Tp2> + constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& + get(pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__get(__in); } + + template<size_t _Int, class _Tp1, class _Tp2> + constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& + get(pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__move_get(std::move(__in)); } + + template<size_t _Int, class _Tp1, class _Tp2> + constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& + get(const pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__const_get(__in); } + + template<size_t _Int, class _Tp1, class _Tp2> + constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& + get(const pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__const_move_get(std::move(__in)); } + +#if __cplusplus >= 201402L + +#define __cpp_lib_tuples_by_type 201304L + + template <typename _Tp, typename _Up> + constexpr _Tp& + get(pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template <typename _Tp, typename _Up> + constexpr const _Tp& + get(const pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template <typename _Tp, typename _Up> + constexpr _Tp&& + get(pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template <typename _Tp, typename _Up> + constexpr const _Tp&& + get(const pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template <typename _Tp, typename _Up> + constexpr _Tp& + get(pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template <typename _Tp, typename _Up> + constexpr const _Tp& + get(const pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template <typename _Tp, typename _Up> + constexpr _Tp&& + get(pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + + template <typename _Tp, typename _Up> + constexpr const _Tp&& + get(const pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + +#endif // C++14 + /// @} +#endif // C++11 + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h new file mode 100644 index 00000000000..96d350874d9 --- /dev/null +++ b/libstdc++-v3/include/bits/utility.h @@ -0,0 +1,205 @@ +// Utilities used throughout the library -*- C++ -*- + +// Copyright (C) 2004-2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <
http://www.gnu.org/licenses/
>. + +/** @file include/bits/utility.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + * + * This file contains the parts of `<utility>` needed by other headers, + * so they don't need to include the whole of `<utility>`. + */ + +#ifndef _GLIBCXX_UTILITY_H +#define _GLIBCXX_UTILITY_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L + +#include <type_traits> +#include <bits/move.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Finds the size of a given tuple type. + template<typename _Tp> + struct tuple_size; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2313. tuple_size should always derive from integral_constant<size_t, N> + // 2770. tuple_size<const T> specialization is not SFINAE compatible + + template<typename _Tp, + typename _Up = typename remove_cv<_Tp>::type, + typename = typename enable_if<is_same<_Tp, _Up>::value>::type, + size_t = tuple_size<_Tp>::value> + using __enable_if_has_tuple_size = _Tp; + + template<typename _Tp> + struct tuple_size<const __enable_if_has_tuple_size<_Tp>> + : public tuple_size<_Tp> { }; + + template<typename _Tp> + struct tuple_size<volatile __enable_if_has_tuple_size<_Tp>> + : public tuple_size<_Tp> { }; + + template<typename _Tp> + struct tuple_size<const volatile __enable_if_has_tuple_size<_Tp>> + : public tuple_size<_Tp> { }; + + /// Gives the type of the ith element of a given tuple type. + template<size_t __i, typename _Tp> + struct tuple_element; + + // Duplicate of C++14's tuple_element_t for internal use in C++11 mode + template<size_t __i, typename _Tp> + using __tuple_element_t = typename tuple_element<__i, _Tp>::type; + + template<size_t __i, typename _Tp> + struct tuple_element<__i, const _Tp> + { + typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; + }; + + template<size_t __i, typename _Tp> + struct tuple_element<__i, volatile _Tp> + { + typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; + }; + + template<size_t __i, typename _Tp> + struct tuple_element<__i, const volatile _Tp> + { + typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; + }; + +#if __cplusplus >= 201402L +// The standard says this macro and alias template should be in <tuple> +// but we define them here, to be available in <utility> and <array> too. +#define __cpp_lib_tuple_element_t 201402L + + template<size_t __i, typename _Tp> + using tuple_element_t = typename tuple_element<__i, _Tp>::type; +#endif // C++14 + + // Stores a tuple of indices. Used by tuple and pair, and by bind() to + // extract the elements in a tuple. + template<size_t... _Indexes> struct _Index_tuple { }; + + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template<size_t _Num> + struct _Build_index_tuple + { +#if __has_builtin(__make_integer_seq) + template<typename, size_t... _Indices> + using _IdxTuple = _Index_tuple<_Indices...>; + + // Clang defines __make_integer_seq for this purpose. + using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; +#else + // For GCC and other compilers, use __integer_pack instead. + using __type = _Index_tuple<__integer_pack(_Num)...>; +#endif + }; + +#if __cplusplus >= 201402L + +#define __cpp_lib_integer_sequence 201304L + + /// Class template integer_sequence + template<typename _Tp, _Tp... _Idx> + struct integer_sequence + { + typedef _Tp value_type; + static constexpr size_t size() noexcept { return sizeof...(_Idx); } + }; + + /// Alias template make_integer_sequence + template<typename _Tp, _Tp _Num> + using make_integer_sequence +#if __has_builtin(__make_integer_seq) + = __make_integer_seq<integer_sequence, _Tp, _Num>; +#else + = integer_sequence<_Tp, __integer_pack(_Num)...>; +#endif + + /// Alias template index_sequence + template<size_t... _Idx> + using index_sequence = integer_sequence<size_t, _Idx...>; + + /// Alias template make_index_sequence + template<size_t _Num> + using make_index_sequence = make_integer_sequence<size_t, _Num>; + + /// Alias template index_sequence_for + template<typename... _Types> + using index_sequence_for = make_index_sequence<sizeof...(_Types)>; + +#if __cplusplus >= 201703L + + // + struct in_place_t { + explicit in_place_t() = default; + }; + + inline constexpr in_place_t in_place{}; + + template<typename _Tp> struct in_place_type_t + { + explicit in_place_type_t() = default; + }; + + template<typename _Tp> + inline constexpr in_place_type_t<_Tp> in_place_type{}; + + template<size_t _Idx> struct in_place_index_t + { + explicit in_place_index_t() = default; + }; + + template<size_t _Idx> + inline constexpr in_place_index_t<_Idx> in_place_index{}; + + template<typename> + struct __is_in_place_type_impl : false_type + { }; + + template<typename _Tp> + struct __is_in_place_type_impl<in_place_type_t<_Tp>> : true_type + { }; + + template<typename _Tp> + struct __is_in_place_type + : public __is_in_place_type_impl<_Tp> + { }; +#endif // C++17 +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 +#endif /* _GLIBCXX_UTILITY_H */ diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index a6995b79c43..1fce95730ea 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -33,10 +33,11 @@ #if __cplusplus >= 201703L +#include <initializer_list> #include <typeinfo> #include <new> -#include <utility> #include <type_traits> +#include <bits/utility.h> // in_place_type_t namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 0c6f33e3276..ea8d3cb5f2e 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -35,10 +35,14 @@ # include <bits/c++0x_warning.h> #else -#include <utility> +#include <compare> +#include <initializer_list> + +#include <type_traits> #include <bits/functexcept.h> #include <bits/stl_algobase.h> -#include <bits/range_access.h> +#include <bits/range_access.h> // std::begin, std::end etc. +#include <bits/utility.h> // std::index_sequence, std::tuple_size #include <debug/assertions.h> namespace std _GLIBCXX_VISIBILITY(default) @@ -428,28 +432,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Tuple interface to class template array. - /// tuple_size - template<typename _Tp> - struct tuple_size; - /// Partial specialization for std::array - template<typename _Tp, std::size_t _Nm> + template<typename _Tp, size_t _Nm> struct tuple_size<array<_Tp, _Nm>> - : public integral_constant<std::size_t, _Nm> { }; - - /// tuple_element - template<std::size_t _Int, typename _Tp> - struct tuple_element; + : public integral_constant<size_t, _Nm> { }; /// Partial specialization for std::array - template<std::size_t _Int, typename _Tp, std::size_t _Nm> - struct tuple_element<_Int, array<_Tp, _Nm>> + template<size_t _Ind, typename _Tp, size_t _Nm> + struct tuple_element<_Ind, array<_Tp, _Nm>> { - static_assert(_Int < _Nm, "index is out of bounds"); - typedef _Tp type; + static_assert(_Ind < _Nm, "array index is in range"); + using type = _Tp; }; - template<typename _Tp, std::size_t _Nm> + template<typename _Tp, size_t _Nm> struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type { }; diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource index df4e806f814..cdc5e5d98b1 100644 --- a/libstdc++-v3/include/std/memory_resource +++ b/libstdc++-v3/include/std/memory_resource @@ -38,13 +38,13 @@ #include <shared_mutex> // shared_mutex #include <bits/align.h> // align #include <bits/functexcept.h> // __throw_bad_array_new_length -#include <bits/uses_allocator.h> // __use_alloc +#include <bits/uses_allocator.h> // allocator_arg_t, __use_alloc #include <bits/uses_allocator_args.h> // uninitialized_construct_using_alloc #include <ext/numeric_traits.h> #include <debug/assertions.h> #if ! __cpp_lib_make_obj_using_allocator -# include <utility> // pair, index_sequence +# include <bits/utility.h> // index_sequence # include <tuple> // tuple, forward_as_tuple #endif @@ -338,10 +338,10 @@ namespace pmr { return _M_resource; } private: +#if ! __cpp_lib_make_obj_using_allocator using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>; using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>; -#if ! __cpp_lib_make_obj_using_allocator template<typename _Ind, typename... _Args> static tuple<_Args&&...> _S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 0a67ce24bbd..df9ed0736b3 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -33,14 +33,14 @@ #if __cplusplus >= 201703L -#include <utility> #include <type_traits> #include <exception> #include <new> #include <initializer_list> +#include <bits/enable_special_members.h> #include <bits/exception_defines.h> #include <bits/functional_hash.h> -#include <bits/enable_special_members.h> +#include <bits/utility.h> // in_place_t #if __cplusplus > 201703L # include <compare> #endif diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 8ee0d2f1ef5..1292aee45c0 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -35,10 +35,10 @@ # include <bits/c++0x_warning.h> #else -#include <utility> -#include <array> -#include <bits/uses_allocator.h> -#include <bits/invoke.h> +#include <bits/stl_pair.h> // for std::pair +#include <bits/uses_allocator.h> // for std::allocator_arg_t +#include <bits/utility.h> // for std::get, std::tuple_size etc. +#include <bits/invoke.h> // for std::__invoke #if __cplusplus > 201703L # include <compare> # define __cpp_lib_constexpr_tuple 201811L @@ -1415,7 +1415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201402L -#define __cpp_lib_tuples_by_type 201304 +#define __cpp_lib_tuples_by_type 201304L // Return the index of _Tp in _Types, if it occurs exactly once. // Otherwise, return sizeof...(_Types). @@ -1613,6 +1613,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION forward_as_tuple(_Elements&&... __args) noexcept { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } + // Declarations of std::array and its std::get overloads, so that + // std::tuple_cat can use them if <tuple> is included before <array>. + + template<typename _Tp, size_t _Nm> struct array; + + template<size_t _Int, typename _Tp, size_t _Nm> + constexpr _Tp& + get(array<_Tp, _Nm>&) noexcept; + + template<size_t _Int, typename _Tp, size_t _Nm> + constexpr _Tp&& + get(array<_Tp, _Nm>&&) noexcept; + + template<size_t _Int, typename _Tp, size_t _Nm> + constexpr const _Tp& + get(const array<_Tp, _Nm>&) noexcept; + + template<size_t _Int, typename _Tp, size_t _Nm> + constexpr const _Tp&& + get(const array<_Tp, _Nm>&&) noexcept; + + template<size_t, typename, typename, size_t> struct __make_tuple_impl; @@ -1721,6 +1743,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + template<typename... _Tps> + struct __is_tuple_like_impl<tuple<_Tps...>> : true_type + { }; + /// tuple_cat template<typename... _Tpls, typename = typename enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 15ec83a06b8..0d821f9c074 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -41,9 +41,6 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION - template<typename... _Elements> - class tuple; - template<typename _Tp> class reference_wrapper; @@ -2680,10 +2677,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __is_tuple_like_impl : false_type { }; - template<typename... _Tps> - struct __is_tuple_like_impl<tuple<_Tps...>> : true_type - { }; - // Internal type trait that allows us to sfinae-protect tuple_cat. template<typename _Tp> struct __is_tuple_like diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 3e68f682e00..c2697f87dc5 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -60,9 +60,8 @@ /** * @defgroup utilities Utilities * - * Components deemed generally useful. Includes pair, tuple, - * forward/move helpers, ratio, function object, metaprogramming and - * type traits, time, date, and memory functions. + * Basic function and class templates used with the rest of the library. + * Includes pair, swap, forward/move helpers, declval, integer_sequence. */ #include <bits/c++config.h> @@ -71,218 +70,21 @@ #if __cplusplus >= 201103L +#include <initializer_list> #include <type_traits> #include <bits/move.h> -#include <initializer_list> +#include <bits/utility.h> -#if __cplusplus > 201703L -#include <ext/numeric_traits.h> +#if __cplusplus >= 202002L +#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits #endif namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION - /// Finds the size of a given tuple type. - template<typename _Tp> - struct tuple_size; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2313. tuple_size should always derive from integral_constant<size_t, N> - // 2770. tuple_size<const T> specialization is not SFINAE compatible - - template<typename _Tp, - typename _Up = typename remove_cv<_Tp>::type, - typename = typename enable_if<is_same<_Tp, _Up>::value>::type, - size_t = tuple_size<_Tp>::value> - using __enable_if_has_tuple_size = _Tp; - - template<typename _Tp> - struct tuple_size<const __enable_if_has_tuple_size<_Tp>> - : public tuple_size<_Tp> { }; - - template<typename _Tp> - struct tuple_size<volatile __enable_if_has_tuple_size<_Tp>> - : public tuple_size<_Tp> { }; - - template<typename _Tp> - struct tuple_size<const volatile __enable_if_has_tuple_size<_Tp>> - : public tuple_size<_Tp> { }; - - /// Gives the type of the ith element of a given tuple type. - template<size_t __i, typename _Tp> - struct tuple_element; - - // Duplicate of C++14's tuple_element_t for internal use in C++11 mode - template<size_t __i, typename _Tp> - using __tuple_element_t = typename tuple_element<__i, _Tp>::type; - - template<size_t __i, typename _Tp> - struct tuple_element<__i, const _Tp> - { - typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; - }; - - template<size_t __i, typename _Tp> - struct tuple_element<__i, volatile _Tp> - { - typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; - }; - - template<size_t __i, typename _Tp> - struct tuple_element<__i, const volatile _Tp> - { - typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; - }; - -#if __cplusplus >= 201402L -// The standard says this macro and alias template should be in <tuple> -// but we define them here, to be available when the partial specializations -// of tuple_element<pair<T,U>> and tuple_element<array<T,N>> are defined. -#define __cpp_lib_tuple_element_t 201402L - - template<size_t __i, typename _Tp> - using tuple_element_t = typename tuple_element<__i, _Tp>::type; -#endif - - // Various functions which give std::pair a tuple-like interface. - - /// Partial specialization for std::pair - template<typename _T1, typename _T2> - struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type - { }; - - /// Partial specialization for std::pair - template<class _Tp1, class _Tp2> - struct tuple_size<pair<_Tp1, _Tp2>> - : public integral_constant<size_t, 2> { }; - - /// Partial specialization for std::pair - template<class _Tp1, class _Tp2> - struct tuple_element<0, pair<_Tp1, _Tp2>> - { typedef _Tp1 type; }; - - /// Partial specialization for std::pair - template<class _Tp1, class _Tp2> - struct tuple_element<1, pair<_Tp1, _Tp2>> - { typedef _Tp2 type; }; - - template<size_t _Int> - struct __pair_get; - - template<> - struct __pair_get<0> - { - template<typename _Tp1, typename _Tp2> - static constexpr _Tp1& - __get(pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.first; } - - template<typename _Tp1, typename _Tp2> - static constexpr _Tp1&& - __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward<_Tp1>(__pair.first); } - - template<typename _Tp1, typename _Tp2> - static constexpr const _Tp1& - __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.first; } - - template<typename _Tp1, typename _Tp2> - static constexpr const _Tp1&& - __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward<const _Tp1>(__pair.first); } - }; - - template<> - struct __pair_get<1> - { - template<typename _Tp1, typename _Tp2> - static constexpr _Tp2& - __get(pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.second; } - - template<typename _Tp1, typename _Tp2> - static constexpr _Tp2&& - __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward<_Tp2>(__pair.second); } - - template<typename _Tp1, typename _Tp2> - static constexpr const _Tp2& - __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.second; } - - template<typename _Tp1, typename _Tp2> - static constexpr const _Tp2&& - __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward<const _Tp2>(__pair.second); } - }; - - template<size_t _Int, class _Tp1, class _Tp2> - constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& - get(pair<_Tp1, _Tp2>& __in) noexcept - { return __pair_get<_Int>::__get(__in); } - - template<size_t _Int, class _Tp1, class _Tp2> - constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& - get(pair<_Tp1, _Tp2>&& __in) noexcept - { return __pair_get<_Int>::__move_get(std::move(__in)); } - - template<size_t _Int, class _Tp1, class _Tp2> - constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& - get(const pair<_Tp1, _Tp2>& __in) noexcept - { return __pair_get<_Int>::__const_get(__in); } - - template<size_t _Int, class _Tp1, class _Tp2> - constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& - get(const pair<_Tp1, _Tp2>&& __in) noexcept - { return __pair_get<_Int>::__const_move_get(std::move(__in)); } - #if __cplusplus >= 201402L - -#define __cpp_lib_tuples_by_type 201304 - - template <typename _Tp, typename _Up> - constexpr _Tp& - get(pair<_Tp, _Up>& __p) noexcept - { return __p.first; } - - template <typename _Tp, typename _Up> - constexpr const _Tp& - get(const pair<_Tp, _Up>& __p) noexcept - { return __p.first; } - - template <typename _Tp, typename _Up> - constexpr _Tp&& - get(pair<_Tp, _Up>&& __p) noexcept - { return std::move(__p.first); } - - template <typename _Tp, typename _Up> - constexpr const _Tp&& - get(const pair<_Tp, _Up>&& __p) noexcept - { return std::move(__p.first); } - - template <typename _Tp, typename _Up> - constexpr _Tp& - get(pair<_Up, _Tp>& __p) noexcept - { return __p.second; } - - template <typename _Tp, typename _Up> - constexpr const _Tp& - get(const pair<_Up, _Tp>& __p) noexcept - { return __p.second; } - - template <typename _Tp, typename _Up> - constexpr _Tp&& - get(pair<_Up, _Tp>&& __p) noexcept - { return std::move(__p.second); } - - template <typename _Tp, typename _Up> - constexpr const _Tp&& - get(const pair<_Up, _Tp>&& __p) noexcept - { return std::move(__p.second); } - -#define __cpp_lib_exchange_function 201304 +#define __cpp_lib_exchange_function 201304L /// Assign @p __new_val to @p __obj and return its previous value. template <typename _Tp, typename _Up = _Tp> @@ -291,100 +93,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION exchange(_Tp& __obj, _Up&& __new_val) { return std::__exchange(__obj, std::forward<_Up>(__new_val)); } -#endif // C++14 - - // Stores a tuple of indices. Used by tuple and pair, and by bind() to - // extract the elements in a tuple. - template<size_t... _Indexes> struct _Index_tuple { }; - - // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. - template<size_t _Num> - struct _Build_index_tuple - { -#if __has_builtin(__make_integer_seq) - template<typename, size_t... _Indices> - using _IdxTuple = _Index_tuple<_Indices...>; - - // Clang defines __make_integer_seq for this purpose. - using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; -#else - // For GCC and other compilers, use __integer_pack instead. - using __type = _Index_tuple<__integer_pack(_Num)...>; -#endif - }; - -#if __cplusplus >= 201402L - -#define __cpp_lib_integer_sequence 201304 - - /// Class template integer_sequence - template<typename _Tp, _Tp... _Idx> </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_bmk_tx1/llvm-master-aarch64-spec2k6-O3 - Build # 12 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *llvm* in CI configuration tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3. So far, this commit has regressed CI configurations: - tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3 Culprit: <cut> commit 0fb299072c5b26396ab84002445570f296be44b3 Author: Jez Ng <jezng(a)fb.com> Date: Sun Jul 11 21:34:31 2021 -0400 [lld-macho][nfc] Fix YAML input in compact-unwind-sym-relocs.s * Adjust strsize so llvm-objdump doesn't complain about it extending past the end of file * Remove symbol that was referencing a deleted section * Adjust n_sect of the remaining `_main` symbol to point at the right section </cut> Results regressed to (for first_bad == 0fb299072c5b26396ab84002445570f296be44b3) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer: -5 # build_llvm true: -3 # true: 0 # benchmark -- -O3 artifacts/build-0fb299072c5b26396ab84002445570f296be44b3/results_id: 1 # 433.milc,milc_base.default regressed by 105 # 433.milc,[.] mult_su3_mat_vec regressed by 132 from (for last_good == a7b7b5dfe5a931a76cbe8410e5a9f55beea73c8e) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer: -5 # build_llvm true: -3 # true: 0 # benchmark -- -O3 artifacts/build-a7b7b5dfe5a931a76cbe8410e5a9f55beea73c8e/results_id: 1 Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of last_good: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3/2801 Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of first_bad: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3/2794 Build top page/logs:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Configuration details: Reproduce builds: <cut> mkdir investigate-llvm-0fb299072c5b26396ab84002445570f296be44b3 cd investigate-llvm-0fb299072c5b26396ab84002445570f296be44b3 git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /llvm/ ./ ./bisect/baseline/ cd llvm # Reproduce first_bad build git checkout --detach 0fb299072c5b26396ab84002445570f296be44b3 ../artifacts/test.sh # Reproduce last_good build git checkout --detach a7b7b5dfe5a931a76cbe8410e5a9f55beea73c8e ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Build log:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Full commit (up to 1000 lines): <cut> commit 0fb299072c5b26396ab84002445570f296be44b3 Author: Jez Ng <jezng(a)fb.com> Date: Sun Jul 11 21:34:31 2021 -0400 [lld-macho][nfc] Fix YAML input in compact-unwind-sym-relocs.s * Adjust strsize so llvm-objdump doesn't complain about it extending past the end of file * Remove symbol that was referencing a deleted section * Adjust n_sect of the remaining `_main` symbol to point at the right section --- lld/test/MachO/compact-unwind-sym-relocs.s | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lld/test/MachO/compact-unwind-sym-relocs.s b/lld/test/MachO/compact-unwind-sym-relocs.s index e87c3330841a..ff0896fd0daf 100644 --- a/lld/test/MachO/compact-unwind-sym-relocs.s +++ b/lld/test/MachO/compact-unwind-sym-relocs.s @@ -76,7 +76,7 @@ LoadCommands: content: '0000000000000000010000000000020200000000000000000000000000000000' relocations: - address: 0x00000000 - symbolnum: 1 + symbolnum: 0 pcrel: false length: 3 extern: true @@ -86,16 +86,11 @@ LoadCommands: - cmd: LC_SYMTAB cmdsize: 24 symoff: 520 - nsyms: 2 + nsyms: 1 stroff: 552 - strsize: 24 + strsize: 8 LinkEditData: NameList: - - n_strx: 8 - n_type: 0x0E - n_sect: 2 - n_desc: 0 - n_value: 8 - n_strx: 2 n_type: 0x0F n_sect: 1 </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_kernel/llvm-master-arm-stable-allyesconfig - Build # 9 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *linux* in CI configuration tcwg_kernel/llvm-master-arm-stable-allyesconfig. So far, this commit has regressed CI configurations: - tcwg_kernel/llvm-master-arm-stable-allyesconfig Culprit: <cut> commit 341db343768bc44f3512facc464021730d64071c Author: Linus Walleij <linus.walleij(a)linaro.org> Date: Sun May 23 00:50:39 2021 +0200 power: supply: ab8500: Move to componentized binding [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ] The driver has problems with the different components of the charging code racing with each other to probe(). This results in all four subdrivers populating battery information to ascertain that it is populated for their own needs for example. Fix this by using component probing and thus expressing to the kernel that these are dependent components. The probes can happen in any order and will only acquire resources such as state container, regulators and interrupts and initialize the data structures, but no execution happens until the .bind() callback is called. The charging driver is the main component and binds first, then bind in order the three subcomponents: ab8500-fg, ab8500-btemp and ab8500-chargalg. Do some housekeeping while we are moving the code around. Like use devm_* for IRQs so as to cut down on some boilerplate. Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel(a)collabora.com> Signed-off-by: Sasha Levin <sashal(a)kernel.org> </cut> Results regressed to (for first_bad == 341db343768bc44f3512facc464021730d64071c) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 19634 # First few build errors in logs: # 00:03:00 drivers/power/supply/ab8500_fg.c:3061:32: error: use of undeclared identifier 'np' # 00:03:00 make[3]: *** [scripts/Makefile.build:273: drivers/power/supply/ab8500_fg.o] Error 1 # 00:03:05 make[2]: *** [scripts/Makefile.build:516: drivers/power/supply] Error 2 # 00:03:05 make[1]: *** [scripts/Makefile.build:516: drivers/power] Error 2 # 00:03:54 make: *** [Makefile:1847: drivers] Error 2 from (for last_good == dc72a15859b2e604abb8a4bff123fbac8a0be92a) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 19722 # linux build successful: all Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
Build top page/logs:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
Configuration details: Reproduce builds: <cut> mkdir investigate-linux-341db343768bc44f3512facc464021730d64071c cd investigate-linux-341db343768bc44f3512facc464021730d64071c git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /linux/ ./ ./bisect/baseline/ cd linux # Reproduce first_bad build git checkout --detach 341db343768bc44f3512facc464021730d64071c ../artifacts/test.sh # Reproduce last_good build git checkout --detach dc72a15859b2e604abb8a4bff123fbac8a0be92a ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
Build log:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-arm-stable-al…
Full commit (up to 1000 lines): <cut> commit 341db343768bc44f3512facc464021730d64071c Author: Linus Walleij <linus.walleij(a)linaro.org> Date: Sun May 23 00:50:39 2021 +0200 power: supply: ab8500: Move to componentized binding [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ] The driver has problems with the different components of the charging code racing with each other to probe(). This results in all four subdrivers populating battery information to ascertain that it is populated for their own needs for example. Fix this by using component probing and thus expressing to the kernel that these are dependent components. The probes can happen in any order and will only acquire resources such as state container, regulators and interrupts and initialize the data structures, but no execution happens until the .bind() callback is called. The charging driver is the main component and binds first, then bind in order the three subcomponents: ab8500-fg, ab8500-btemp and ab8500-chargalg. Do some housekeeping while we are moving the code around. Like use devm_* for IRQs so as to cut down on some boilerplate. Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel(a)collabora.com> Signed-off-by: Sasha Levin <sashal(a)kernel.org> --- drivers/power/supply/ab8500-bm.h | 4 + drivers/power/supply/ab8500_btemp.c | 118 +++++------- drivers/power/supply/ab8500_charger.c | 339 +++++++++++++++++++-------------- drivers/power/supply/ab8500_fg.c | 136 +++++++------ drivers/power/supply/abx500_chargalg.c | 116 ++++++----- 5 files changed, 379 insertions(+), 334 deletions(-) diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h index 41c69a4f2a1f..012595a9d269 100644 --- a/drivers/power/supply/ab8500-bm.h +++ b/drivers/power/supply/ab8500-bm.h @@ -730,4 +730,8 @@ int ab8500_bm_of_probe(struct device *dev, struct device_node *np, struct abx500_bm_data *bm); +extern struct platform_driver ab8500_fg_driver; +extern struct platform_driver ab8500_btemp_driver; +extern struct platform_driver abx500_chargalg_driver; + #endif /* _AB8500_CHARGER_H_ */ diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index fdfcd59fc43e..3598b5a748e7 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> @@ -932,26 +933,6 @@ static int __maybe_unused ab8500_btemp_suspend(struct device *dev) return 0; } -static int ab8500_btemp_remove(struct platform_device *pdev) -{ - struct ab8500_btemp *di = platform_get_drvdata(pdev); - int i, irq; - - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } - - /* Delete the work queue */ - destroy_workqueue(di->btemp_wq); - - flush_scheduled_work(); - power_supply_unregister(di->btemp_psy); - - return 0; -} - static char *supply_interface[] = { "ab8500_chargalg", "ab8500_fg", @@ -966,6 +947,40 @@ static const struct power_supply_desc ab8500_btemp_desc = { .external_power_changed = ab8500_btemp_external_power_changed, }; +static int ab8500_btemp_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Create a work queue for the btemp */ + di->btemp_wq = + alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); + if (di->btemp_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Kick off periodic temperature measurements */ + ab8500_btemp_periodic(di, true); + + return 0; +} + +static void ab8500_btemp_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Delete the work queue */ + destroy_workqueue(di->btemp_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_btemp_component_ops = { + .bind = ab8500_btemp_bind, + .unbind = ab8500_btemp_unbind, +}; + static int ab8500_btemp_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1011,14 +1026,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); psy_cfg.drv_data = di; - /* Create a work queue for the btemp */ - di->btemp_wq = - alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); - if (di->btemp_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for measuring temperature periodically */ INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, ab8500_btemp_periodic_work); @@ -1031,7 +1038,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) AB8500_BTEMP_HIGH_TH, &val); if (ret < 0) { dev_err(dev, "%s ab8500 read failed\n", __func__); - goto free_btemp_wq; + return ret; } switch (val) { case BTEMP_HIGH_TH_57_0: @@ -1050,30 +1057,28 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } /* Register BTEMP power supply class */ - di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc, - &psy_cfg); + di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc, + &psy_cfg); if (IS_ERR(di->btemp_psy)) { dev_err(dev, "failed to register BTEMP psy\n"); - ret = PTR_ERR(di->btemp_psy); - goto free_btemp_wq; + return PTR_ERR(di->btemp_psy); } /* Register interrupts */ for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_btemp_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_btemp_irq[i].name, di); if (ret) { dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_btemp_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_btemp_irq[i].name, irq, ret); @@ -1081,23 +1086,16 @@ static int ab8500_btemp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, di); - /* Kick off periodic temperature measurements */ - ab8500_btemp_periodic(di, true); list_add_tail(&di->node, &ab8500_btemp_list); - return ret; + return component_add(dev, &ab8500_btemp_component_ops); +} -free_irq: - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } +static int ab8500_btemp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &ab8500_btemp_component_ops); - power_supply_unregister(di->btemp_psy); -free_btemp_wq: - destroy_workqueue(di->btemp_wq); - return ret; + return 0; } static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); @@ -1107,7 +1105,7 @@ static const struct of_device_id ab8500_btemp_match[] = { { }, }; -static struct platform_driver ab8500_btemp_driver = { +struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = ab8500_btemp_remove, .driver = { @@ -1116,20 +1114,6 @@ static struct platform_driver ab8500_btemp_driver = { .pm = &ab8500_btemp_pm_ops, }, }; - -static int __init ab8500_btemp_init(void) -{ - return platform_driver_register(&ab8500_btemp_driver); -} - -static void __exit ab8500_btemp_exit(void) -{ - platform_driver_unregister(&ab8500_btemp_driver); -} - -device_initcall(ab8500_btemp_init); -module_exit(ab8500_btemp_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); MODULE_ALIAS("platform:ab8500-btemp"); diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index a9be10eb2c22..af32cfae9f19 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/notifier.h> @@ -3276,10 +3277,74 @@ static struct notifier_block charger_nb = { .notifier_call = ab8500_external_charger_prepare, }; -static int ab8500_charger_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static const struct power_supply_desc ab8500_ac_chg_desc = { + .name = "ab8500_ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = ab8500_charger_ac_props, + .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), + .get_property = ab8500_charger_ac_get_property, +}; + +static const struct power_supply_desc ab8500_usb_chg_desc = { + .name = "ab8500_usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = ab8500_charger_usb_props, + .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), + .get_property = ab8500_charger_usb_get_property, +}; + +static int ab8500_charger_bind(struct device *dev) { - struct ab8500_charger *di = platform_get_drvdata(pdev); - int i, irq, ret; + struct ab8500_charger *di = dev_get_drvdata(dev); + int ch_stat; + int ret; + + /* Create a work queue for the charger */ + di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", + WQ_MEM_RECLAIM); + if (di->charger_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + ch_stat = ab8500_charger_detect_chargers(di, false); + + if (ch_stat & AC_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->ac_charger_attached_work, + HZ); + } + if (ch_stat & USB_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->usb_charger_attached_work, + HZ); + di->vbus_detected = true; + di->vbus_detected_start = true; + queue_work(di->charger_wq, + &di->detect_usb_type_work); + } + + ret = component_bind_all(dev, di); + if (ret) { + dev_err(dev, "can't bind component devices\n"); + return ret; + } + + return 0; +} + +static void ab8500_charger_unbind(struct device *dev) +{ + struct ab8500_charger *di = dev_get_drvdata(dev); + int ret; /* Disable AC charging */ ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); @@ -3287,68 +3352,47 @@ static int ab8500_charger_remove(struct platform_device *pdev) /* Disable USB charging */ ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } - /* Backup battery voltage and current disable */ ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); if (ret < 0) dev_err(di->dev, "%s mask and set failed\n", __func__); - usb_unregister_notifier(di->usb_phy, &di->nb); - usb_put_phy(di->usb_phy); - /* Delete the work queue */ destroy_workqueue(di->charger_wq); - /* Unregister external charger enable notifier */ - if (!di->ac_chg.enabled) - blocking_notifier_chain_unregister( - &charger_notifier_list, &charger_nb); - flush_scheduled_work(); - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); - - if (di->ac_chg.enabled && !di->ac_chg.external) - power_supply_unregister(di->ac_chg.psy); - return 0; + /* Unbind fg, btemp, algorithm */ + component_unbind_all(dev, di); } -static char *supply_interface[] = { - "ab8500_chargalg", - "ab8500_fg", - "ab8500_btemp", +static const struct component_master_ops ab8500_charger_comp_ops = { + .bind = ab8500_charger_bind, + .unbind = ab8500_charger_unbind, }; -static const struct power_supply_desc ab8500_ac_chg_desc = { - .name = "ab8500_ac", - .type = POWER_SUPPLY_TYPE_MAINS, - .properties = ab8500_charger_ac_props, - .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), - .get_property = ab8500_charger_ac_get_property, +static struct platform_driver *const ab8500_charger_component_drivers[] = { + &ab8500_fg_driver, + &ab8500_btemp_driver, + &abx500_chargalg_driver, }; -static const struct power_supply_desc ab8500_usb_chg_desc = { - .name = "ab8500_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = ab8500_charger_usb_props, - .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), - .get_property = ab8500_charger_usb_get_property, -}; +static int ab8500_charger_compare_dev(struct device *dev, void *data) +{ + return dev == data; +} static int ab8500_charger_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct component_match *match = NULL; struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; struct ab8500_charger *di; - int irq, i, charger_status, ret = 0, ch_stat; - struct device *dev = &pdev->dev; + int charger_status; + int i, irq; + int ret; di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); if (!di) @@ -3393,6 +3437,38 @@ static int ab8500_charger_probe(struct platform_device *pdev) return ret; } + /* + * VDD ADC supply needs to be enabled from this driver when there + * is a charger connected to avoid erroneous BTEMP_HIGH/LOW + * interrupts during charging + */ + di->regu = devm_regulator_get(dev, "vddadc"); + if (IS_ERR(di->regu)) { + ret = PTR_ERR(di->regu); + dev_err(dev, "failed to get vddadc regulator\n"); + return ret; + } + + /* Request interrupts */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { + irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, + irq, NULL, ab8500_charger_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_charger_irq[i].name, di); + + if (ret != 0) { + dev_err(dev, "failed to request %s IRQ %d: %d\n" + , ab8500_charger_irq[i].name, irq, ret); + return ret; + } + dev_dbg(dev, "Requested %s IRQ %d: %d\n", + ab8500_charger_irq[i].name, irq, ret); + } + /* initialize lock */ spin_lock_init(&di->usb_state.usb_lock); mutex_init(&di->usb_ipt_crnt_lock); @@ -3422,11 +3498,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->ac_chg.enabled = di->bm->ac_enabled; di->ac_chg.external = false; - /*notifier for external charger enabling*/ - if (!di->ac_chg.enabled) - blocking_notifier_chain_register( - &charger_notifier_list, &charger_nb); - /* USB supply */ /* ux500_charger sub-class */ di->usb_chg.ops.enable = &ab8500_charger_usb_en; @@ -3442,14 +3513,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->usb_chg.external = false; di->usb_state.usb_current = -1; - /* Create a work queue for the charger */ - di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", - WQ_MEM_RECLAIM); - if (di->charger_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - mutex_init(&di->charger_attached_mutex); /* Init work for HW failure check */ @@ -3500,63 +3563,36 @@ static int ab8500_charger_probe(struct platform_device *pdev) INIT_WORK(&di->check_usb_thermal_prot_work, ab8500_charger_check_usb_thermal_prot_work); - /* - * VDD ADC supply needs to be enabled from this driver when there - * is a charger connected to avoid erroneous BTEMP_HIGH/LOW - * interrupts during charging - */ - di->regu = devm_regulator_get(dev, "vddadc"); - if (IS_ERR(di->regu)) { - ret = PTR_ERR(di->regu); - dev_err(dev, "failed to get vddadc regulator\n"); - goto free_charger_wq; - } - /* Initialize OVV, and other registers */ ret = ab8500_charger_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize ABB registers\n"); - goto free_charger_wq; + return ret; } /* Register AC charger class */ if (di->ac_chg.enabled) { - di->ac_chg.psy = power_supply_register(dev, + di->ac_chg.psy = devm_power_supply_register(dev, &ab8500_ac_chg_desc, &ac_psy_cfg); if (IS_ERR(di->ac_chg.psy)) { dev_err(dev, "failed to register AC charger\n"); - ret = PTR_ERR(di->ac_chg.psy); - goto free_charger_wq; + return PTR_ERR(di->ac_chg.psy); } } /* Register USB charger class */ if (di->usb_chg.enabled) { - di->usb_chg.psy = power_supply_register(dev, + di->usb_chg.psy = devm_power_supply_register(dev, &ab8500_usb_chg_desc, &usb_psy_cfg); if (IS_ERR(di->usb_chg.psy)) { dev_err(dev, "failed to register USB charger\n"); - ret = PTR_ERR(di->usb_chg.psy); - goto free_ac; + return PTR_ERR(di->usb_chg.psy); } } - di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(di->usb_phy)) { - dev_err(dev, "failed to get usb transceiver\n"); - ret = -EINVAL; - goto free_usb; - } - di->nb.notifier_call = ab8500_charger_usb_notifier_call; - ret = usb_register_notifier(di->usb_phy, &di->nb); - if (ret) { - dev_err(dev, "failed to register usb notifier\n"); - goto put_usb_phy; - } - /* Identify the connected charger types during startup */ charger_status = ab8500_charger_detect_chargers(di, true); if (charger_status & AC_PW_CONN) { @@ -3566,78 +3602,86 @@ static int ab8500_charger_probe(struct platform_device *pdev) sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); } - if (charger_status & USB_PW_CONN) { - di->vbus_detected = true; - di->vbus_detected_start = true; - queue_work(di->charger_wq, - &di->detect_usb_type_work); - } - - /* Register interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + platform_set_drvdata(pdev, di); - ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_charger_irq[i].name, di); + /* Create something that will match the subdrivers when we bind */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) { + struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver; + struct device *p = NULL, *d; - if (ret != 0) { - dev_err(dev, "failed to request %s IRQ %d: %d\n" - , ab8500_charger_irq[i].name, irq, ret); - goto free_irq; + while ((d = platform_find_device_by_driver(p, drv))) { + put_device(p); + component_match_add(dev, &match, + ab8500_charger_compare_dev, d); + p = d; } - dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_charger_irq[i].name, irq, ret); + put_device(p); + } + if (!match) { + dev_err(dev, "no matching components\n"); + return -ENODEV; + } + if (IS_ERR(match)) { + dev_err(dev, "could not create component match\n"); + return PTR_ERR(match); } - platform_set_drvdata(pdev, di); + /* Notifier for external charger enabling */ + if (!di->ac_chg.enabled) + blocking_notifier_chain_register( + &charger_notifier_list, &charger_nb); - mutex_lock(&di->charger_attached_mutex); - ch_stat = ab8500_charger_detect_chargers(di, false); - - if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->ac_charger_attached_work, - HZ); + di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(di->usb_phy)) { + dev_err(dev, "failed to get usb transceiver\n"); + ret = -EINVAL; + goto out_charger_notifier; } - if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->usb_charger_attached_work, - HZ); + di->nb.notifier_call = ab8500_charger_usb_notifier_call; + ret = usb_register_notifier(di->usb_phy, &di->nb); + if (ret) { + dev_err(dev, "failed to register usb notifier\n"); + goto put_usb_phy; } - mutex_unlock(&di->charger_attached_mutex); - return ret; + ret = component_master_add_with_match(&pdev->dev, + &ab8500_charger_comp_ops, + match); + if (ret) { + dev_err(dev, "failed to add component master\n"); + goto free_notifier; + } -free_irq: - usb_unregister_notifier(di->usb_phy, &di->nb); + return 0; - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } +free_notifier: + usb_unregister_notifier(di->usb_phy, &di->nb); put_usb_phy: usb_put_phy(di->usb_phy); -free_usb: - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); -free_ac: - if (di->ac_chg.enabled) - power_supply_unregister(di->ac_chg.psy); -free_charger_wq: - destroy_workqueue(di->charger_wq); +out_charger_notifier: + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); return ret; } +static int ab8500_charger_remove(struct platform_device *pdev) +{ + struct ab8500_charger *di = platform_get_drvdata(pdev); + + component_master_del(&pdev->dev, &ab8500_charger_comp_ops); + + usb_unregister_notifier(di->usb_phy, &di->nb); + usb_put_phy(di->usb_phy); + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); + + return 0; +} + static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); static const struct of_device_id ab8500_charger_match[] = { @@ -3657,15 +3701,24 @@ static struct platform_driver ab8500_charger_driver = { static int __init ab8500_charger_init(void) { + int ret; + + ret = platform_register_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); + if (ret) + return ret; + return platform_driver_register(&ab8500_charger_driver); } static void __exit ab8500_charger_exit(void) { + platform_unregister_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); platform_driver_unregister(&ab8500_charger_driver); } -subsys_initcall_sync(ab8500_charger_init); +module_init(ab8500_charger_init); module_exit(ab8500_charger_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 0c7c01a0d979..acf0f2471c0b 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/component.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -2980,27 +2981,6 @@ static int __maybe_unused ab8500_fg_suspend(struct device *dev) return 0; } -static int ab8500_fg_remove(struct platform_device *pdev) -{ - int ret = 0; - struct ab8500_fg *di = platform_get_drvdata(pdev); - - list_del(&di->node); - - /* Disable coulomb counter */ - ret = ab8500_fg_coulomb_counter(di, false); - if (ret) - dev_err(di->dev, "failed to disable coulomb counter\n"); - - destroy_workqueue(di->fg_wq); - ab8500_fg_sysfs_exit(di); - - flush_scheduled_work(); - ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); - return ret; -} - /* ab8500 fg driver interrupts and their respective isr */ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, @@ -3024,11 +3004,50 @@ static const struct power_supply_desc ab8500_fg_desc = { .external_power_changed = ab8500_fg_external_power_changed, }; +static int ab8500_fg_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + + /* Create a work queue for running the FG algorithm */ + di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); + if (di->fg_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Start the coulomb counter */ + ab8500_fg_coulomb_counter(di, true); + /* Run the FG algorithm */ + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + return 0; +} + +static void ab8500_fg_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + int ret; + + /* Disable coulomb counter */ + ret = ab8500_fg_coulomb_counter(di, false); + if (ret) + dev_err(dev, "failed to disable coulomb counter\n"); + + destroy_workqueue(di->fg_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_fg_component_ops = { + .bind = ab8500_fg_bind, + .unbind = ab8500_fg_unbind, +}; + static int ab8500_fg_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct power_supply_config psy_cfg = {}; struct device *dev = &pdev->dev; + struct power_supply_config psy_cfg = {}; struct ab8500_fg *di; int i, irq; int ret = 0; @@ -3074,13 +3093,6 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); - /* Create a work queue for running the FG algorithm */ - di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); - if (di->fg_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for running the fg algorithm instantly */ INIT_WORK(&di->fg_work, ab8500_fg_instant_work); @@ -3113,7 +3125,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize registers\n"); - goto free_inst_curr_wq; + return ret; } /* Consider battery unknown until we're informed otherwise */ @@ -3121,15 +3133,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->flags.batt_id_received = false; /* Register FG power supply class */ - di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); + di->fg_psy = devm_power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); if (IS_ERR(di->fg_psy)) { dev_err(dev, "failed to register FG psy\n"); - ret = PTR_ERR(di->fg_psy); - goto free_inst_curr_wq; + return PTR_ERR(di->fg_psy); } di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); - ab8500_fg_coulomb_counter(di, true); /* * Initialize completion used to notify completion and start @@ -3141,19 +3151,18 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Register primary interrupt handlers */ for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_fg_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_fg_irq[i].name, di); if (ret != 0) { dev_err(dev, "failed to request %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); @@ -3168,14 +3177,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_sysfs_init(di); if (ret) { dev_err(dev, "failed to create sysfs entry\n"); - goto free_irq; + return ret; } ret = ab8500_fg_sysfs_psy_create_attrs(di); if (ret) { dev_err(dev, "failed to create FG psy\n"); ab8500_fg_sysfs_exit(di); - goto free_irq; + return ret; } /* Calibrate the fg first time */ @@ -3185,24 +3194,21 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Use room temp as default value until we get an update from driver. */ di->bat_temp = 210; - /* Run the FG algorithm */ - queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); - list_add_tail(&di->node, &ab8500_fg_list); - return ret; + return component_add(dev, &ab8500_fg_component_ops); +} -free_irq: - /* We also have to free all registered irqs */ - while (--i >= 0) { - /* Last assignment of i from primary interrupt handlers */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - free_irq(irq, di); - } +static int ab8500_fg_remove(struct platform_device *pdev) +{ + int ret = 0; + struct ab8500_fg *di = platform_get_drvdata(pdev); + + component_del(&pdev->dev, &ab8500_fg_component_ops); + list_del(&di->node); + ab8500_fg_sysfs_exit(di); + ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); -free_inst_curr_wq: - destroy_workqueue(di->fg_wq); return ret; } @@ -3213,7 +3219,7 @@ static const struct of_device_id ab8500_fg_match[] = { { }, }; -static struct platform_driver ab8500_fg_driver = { +struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, .remove = ab8500_fg_remove, .driver = { @@ -3222,20 +3228,6 @@ static struct platform_driver ab8500_fg_driver = { .pm = &ab8500_fg_pm_ops, }, }; - -static int __init ab8500_fg_init(void) -{ - return platform_driver_register(&ab8500_fg_driver); -} - -static void __exit ab8500_fg_exit(void) -{ - platform_driver_unregister(&ab8500_fg_driver); -} - -subsys_initcall_sync(ab8500_fg_init); -module_exit(ab8500_fg_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); MODULE_ALIAS("platform:ab8500-fg"); diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c index f5b792243727..599684ce0e4b 100644 --- a/drivers/power/supply/abx500_chargalg.c +++ b/drivers/power/supply/abx500_chargalg.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/hrtimer.h> #include <linux/interrupt.h> #include <linux/delay.h> @@ -1943,13 +1944,44 @@ static int __maybe_unused abx500_chargalg_suspend(struct device *dev) return 0; } -static int abx500_chargalg_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_fg", +}; + </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_bmk_tx1/llvm-master-aarch64-spec2k6-O3_LTO - Build # 26 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *llvm* in CI configuration tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3_LTO. So far, this commit has regressed CI configurations: - tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3_LTO Culprit: <cut> commit 45b7cf995551a0c0743e5d69f611bba7e4072ddf Author: Sam Clegg <sbc(a)chromium.org> Date: Wed May 12 16:48:34 2021 -0700 [lld][WebAssembly] Enable string tail merging in debug sections This is a followup to
https://reviews.llvm.org/D97657
which applied string tail merging to data segments. Fixes:
https://bugs.llvm.org/show_bug.cgi?id=48828
Differential Revision:
https://reviews.llvm.org/D102436
</cut> Results regressed to (for first_bad == 45b7cf995551a0c0743e5d69f611bba7e4072ddf) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer: -5 # build_llvm true: -3 # true: 0 # benchmark -O3_LTO -- artifacts/build-45b7cf995551a0c0743e5d69f611bba7e4072ddf/results_id: 1 # 433.milc,milc_base.default regressed by 104 from (for last_good == 8dd5ef01ef13e402784bba47f7a24175f5f00325) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer: -5 # build_llvm true: -3 # true: 0 # benchmark -O3_LTO -- artifacts/build-8dd5ef01ef13e402784bba47f7a24175f5f00325/results_id: 1 Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of last_good: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3_LTO/2681 Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of first_bad: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3_LTO/2637 Build top page/logs:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Configuration details: Reproduce builds: <cut> mkdir investigate-llvm-45b7cf995551a0c0743e5d69f611bba7e4072ddf cd investigate-llvm-45b7cf995551a0c0743e5d69f611bba7e4072ddf git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /llvm/ ./ ./bisect/baseline/ cd llvm # Reproduce first_bad build git checkout --detach 45b7cf995551a0c0743e5d69f611bba7e4072ddf ../artifacts/test.sh # Reproduce last_good build git checkout --detach 8dd5ef01ef13e402784bba47f7a24175f5f00325 ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Build log:
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Full commit (up to 1000 lines): <cut> commit 45b7cf995551a0c0743e5d69f611bba7e4072ddf Author: Sam Clegg <sbc(a)chromium.org> Date: Wed May 12 16:48:34 2021 -0700 [lld][WebAssembly] Enable string tail merging in debug sections This is a followup to
https://reviews.llvm.org/D97657
which applied string tail merging to data segments. Fixes:
https://bugs.llvm.org/show_bug.cgi?id=48828
Differential Revision:
https://reviews.llvm.org/D102436
--- lld/test/wasm/Inputs/merge-string-debug2.s | 4 +++ lld/test/wasm/merge-string-debug.s | 22 ++++++++++++++ lld/wasm/Driver.cpp | 6 +++- lld/wasm/InputChunks.cpp | 16 +++++----- lld/wasm/InputChunks.h | 49 +++++++++++++++++------------- lld/wasm/InputFiles.cpp | 23 +++++++++++--- lld/wasm/InputFiles.h | 4 +-- lld/wasm/OutputSections.cpp | 38 ++++++++++++++++++++--- lld/wasm/OutputSections.h | 5 +-- lld/wasm/OutputSegment.cpp | 7 ++--- lld/wasm/Symbols.cpp | 2 +- lld/wasm/Symbols.h | 4 +-- lld/wasm/Writer.cpp | 4 +-- llvm/include/llvm/MC/MCContext.h | 5 +-- llvm/lib/MC/MCObjectFileInfo.cpp | 11 ++++--- 15 files changed, 143 insertions(+), 57 deletions(-) diff --git a/lld/test/wasm/Inputs/merge-string-debug2.s b/lld/test/wasm/Inputs/merge-string-debug2.s new file mode 100644 index 000000000000..1f4979056ac8 --- /dev/null +++ b/lld/test/wasm/Inputs/merge-string-debug2.s @@ -0,0 +1,4 @@ +.section .debug_str,"S",@ + .asciz "clang version 13.0.0" + .asciz "bar" + .asciz "foo" diff --git a/lld/test/wasm/merge-string-debug.s b/lld/test/wasm/merge-string-debug.s new file mode 100644 index 000000000000..4a663501959f --- /dev/null +++ b/lld/test/wasm/merge-string-debug.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/merge-string-debug2.s -o %t2.o + +# RUN: wasm-ld %t.o %t2.o -o %t.wasm --no-entry +# RUN: llvm-readobj -x .debug_str %t.wasm | FileCheck %s --check-prefixes CHECK,CHECK-O1 + +# RUN: wasm-ld -O0 %t.o %t2.o -o %tO0.wasm --no-entry +# RUN: llvm-readobj -x .debug_str %tO0.wasm | FileCheck %s --check-prefixes CHECK,CHECK-O0 + +.section .debug_str,"S",@ + .asciz "clang version 13.0.0" + .asciz "foobar" + +# CHECK: Hex dump of section '.debug_str': + +# CHECK-O0: 0x00000000 636c616e 67207665 7273696f 6e203133 clang version 13 +# CHECK-O0: 0x00000010 2e302e30 00666f6f 62617200 636c616e .0.0.foobar.clan +# CHECK-O0: 0x00000020 67207665 7273696f 6e203133 2e302e30 g version 13.0.0 +# CHECK-O0: 0x00000030 00626172 00666f6f 00 .bar.foo. + +# CHECK-O1: 0x00000000 666f6f62 61720066 6f6f0063 6c616e67 foobar.foo.clang +# CHECK-O1: 0x00000010 20766572 73696f6e 2031332e 302e3000 version 13.0.0. diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 6fec9d5b2278..9b01a84f7812 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -796,7 +796,7 @@ static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) { } static void splitSections() { - // splitIntoPieces needs to be called on each MergeInputSection + // splitIntoPieces needs to be called on each MergeInputChunk // before calling finalizeContents(). LLVM_DEBUG(llvm::dbgs() << "splitSections\n"); parallelForEach(symtab->objectFiles, [](ObjFile *file) { @@ -804,6 +804,10 @@ static void splitSections() { if (auto *s = dyn_cast<MergeInputChunk>(seg)) s->splitIntoPieces(); } + for (InputChunk *sec : file->customSections) { + if (auto *s = dyn_cast<MergeInputChunk>(sec)) + s->splitIntoPieces(); + } }); } diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index b7d1aa25e9c8..279cd41d1ff2 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -328,24 +328,24 @@ void InputFunction::writeCompressed(uint8_t *buf) const { LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n"); } -uint64_t InputChunk::getOffset(uint64_t offset) const { - return outSecOff + offset; -} - -uint64_t InputChunk::getSegmentOffset(uint64_t offset) const { +uint64_t InputChunk::getChunkOffset(uint64_t offset) const { if (const auto *ms = dyn_cast<MergeInputChunk>(this)) { - LLVM_DEBUG(dbgs() << "getSegmentOffset(merged): " << getName() << "\n"); + LLVM_DEBUG(dbgs() << "getChunkOffset(merged): " << getName() << "\n"); LLVM_DEBUG(dbgs() << "offset: " << offset << "\n"); LLVM_DEBUG(dbgs() << "parentOffset: " << ms->getParentOffset(offset) << "\n"); assert(ms->parent); - return ms->parent->getSegmentOffset(ms->getParentOffset(offset)); + return ms->parent->getChunkOffset(ms->getParentOffset(offset)); } return outputSegmentOffset + offset; } +uint64_t InputChunk::getOffset(uint64_t offset) const { + return outSecOff + getChunkOffset(offset); +} + uint64_t InputChunk::getVA(uint64_t offset) const { - return (outputSeg ? outputSeg->startVA : 0) + getSegmentOffset(offset); + return (outputSeg ? outputSeg->startVA : 0) + getChunkOffset(offset); } // Generate code to apply relocations to the data section at runtime. diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h index 47ed7ccaadcb..f1174d937ad3 100644 --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -43,7 +43,7 @@ public: MergedChunk, Function, SyntheticFunction, - Section + Section, }; StringRef name; @@ -62,12 +62,15 @@ public: ArrayRef<WasmRelocation> getRelocations() const { return relocations; } void setRelocations(ArrayRef<WasmRelocation> rs) { relocations = rs; } - // Translate an offset in the input section to an offset in the output + // Translate an offset into the input chunk to an offset in the output // section. uint64_t getOffset(uint64_t offset) const; - // For data segments, translate and offset into the input segment into - // an offset into the output segment - uint64_t getSegmentOffset(uint64_t offset) const; + // Translate an offset into the input chunk into an offset into the output + // chunk. For data segments (InputSegment) this will return and offset into + // the output segment. For MergeInputChunk, this will return an offset into + // the parent merged chunk. For other chunk types this is no-op and we just + // return unmodified offset. + uint64_t getChunkOffset(uint64_t offset) const; uint64_t getVA(uint64_t offset = 0) const; uint32_t getComdat() const { return comdat; } @@ -132,22 +135,19 @@ protected: // each global variable. class InputSegment : public InputChunk { public: - InputSegment(const WasmSegment *seg, ObjFile *f) - : InputChunk(f, InputChunk::DataSegment, seg->Data.Name, - seg->Data.Alignment, seg->Data.LinkingFlags), + InputSegment(const WasmSegment &seg, ObjFile *f) + : InputChunk(f, InputChunk::DataSegment, seg.Data.Name, + seg.Data.Alignment, seg.Data.LinkingFlags), segment(seg) { - rawData = segment->Data.Content; - comdat = segment->Data.Comdat; - inputSectionOffset = segment->SectionOffset; + rawData = segment.Data.Content; + comdat = segment.Data.Comdat; + inputSectionOffset = segment.SectionOffset; } - InputSegment(StringRef name, uint32_t alignment, uint32_t flags) - : InputChunk(nullptr, InputChunk::DataSegment, name, alignment, flags) {} - static bool classof(const InputChunk *c) { return c->kind() == DataSegment; } protected: - const WasmSegment *segment = nullptr; + const WasmSegment &segment; }; class SyntheticMergedChunk; @@ -174,12 +174,19 @@ static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big"); // This corresponds segments marked as WASM_SEG_FLAG_STRINGS. class MergeInputChunk : public InputChunk { public: - MergeInputChunk(const WasmSegment *seg, ObjFile *f) - : InputChunk(f, Merge, seg->Data.Name, seg->Data.Alignment, - seg->Data.LinkingFlags) { - rawData = seg->Data.Content; - comdat = seg->Data.Comdat; - inputSectionOffset = seg->SectionOffset; + MergeInputChunk(const WasmSegment &seg, ObjFile *f) + : InputChunk(f, Merge, seg.Data.Name, seg.Data.Alignment, + seg.Data.LinkingFlags) { + rawData = seg.Data.Content; + comdat = seg.Data.Comdat; + inputSectionOffset = seg.SectionOffset; + } + + MergeInputChunk(const WasmSection &s, ObjFile *f) + : InputChunk(f, Merge, s.Name, 0, llvm::wasm::WASM_SEG_FLAG_STRINGS) { + assert(s.Type == llvm::wasm::WASM_SEC_CUSTOM); + comdat = s.Comdat; + rawData = s.Content; } static bool classof(const InputChunk *s) { return s->kind() == Merge; } diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index c65b05109c3d..7fd9215f1171 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -360,6 +360,17 @@ void ObjFile::addLegacyIndirectFunctionTableIfNeeded( config->legacyFunctionTable = true; } +static bool shouldMerge(const WasmSection &sec) { + if (config->optimize == 0) + return false; + // Sadly we don't have section attributes yet for custom sections, so we + // currently go by the name alone. + // TODO(sbc): Add ability for wasm sections to carry flags so we don't + // need to use names here. + return sec.Name.startswith(".debug_str") || + sec.Name.startswith(".debug_line_str"); +} + static bool shouldMerge(const WasmSegment &seg) { // As of now we only support merging strings, and only with single byte // alignment (2^0). @@ -445,7 +456,11 @@ void ObjFile::parse(bool ignoreComdats) { assert(!dataSection); dataSection = §ion; } else if (section.Type == WASM_SEC_CUSTOM) { - auto *customSec = make<InputSection>(section, this); + InputChunk *customSec; + if (shouldMerge(section)) + customSec = make<MergeInputChunk>(section, this); + else + customSec = make<InputSection>(section, this); customSec->discarded = isExcludedByComdat(customSec); customSections.emplace_back(customSec); customSections.back()->setRelocations(section.Relocations); @@ -466,9 +481,9 @@ void ObjFile::parse(bool ignoreComdats) { for (const WasmSegment &s : wasmObj->dataSegments()) { InputChunk *seg; if (shouldMerge(s)) { - seg = make<MergeInputChunk>(&s, this); + seg = make<MergeInputChunk>(s, this); } else - seg = make<InputSegment>(&s, this); + seg = make<InputSegment>(s, this); seg->discarded = isExcludedByComdat(seg); segments.emplace_back(seg); @@ -585,7 +600,7 @@ Symbol *ObjFile::createDefined(const WasmSymbol &sym) { return symtab->addDefinedGlobal(name, flags, this, global); } case WASM_SYMBOL_TYPE_SECTION: { - InputSection *section = customSectionsByIndex[sym.Info.ElementIndex]; + InputChunk *section = customSectionsByIndex[sym.Info.ElementIndex]; assert(sym.isBindingLocal()); // Need to return null if discarded here? data and func only do that when // binding is not local. diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h index b720b889adcc..49337bd0eb33 100644 --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -141,8 +141,8 @@ public: std::vector<InputGlobal *> globals; std::vector<InputEvent *> events; std::vector<InputTable *> tables; - std::vector<InputSection *> customSections; - llvm::DenseMap<uint32_t, InputSection *> customSectionsByIndex; + std::vector<InputChunk *> customSections; + llvm::DenseMap<uint32_t, InputChunk *> customSectionsByIndex; Symbol *getSymbol(uint32_t index) const { return symbols[index]; } FunctionSymbol *getFunctionSymbol(uint32_t index) const; diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp index 780c8e4b2776..e39c3331641a 100644 --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -12,6 +12,7 @@ #include "OutputSegment.h" #include "WriterUtils.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Memory.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/Parallel.h" @@ -234,13 +235,42 @@ bool DataSection::isNeeded() const { return false; } +// Lots of duplication here with OutputSegment::finalizeInputSegments +void CustomSection::finalizeInputSections() { + SyntheticMergedChunk *mergedSection = nullptr; + std::vector<InputChunk *> newSections; + + for (InputChunk *s : inputSections) { + MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s); + if (!ms) { + newSections.push_back(s); + continue; + } + + if (!mergedSection) { + mergedSection = + make<SyntheticMergedChunk>(name, 0, WASM_SEG_FLAG_STRINGS); + newSections.push_back(mergedSection); + } + mergedSection->addMergeChunk(ms); + } + + if (!mergedSection) + return; + + mergedSection->finalizeContents(); + inputSections = newSections; +} + void CustomSection::finalizeContents() { + finalizeInputSections(); + raw_string_ostream os(nameData); encodeULEB128(name.size(), os); os << name; os.flush(); - for (InputSection *section : inputSections) { + for (InputChunk *section : inputSections) { assert(!section->discarded); section->outputSec = this; section->outSecOff = payloadSize; @@ -264,19 +294,19 @@ void CustomSection::writeTo(uint8_t *buf) { buf += nameData.size(); // Write custom sections payload - for (const InputSection *section : inputSections) + for (const InputChunk *section : inputSections) section->writeTo(buf); } uint32_t CustomSection::getNumRelocations() const { uint32_t count = 0; - for (const InputSection *inputSect : inputSections) + for (const InputChunk *inputSect : inputSections) count += inputSect->getNumRelocations(); return count; } void CustomSection::writeRelocations(raw_ostream &os) const { - for (const InputSection *s : inputSections) + for (const InputChunk *s : inputSections) s->writeRelocations(os); } diff --git a/lld/wasm/OutputSections.h b/lld/wasm/OutputSections.h index 444116dac7d8..c3becf6ec240 100644 --- a/lld/wasm/OutputSections.h +++ b/lld/wasm/OutputSections.h @@ -111,7 +111,7 @@ protected: // separately and are instead synthesized by the linker. class CustomSection : public OutputSection { public: - CustomSection(std::string name, ArrayRef<InputSection *> inputSections) + CustomSection(std::string name, ArrayRef<InputChunk *> inputSections) : OutputSection(llvm::wasm::WASM_SEC_CUSTOM, name), inputSections(inputSections) {} @@ -128,8 +128,9 @@ public: void finalizeContents() override; protected: + void finalizeInputSections(); size_t payloadSize = 0; - ArrayRef<InputSection *> inputSections; + std::vector<InputChunk *> inputSections; std::string nameData; }; diff --git a/lld/wasm/OutputSegment.cpp b/lld/wasm/OutputSegment.cpp index bf3e40c968a0..c09d5c30a0f6 100644 --- a/lld/wasm/OutputSegment.cpp +++ b/lld/wasm/OutputSegment.cpp @@ -55,16 +55,15 @@ void OutputSegment::finalizeInputSegments() { return seg->flags == ms->flags && seg->alignment == ms->alignment; }); if (i == mergedSegments.end()) { - LLVM_DEBUG(llvm::dbgs() << "new merge section: " << name + LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name << " alignment=" << ms->alignment << "\n"); - SyntheticMergedChunk *syn = - make<SyntheticMergedChunk>(name, ms->alignment, ms->flags); + auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags); syn->outputSeg = this; mergedSegments.push_back(syn); i = std::prev(mergedSegments.end()); newSegments.push_back(syn); } else { - LLVM_DEBUG(llvm::dbgs() << "adding to merge section: " << name << "\n"); + LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n"); } (*i)->addMergeChunk(ms); } diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index 24b7e10dc559..6d960b4cf7e6 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -301,7 +301,7 @@ void DefinedData::setVA(uint64_t value_) { uint64_t DefinedData::getOutputSegmentOffset() const { LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); - return segment->getSegmentOffset(value); + return segment->getChunkOffset(value); } uint64_t DefinedData::getOutputSegmentIndex() const { diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index ff6eb0ae7ccb..0c557530236d 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -254,14 +254,14 @@ public: class SectionSymbol : public Symbol { public: - SectionSymbol(uint32_t flags, const InputSection *s, InputFile *f = nullptr) + SectionSymbol(uint32_t flags, const InputChunk *s, InputFile *f = nullptr) : Symbol("", SectionKind, flags, f), section(s) {} static bool classof(const Symbol *s) { return s->kind() == SectionKind; } const OutputSectionSymbol *getOutputSectionSymbol() const; - const InputSection *section; + const InputChunk *section; }; class DataSymbol : public Symbol { diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 055972560b81..1705c205eca4 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -100,7 +100,7 @@ private: uint64_t fileSize = 0; std::vector<WasmInitEntry> initFunctions; - llvm::StringMap<std::vector<InputSection *>> customSectionMapping; + llvm::StringMap<std::vector<InputChunk *>> customSectionMapping; // Stable storage for command export wrapper function name strings. std::list<std::string> commandExportWrapperNames; @@ -121,7 +121,7 @@ void Writer::calculateCustomSections() { log("calculateCustomSections"); bool stripDebug = config->stripDebug || config->stripAll; for (ObjFile *file : symtab->objectFiles) { - for (InputSection *section : file->customSections) { + for (InputChunk *section : file->customSections) { // Exclude COMDAT sections that are not selected for inclusion if (section->discarded) continue; diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index c531aa851d1e..100befc48ecb 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -610,8 +610,9 @@ namespace llvm { getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID = GenericSectionID); - MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K) { - return getWasmSection(Section, K, 0, nullptr); + MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K, + unsigned Flags = 0) { + return getWasmSection(Section, K, Flags, nullptr); } MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K, diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index 92091ffcb746..1a448f040b3b 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/BinaryFormat/Wasm.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSection.h" @@ -791,9 +792,10 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) { DwarfLineSection = Ctx->getWasmSection(".debug_line", SectionKind::getMetadata()); DwarfLineStrSection = - Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata()); - DwarfStrSection = - Ctx->getWasmSection(".debug_str", SectionKind::getMetadata()); + Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata(), + wasm::WASM_SEG_FLAG_STRINGS); + DwarfStrSection = Ctx->getWasmSection( + ".debug_str", SectionKind::getMetadata(), wasm::WASM_SEG_FLAG_STRINGS); DwarfLocSection = Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata()); DwarfAbbrevSection = @@ -836,7 +838,8 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) { DwarfAbbrevDWOSection = Ctx->getWasmSection(".debug_abbrev.dwo", SectionKind::getMetadata()); DwarfStrDWOSection = - Ctx->getWasmSection(".debug_str.dwo", SectionKind::getMetadata()); + Ctx->getWasmSection(".debug_str.dwo", SectionKind::getMetadata(), + wasm::WASM_SEG_FLAG_STRINGS); DwarfLineDWOSection = Ctx->getWasmSection(".debug_line.dwo", SectionKind::getMetadata()); DwarfLocDWOSection = </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_kernel/llvm-release-arm-next-allmodconfig - Build # 30 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *linux* in CI configuration tcwg_kernel/llvm-release-arm-next-allmodconfig. So far, this commit has regressed CI configurations: - tcwg_kernel/llvm-release-arm-next-allmodconfig Culprit: <cut> commit 3d463dd5023b5a58b3c37207d65eeb5acbac2be3 Author: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Date: Thu Jul 29 12:40:19 2021 +0200 nfc: fdp: constify several pointers Several functions do not modify pointed data so arguments and local variables can be const for correctness and safety. This allows also making file-scope nci_core_get_config_otp_ram_version array const. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Signed-off-by: David S. Miller <davem(a)davemloft.net> </cut> Results regressed to (for first_bad == 3d463dd5023b5a58b3c37207d65eeb5acbac2be3) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 21699 # First few build errors in logs: # 00:02:22 drivers/nfc/fdp/fdp.c:116:60: error: passing 'const char *' to parameter of type '__u8 *' (aka 'unsigned char *') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers] # 00:02:22 make[3]: *** [drivers/nfc/fdp/fdp.o] Error 1 # 00:02:23 make[2]: *** [drivers/nfc/fdp] Error 2 # 00:02:45 make[1]: *** [drivers/nfc] Error 2 # 00:05:31 make: *** [drivers] Error 2 from (for last_good == c3e26b6dc1b4e3e8f57be4f004b1f2a410c5c468) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 29761 # linux build successful: all Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
Build top page/logs:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
Configuration details: rr[linux_git]="
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git#cb16362…
" Reproduce builds: <cut> mkdir investigate-linux-3d463dd5023b5a58b3c37207d65eeb5acbac2be3 cd investigate-linux-3d463dd5023b5a58b3c37207d65eeb5acbac2be3 git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /linux/ ./ ./bisect/baseline/ cd linux # Reproduce first_bad build git checkout --detach 3d463dd5023b5a58b3c37207d65eeb5acbac2be3 ../artifacts/test.sh # Reproduce last_good build git checkout --detach c3e26b6dc1b4e3e8f57be4f004b1f2a410c5c468 ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
Build log:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-next-all…
Full commit (up to 1000 lines): <cut> commit 3d463dd5023b5a58b3c37207d65eeb5acbac2be3 Author: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Date: Thu Jul 29 12:40:19 2021 +0200 nfc: fdp: constify several pointers Several functions do not modify pointed data so arguments and local variables can be const for correctness and safety. This allows also making file-scope nci_core_get_config_otp_ram_version array const. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Signed-off-by: David S. Miller <davem(a)davemloft.net> --- drivers/nfc/fdp/fdp.c | 18 +++++++++--------- drivers/nfc/fdp/fdp.h | 2 +- drivers/nfc/fdp/i2c.c | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index 3f5fba922c4d..c6b3334f24c9 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c @@ -52,7 +52,7 @@ struct fdp_nci_info { u32 limited_otp_version; u8 key_index; - u8 *fw_vsc_cfg; + const u8 *fw_vsc_cfg; u8 clock_type; u32 clock_freq; @@ -65,7 +65,7 @@ struct fdp_nci_info { wait_queue_head_t setup_wq; }; -static u8 nci_core_get_config_otp_ram_version[5] = { +static const u8 nci_core_get_config_otp_ram_version[5] = { 0x04, NCI_PARAM_ID_FW_RAM_VERSION, NCI_PARAM_ID_FW_OTP_VERSION, @@ -111,7 +111,7 @@ static inline int fdp_nci_patch_cmd(struct nci_dev *ndev, u8 type) } static inline int fdp_nci_set_production_data(struct nci_dev *ndev, u8 len, - char *data) + const char *data) { return nci_prop_cmd(ndev, NCI_OP_PROP_SET_PDATA_OID, len, data); } @@ -236,7 +236,7 @@ static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) static int fdp_nci_open(struct nci_dev *ndev) { - struct fdp_nci_info *info = nci_get_drvdata(ndev); + const struct fdp_nci_info *info = nci_get_drvdata(ndev); return info->phy_ops->enable(info->phy); } @@ -260,7 +260,7 @@ static int fdp_nci_request_firmware(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; - u8 *data; + const u8 *data; int r; r = request_firmware(&info->ram_patch, FDP_RAM_PATCH_NAME, dev); @@ -269,7 +269,7 @@ static int fdp_nci_request_firmware(struct nci_dev *ndev) return r; } - data = (u8 *) info->ram_patch->data; + data = info->ram_patch->data; info->ram_patch_version = data[FDP_FW_HEADER_SIZE] | (data[FDP_FW_HEADER_SIZE + 1] << 8) | @@ -610,9 +610,9 @@ static int fdp_nci_core_get_config_rsp_packet(struct nci_dev *ndev, { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; - struct nci_core_get_config_rsp *rsp = (void *) skb->data; + const struct nci_core_get_config_rsp *rsp = (void *) skb->data; unsigned int i; - u8 *p; + const u8 *p; if (rsp->status == NCI_STATUS_OK) { @@ -691,7 +691,7 @@ static const struct nci_ops nci_ops = { int fdp_nci_probe(struct fdp_i2c_phy *phy, const struct nfc_phy_ops *phy_ops, struct nci_dev **ndevp, int tx_headroom, int tx_tailroom, u8 clock_type, u32 clock_freq, - u8 *fw_vsc_cfg) + const u8 *fw_vsc_cfg) { struct device *dev = &phy->i2c_dev->dev; struct fdp_nci_info *info; diff --git a/drivers/nfc/fdp/fdp.h b/drivers/nfc/fdp/fdp.h index dc048d4b977e..2e9161a4d7bf 100644 --- a/drivers/nfc/fdp/fdp.h +++ b/drivers/nfc/fdp/fdp.h @@ -23,7 +23,7 @@ struct fdp_i2c_phy { int fdp_nci_probe(struct fdp_i2c_phy *phy, const struct nfc_phy_ops *phy_ops, struct nci_dev **ndev, int tx_headroom, int tx_tailroom, - u8 clock_type, u32 clock_freq, u8 *fw_vsc_cfg); + u8 clock_type, u32 clock_freq, const u8 *fw_vsc_cfg); void fdp_nci_remove(struct nci_dev *ndev); #endif /* __LOCAL_FDP_H_ */ diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c index 98e1876c9468..051c43a2a52f 100644 --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -36,7 +36,7 @@ print_hex_dump(KERN_DEBUG, prefix": ", DUMP_PREFIX_OFFSET, \ 16, 1, (skb)->data, (skb)->len, 0) -static void fdp_nci_i2c_reset(struct fdp_i2c_phy *phy) +static void fdp_nci_i2c_reset(const struct fdp_i2c_phy *phy) { /* Reset RST/WakeUP for at least 100 micro-second */ gpiod_set_value_cansleep(phy->power_gpio, FDP_POWER_OFF); @@ -47,7 +47,7 @@ static void fdp_nci_i2c_reset(struct fdp_i2c_phy *phy) static int fdp_nci_i2c_enable(void *phy_id) { - struct fdp_i2c_phy *phy = phy_id; + const struct fdp_i2c_phy *phy = phy_id; fdp_nci_i2c_reset(phy); @@ -56,7 +56,7 @@ static int fdp_nci_i2c_enable(void *phy_id) static void fdp_nci_i2c_disable(void *phy_id) { - struct fdp_i2c_phy *phy = phy_id; + const struct fdp_i2c_phy *phy = phy_id; fdp_nci_i2c_reset(phy); } </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_bmk_tx1/gnu-release-aarch64-spec2k6-O2 - Build # 17 - Fixed!
by ci_notify@linaro.org
Successfully identified regression in *gcc* in CI configuration tcwg_bmk_gnu_tx1/gnu-release-aarch64-spec2k6-O2. So far, this commit has regressed CI configurations: - tcwg_bmk_gnu_tx1/gnu-release-aarch64-spec2k6-O2 Culprit: <cut> commit 0b92cf305dcf34387a8e2564e55ca8948df3b47a Author: Jan Hubicka <hubicka(a)ucw.cz> Date: Tue Oct 1 18:58:35 2019 +0200 invoke.texi (early-inlining-insns-O2): Document. * doc/invoke.texi (early-inlining-insns-O2): Document. (early-inlining-insns): Update. * params.def (early-inlining-insns-O2): New bound. (early-inlining-insns): Update docs. * ipa-inline.c (want_early_inline_function_p): Use new bound. * g++.dg/tree-ssa/pr61034.C: Set early-inlining-insns-O2=14. * g++.dg/tree-ssa/pr8781.C: Likewise. * g++.dg/warn/Wstringop-truncation-1.C: Likewise. * gcc.dg/ipa/pr63416.c: likewise. * gcc.dg/vect/pr66142.c: Likewise. * gcc.dg/tree-ssa/ssa-thread-12.c: Mark compure_idf inline. From-SVN: r276416 </cut> Results regressed to (for first_bad == 0b92cf305dcf34387a8e2564e55ca8948df3b47a) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer: -5 # true: 0 # benchmark -O2 -- artifacts/build-0b92cf305dcf34387a8e2564e55ca8948df3b47a/results_id: 1 # 483.xalancbmk,Xalan_base.default regressed by 103 # 447.dealII,[.] _ZSt18_Rb_tree_incrementPKSt18_Rb_tree_node_ba regressed by 1239 from (for last_good == 7552c36afa1f9058bb39f336ae84f019621885a0) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer: -5 # true: 0 # benchmark -O2 -- artifacts/build-7552c36afa1f9058bb39f336ae84f019621885a0/results_id: 1 Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Results ID of last_good: tx1_64/tcwg_bmk_gnu_tx1/bisect-gnu-release-aarch64-spec2k6-O2/2646 Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Results ID of first_bad: tx1_64/tcwg_bmk_gnu_tx1/bisect-gnu-release-aarch64-spec2k6-O2/2640 Build top page/logs:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Configuration details: Reproduce builds: <cut> mkdir investigate-gcc-0b92cf305dcf34387a8e2564e55ca8948df3b47a cd investigate-gcc-0b92cf305dcf34387a8e2564e55ca8948df3b47a git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/ cd gcc # Reproduce first_bad build git checkout --detach 0b92cf305dcf34387a8e2564e55ca8948df3b47a ../artifacts/test.sh # Reproduce last_good build git checkout --detach 7552c36afa1f9058bb39f336ae84f019621885a0 ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Build log:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Full commit (up to 1000 lines): <cut> commit 0b92cf305dcf34387a8e2564e55ca8948df3b47a Author: Jan Hubicka <hubicka(a)ucw.cz> Date: Tue Oct 1 18:58:35 2019 +0200 invoke.texi (early-inlining-insns-O2): Document. * doc/invoke.texi (early-inlining-insns-O2): Document. (early-inlining-insns): Update. * params.def (early-inlining-insns-O2): New bound. (early-inlining-insns): Update docs. * ipa-inline.c (want_early_inline_function_p): Use new bound. * g++.dg/tree-ssa/pr61034.C: Set early-inlining-insns-O2=14. * g++.dg/tree-ssa/pr8781.C: Likewise. * g++.dg/warn/Wstringop-truncation-1.C: Likewise. * gcc.dg/ipa/pr63416.c: likewise. * gcc.dg/vect/pr66142.c: Likewise. * gcc.dg/tree-ssa/ssa-thread-12.c: Mark compure_idf inline. From-SVN: r276416 --- gcc/ChangeLog | 8 ++++++++ gcc/doc/invoke.texi | 8 ++++++++ gcc/ipa-inline.c | 22 ++++++++++++++-------- gcc/params.def | 6 +++++- gcc/testsuite/ChangeLog | 9 +++++++++ gcc/testsuite/g++.dg/tree-ssa/pr61034.C | 2 +- gcc/testsuite/g++.dg/tree-ssa/pr8781.C | 2 +- gcc/testsuite/g++.dg/warn/Wstringop-truncation-1.C | 2 +- gcc/testsuite/gcc.dg/ipa/pr63416.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c | 2 +- gcc/testsuite/gcc.dg/vect/pr66142.c | 2 +- 11 files changed, 50 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb4de20ab16..b4c4292c299 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-10-01 Jan Hubicka <hubicka(a)ucw.cz> + + * doc/invoke.texi (early-inlining-insns-O2): Document. + (early-inlining-insns): Update. + * params.def (early-inlining-insns-O2): New bound. + (early-inlining-insns): Update docs. + * ipa-inline.c (want_early_inline_function_p): Use new bound. + 2019-10-01 Oleg Endo <olegendo(a)gcc.gnu.org> PR target/88562 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 83016a5a8ee..4281ee7c614 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -11291,9 +11291,17 @@ recursion depth can be guessed from the probability that function recurses via a given call expression. This parameter limits inlining only to call expressions whose probability exceeds the given threshold (in percents). +@item early-inlining-insns-O2 +Specify growth that the early inliner can make. In effect it increases +the amount of inlining for code having a large abstraction penalty. +This is applied to functions compiled with @option{-O1} or @option{-O2} +optimization levels. + @item early-inlining-insns Specify growth that the early inliner can make. In effect it increases the amount of inlining for code having a large abstraction penalty. +This is applied to functions compiled with @option{-O3} or @option{-Ofast} +optimization levels. @item max-early-inliner-iterations Limit of iterations of the early inliner. This basically bounds diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index b62d280eb25..c8689c7d9a8 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -641,6 +641,10 @@ want_early_inline_function_p (struct cgraph_edge *e) { int growth = estimate_edge_growth (e); int n; + int early_inlining_insns = opt_for_fn (e->caller->decl, optimize) >= 3 + ? PARAM_VALUE (PARAM_EARLY_INLINING_INSNS) + : PARAM_VALUE (PARAM_EARLY_INLINING_INSNS_O2); + if (growth <= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE)) ; @@ -654,26 +658,28 @@ want_early_inline_function_p (struct cgraph_edge *e) growth); want_inline = false; } - else if (growth > PARAM_VALUE (PARAM_EARLY_INLINING_INSNS)) + else if (growth > early_inlining_insns) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt, " will not early inline: %C->%C, " - "growth %i exceeds --param early-inlining-insns\n", - e->caller, callee, - growth); + "growth %i exceeds --param early-inlining-insns%s\n", + e->caller, callee, growth, + opt_for_fn (e->caller->decl, optimize) >= 3 + ? "" : "-O2"); want_inline = false; } else if ((n = num_calls (callee)) != 0 - && growth * (n + 1) > PARAM_VALUE (PARAM_EARLY_INLINING_INSNS)) + && growth * (n + 1) > early_inlining_insns) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt, " will not early inline: %C->%C, " - "growth %i exceeds --param early-inlining-insns " + "growth %i exceeds --param early-inlining-insns%s " "divided by number of calls\n", - e->caller, callee, - growth); + e->caller, callee, growth, + opt_for_fn (e->caller->decl, optimize) >= 3 + ? "" : "-O2"); want_inline = false; } } diff --git a/gcc/params.def b/gcc/params.def index d2d957fc6b1..0acf29b6c4d 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -233,8 +233,12 @@ DEFPARAM(PARAM_IPCP_UNIT_GROWTH, 10, 0, 0) DEFPARAM(PARAM_EARLY_INLINING_INSNS, "early-inlining-insns", - "Maximal estimated growth of function body caused by early inlining of single call.", + "Maximal estimated growth of function body caused by early inlining of single call with -O3 and -Ofast.", 14, 0, 0) +DEFPARAM(PARAM_EARLY_INLINING_INSNS_O2, + "early-inlining-insns-O2", + "Maximal estimated growth of function body caused by early inlining of single call with -O1 and -O2.", + 6, 0, 0) DEFPARAM(PARAM_LARGE_STACK_FRAME, "large-stack-frame", "The size of stack frame to be considered large.", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index df6105f3d13..0dcaf4b6292 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2019-10-01 Jan Hubicka <hubicka(a)ucw.cz> + + * g++.dg/tree-ssa/pr61034.C: Set early-inlining-insns-O2=14. + * g++.dg/tree-ssa/pr8781.C: Likewise. + * g++.dg/warn/Wstringop-truncation-1.C: Likewise. + * gcc.dg/ipa/pr63416.c: likewise. + * gcc.dg/vect/pr66142.c: Likewise. + * gcc.dg/tree-ssa/ssa-thread-12.c: Mark compure_idf inline. + 2019-10-01 Jakub Jelinek <jakub(a)redhat.com> PR c++/91925 diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C index 870b2372166..2e3dfecacb4 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks" } +// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns-O2=14" } #define assume(x) if(!(x))__builtin_unreachable() diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr8781.C b/gcc/testsuite/g++.dg/tree-ssa/pr8781.C index 1f115b2b26d..5bc1ef03520 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr8781.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr8781.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1" } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1 --param early-inlining-insns-O2=14" } */ int f(); diff --git a/gcc/testsuite/g++.dg/warn/Wstringop-truncation-1.C b/gcc/testsuite/g++.dg/warn/Wstringop-truncation-1.C index 83066019772..49dde0a65ba 100644 --- a/gcc/testsuite/g++.dg/warn/Wstringop-truncation-1.C +++ b/gcc/testsuite/g++.dg/warn/Wstringop-truncation-1.C @@ -1,7 +1,7 @@ /* PR/tree-optimization/84480 - bogus -Wstringop-truncation despite assignment with an inlined string literal { dg-do compile } - { dg-options "-O2 -Wstringop-truncation" } */ + { dg-options "-O2 -Wstringop-truncation --param early-inlining-insns-O2=14" } */ #include <string.h> diff --git a/gcc/testsuite/gcc.dg/ipa/pr63416.c b/gcc/testsuite/gcc.dg/ipa/pr63416.c index b5374c51fe9..5873954fba3 100644 --- a/gcc/testsuite/gcc.dg/ipa/pr63416.c +++ b/gcc/testsuite/gcc.dg/ipa/pr63416.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized --param early-inlining-insns-O2=14" } */ #define _UNUSED_ __attribute__((__unused__)) typedef int TEST_F30 (int *v); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c index 67526762f2c..216de23d791 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c @@ -56,7 +56,7 @@ bmp_iter_and_compl (bitmap_iterator * bi, unsigned *bit_no) } extern int VEC_int_base_length (VEC_int_base *); -bitmap +inline bitmap compute_idf (bitmap def_blocks, bitmap_head * dfs) { bitmap_iterator bi; diff --git a/gcc/testsuite/gcc.dg/vect/pr66142.c b/gcc/testsuite/gcc.dg/vect/pr66142.c index 8c79f290767..a0316f1f01e 100644 --- a/gcc/testsuite/gcc.dg/vect/pr66142.c +++ b/gcc/testsuite/gcc.dg/vect/pr66142.c @@ -1,6 +1,6 @@ /* PR middle-end/66142 */ /* { dg-do compile } */ -/* { dg-additional-options "-ffast-math -fopenmp-simd" } */ +/* { dg-additional-options "-ffast-math -fopenmp-simd --param early-inlining-insns-O2=14" } */ /* { dg-additional-options "-mavx" { target avx_runtime } } */ struct A { float x, y; }; </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_bmk_tk1/gnu-master-arm-spec2k6-O3 - Build # 37 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *gcc* in CI configuration tcwg_bmk_gnu_tk1/gnu-master-arm-spec2k6-O3. So far, this commit has regressed CI configurations: - tcwg_bmk_gnu_tk1/gnu-master-arm-spec2k6-O3 Culprit: <cut> commit 5b759cdcb7f863520346e5bf63fcf1d3746c2cc3 Author: Jason Merrill <jason(a)redhat.com> Date: Sat Jul 10 05:45:02 2021 -0400 c++: pretty-print TYPE_PACK_EXPANSION better gcc/cp/ChangeLog: * ptree.c (cxx_print_type) [TYPE_PACK_EXPANSION]: Also print PACK_EXPANSION_PATTERN. </cut> Results regressed to (for first_bad == 5b759cdcb7f863520346e5bf63fcf1d3746c2cc3) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer: -5 # true: 0 # benchmark -- -O3_marm artifacts/build-5b759cdcb7f863520346e5bf63fcf1d3746c2cc3/results_id: 1 # 483.xalancbmk,[.] _ZN11xercesc_2_510ValueStore13isDuplicateOf regressed by 111 from (for last_good == 4c4249b71de3b15ba1e176ce90a57fb7bc54b917) # reset_artifacts: -10 # build_abe binutils: -9 # build_abe stage1 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer: -8 # build_abe linux: -7 # build_abe glibc: -6 # build_abe stage2 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer: -5 # true: 0 # benchmark -- -O3_marm artifacts/build-4c4249b71de3b15ba1e176ce90a57fb7bc54b917/results_id: 1 Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
Results ID of last_good: tk1_32/tcwg_bmk_gnu_tk1/bisect-gnu-master-arm-spec2k6-O3/2632 Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
Results ID of first_bad: tk1_32/tcwg_bmk_gnu_tk1/bisect-gnu-master-arm-spec2k6-O3/2639 Build top page/logs:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
Configuration details: Reproduce builds: <cut> mkdir investigate-gcc-5b759cdcb7f863520346e5bf63fcf1d3746c2cc3 cd investigate-gcc-5b759cdcb7f863520346e5bf63fcf1d3746c2cc3 git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/ cd gcc # Reproduce first_bad build git checkout --detach 5b759cdcb7f863520346e5bf63fcf1d3746c2cc3 ../artifacts/test.sh # Reproduce last_good build git checkout --detach 4c4249b71de3b15ba1e176ce90a57fb7bc54b917 ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
Build log:
https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-master-ar…
Full commit (up to 1000 lines): <cut> commit 5b759cdcb7f863520346e5bf63fcf1d3746c2cc3 Author: Jason Merrill <jason(a)redhat.com> Date: Sat Jul 10 05:45:02 2021 -0400 c++: pretty-print TYPE_PACK_EXPANSION better gcc/cp/ChangeLog: * ptree.c (cxx_print_type) [TYPE_PACK_EXPANSION]: Also print PACK_EXPANSION_PATTERN. --- gcc/cp/ptree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 33b73fb24b6..7f140f5f06b 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -171,6 +171,7 @@ cxx_print_type (FILE *file, tree node, int indent) return; case TYPE_PACK_EXPANSION: + print_node (file, "pattern", PACK_EXPANSION_PATTERN (node), indent + 4); print_node (file, "args", PACK_EXPANSION_EXTRA_ARGS (node), indent + 4); return; </cut>
3 years, 3 months
1
0
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_kernel/llvm-release-arm-stable-allyesconfig - Build # 4 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *linux* in CI configuration tcwg_kernel/llvm-release-arm-stable-allyesconfig. So far, this commit has regressed CI configurations: - tcwg_kernel/llvm-release-arm-stable-allyesconfig Culprit: <cut> commit 341db343768bc44f3512facc464021730d64071c Author: Linus Walleij <linus.walleij(a)linaro.org> Date: Sun May 23 00:50:39 2021 +0200 power: supply: ab8500: Move to componentized binding [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ] The driver has problems with the different components of the charging code racing with each other to probe(). This results in all four subdrivers populating battery information to ascertain that it is populated for their own needs for example. Fix this by using component probing and thus expressing to the kernel that these are dependent components. The probes can happen in any order and will only acquire resources such as state container, regulators and interrupts and initialize the data structures, but no execution happens until the .bind() callback is called. The charging driver is the main component and binds first, then bind in order the three subcomponents: ab8500-fg, ab8500-btemp and ab8500-chargalg. Do some housekeeping while we are moving the code around. Like use devm_* for IRQs so as to cut down on some boilerplate. Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel(a)collabora.com> Signed-off-by: Sasha Levin <sashal(a)kernel.org> </cut> Results regressed to (for first_bad == 341db343768bc44f3512facc464021730d64071c) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 19634 # First few build errors in logs: # 00:03:07 drivers/power/supply/ab8500_fg.c:3061:32: error: use of undeclared identifier 'np' # 00:03:08 make[3]: *** [drivers/power/supply/ab8500_fg.o] Error 1 # 00:03:10 make[2]: *** [drivers/power/supply] Error 2 # 00:03:10 make[1]: *** [drivers/power] Error 2 # 00:04:05 make: *** [drivers] Error 2 from (for last_good == dc72a15859b2e604abb8a4bff123fbac8a0be92a) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 19722 # linux build successful: all Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
Build top page/logs:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
Configuration details: Reproduce builds: <cut> mkdir investigate-linux-341db343768bc44f3512facc464021730d64071c cd investigate-linux-341db343768bc44f3512facc464021730d64071c git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /linux/ ./ ./bisect/baseline/ cd linux # Reproduce first_bad build git checkout --detach 341db343768bc44f3512facc464021730d64071c ../artifacts/test.sh # Reproduce last_good build git checkout --detach dc72a15859b2e604abb8a4bff123fbac8a0be92a ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
Build log:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-arm-stable-a…
Full commit (up to 1000 lines): <cut> commit 341db343768bc44f3512facc464021730d64071c Author: Linus Walleij <linus.walleij(a)linaro.org> Date: Sun May 23 00:50:39 2021 +0200 power: supply: ab8500: Move to componentized binding [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ] The driver has problems with the different components of the charging code racing with each other to probe(). This results in all four subdrivers populating battery information to ascertain that it is populated for their own needs for example. Fix this by using component probing and thus expressing to the kernel that these are dependent components. The probes can happen in any order and will only acquire resources such as state container, regulators and interrupts and initialize the data structures, but no execution happens until the .bind() callback is called. The charging driver is the main component and binds first, then bind in order the three subcomponents: ab8500-fg, ab8500-btemp and ab8500-chargalg. Do some housekeeping while we are moving the code around. Like use devm_* for IRQs so as to cut down on some boilerplate. Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel(a)collabora.com> Signed-off-by: Sasha Levin <sashal(a)kernel.org> --- drivers/power/supply/ab8500-bm.h | 4 + drivers/power/supply/ab8500_btemp.c | 118 +++++------- drivers/power/supply/ab8500_charger.c | 339 +++++++++++++++++++-------------- drivers/power/supply/ab8500_fg.c | 136 +++++++------ drivers/power/supply/abx500_chargalg.c | 116 ++++++----- 5 files changed, 379 insertions(+), 334 deletions(-) diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h index 41c69a4f2a1f..012595a9d269 100644 --- a/drivers/power/supply/ab8500-bm.h +++ b/drivers/power/supply/ab8500-bm.h @@ -730,4 +730,8 @@ int ab8500_bm_of_probe(struct device *dev, struct device_node *np, struct abx500_bm_data *bm); +extern struct platform_driver ab8500_fg_driver; +extern struct platform_driver ab8500_btemp_driver; +extern struct platform_driver abx500_chargalg_driver; + #endif /* _AB8500_CHARGER_H_ */ diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index fdfcd59fc43e..3598b5a748e7 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> @@ -932,26 +933,6 @@ static int __maybe_unused ab8500_btemp_suspend(struct device *dev) return 0; } -static int ab8500_btemp_remove(struct platform_device *pdev) -{ - struct ab8500_btemp *di = platform_get_drvdata(pdev); - int i, irq; - - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } - - /* Delete the work queue */ - destroy_workqueue(di->btemp_wq); - - flush_scheduled_work(); - power_supply_unregister(di->btemp_psy); - - return 0; -} - static char *supply_interface[] = { "ab8500_chargalg", "ab8500_fg", @@ -966,6 +947,40 @@ static const struct power_supply_desc ab8500_btemp_desc = { .external_power_changed = ab8500_btemp_external_power_changed, }; +static int ab8500_btemp_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Create a work queue for the btemp */ + di->btemp_wq = + alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); + if (di->btemp_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Kick off periodic temperature measurements */ + ab8500_btemp_periodic(di, true); + + return 0; +} + +static void ab8500_btemp_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Delete the work queue */ + destroy_workqueue(di->btemp_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_btemp_component_ops = { + .bind = ab8500_btemp_bind, + .unbind = ab8500_btemp_unbind, +}; + static int ab8500_btemp_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1011,14 +1026,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); psy_cfg.drv_data = di; - /* Create a work queue for the btemp */ - di->btemp_wq = - alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); - if (di->btemp_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for measuring temperature periodically */ INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, ab8500_btemp_periodic_work); @@ -1031,7 +1038,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) AB8500_BTEMP_HIGH_TH, &val); if (ret < 0) { dev_err(dev, "%s ab8500 read failed\n", __func__); - goto free_btemp_wq; + return ret; } switch (val) { case BTEMP_HIGH_TH_57_0: @@ -1050,30 +1057,28 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } /* Register BTEMP power supply class */ - di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc, - &psy_cfg); + di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc, + &psy_cfg); if (IS_ERR(di->btemp_psy)) { dev_err(dev, "failed to register BTEMP psy\n"); - ret = PTR_ERR(di->btemp_psy); - goto free_btemp_wq; + return PTR_ERR(di->btemp_psy); } /* Register interrupts */ for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_btemp_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_btemp_irq[i].name, di); if (ret) { dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_btemp_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_btemp_irq[i].name, irq, ret); @@ -1081,23 +1086,16 @@ static int ab8500_btemp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, di); - /* Kick off periodic temperature measurements */ - ab8500_btemp_periodic(di, true); list_add_tail(&di->node, &ab8500_btemp_list); - return ret; + return component_add(dev, &ab8500_btemp_component_ops); +} -free_irq: - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } +static int ab8500_btemp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &ab8500_btemp_component_ops); - power_supply_unregister(di->btemp_psy); -free_btemp_wq: - destroy_workqueue(di->btemp_wq); - return ret; + return 0; } static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); @@ -1107,7 +1105,7 @@ static const struct of_device_id ab8500_btemp_match[] = { { }, }; -static struct platform_driver ab8500_btemp_driver = { +struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = ab8500_btemp_remove, .driver = { @@ -1116,20 +1114,6 @@ static struct platform_driver ab8500_btemp_driver = { .pm = &ab8500_btemp_pm_ops, }, }; - -static int __init ab8500_btemp_init(void) -{ - return platform_driver_register(&ab8500_btemp_driver); -} - -static void __exit ab8500_btemp_exit(void) -{ - platform_driver_unregister(&ab8500_btemp_driver); -} - -device_initcall(ab8500_btemp_init); -module_exit(ab8500_btemp_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); MODULE_ALIAS("platform:ab8500-btemp"); diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index a9be10eb2c22..af32cfae9f19 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/notifier.h> @@ -3276,10 +3277,74 @@ static struct notifier_block charger_nb = { .notifier_call = ab8500_external_charger_prepare, }; -static int ab8500_charger_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static const struct power_supply_desc ab8500_ac_chg_desc = { + .name = "ab8500_ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = ab8500_charger_ac_props, + .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), + .get_property = ab8500_charger_ac_get_property, +}; + +static const struct power_supply_desc ab8500_usb_chg_desc = { + .name = "ab8500_usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = ab8500_charger_usb_props, + .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), + .get_property = ab8500_charger_usb_get_property, +}; + +static int ab8500_charger_bind(struct device *dev) { - struct ab8500_charger *di = platform_get_drvdata(pdev); - int i, irq, ret; + struct ab8500_charger *di = dev_get_drvdata(dev); + int ch_stat; + int ret; + + /* Create a work queue for the charger */ + di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", + WQ_MEM_RECLAIM); + if (di->charger_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + ch_stat = ab8500_charger_detect_chargers(di, false); + + if (ch_stat & AC_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->ac_charger_attached_work, + HZ); + } + if (ch_stat & USB_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->usb_charger_attached_work, + HZ); + di->vbus_detected = true; + di->vbus_detected_start = true; + queue_work(di->charger_wq, + &di->detect_usb_type_work); + } + + ret = component_bind_all(dev, di); + if (ret) { + dev_err(dev, "can't bind component devices\n"); + return ret; + } + + return 0; +} + +static void ab8500_charger_unbind(struct device *dev) +{ + struct ab8500_charger *di = dev_get_drvdata(dev); + int ret; /* Disable AC charging */ ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); @@ -3287,68 +3352,47 @@ static int ab8500_charger_remove(struct platform_device *pdev) /* Disable USB charging */ ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } - /* Backup battery voltage and current disable */ ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); if (ret < 0) dev_err(di->dev, "%s mask and set failed\n", __func__); - usb_unregister_notifier(di->usb_phy, &di->nb); - usb_put_phy(di->usb_phy); - /* Delete the work queue */ destroy_workqueue(di->charger_wq); - /* Unregister external charger enable notifier */ - if (!di->ac_chg.enabled) - blocking_notifier_chain_unregister( - &charger_notifier_list, &charger_nb); - flush_scheduled_work(); - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); - - if (di->ac_chg.enabled && !di->ac_chg.external) - power_supply_unregister(di->ac_chg.psy); - return 0; + /* Unbind fg, btemp, algorithm */ + component_unbind_all(dev, di); } -static char *supply_interface[] = { - "ab8500_chargalg", - "ab8500_fg", - "ab8500_btemp", +static const struct component_master_ops ab8500_charger_comp_ops = { + .bind = ab8500_charger_bind, + .unbind = ab8500_charger_unbind, }; -static const struct power_supply_desc ab8500_ac_chg_desc = { - .name = "ab8500_ac", - .type = POWER_SUPPLY_TYPE_MAINS, - .properties = ab8500_charger_ac_props, - .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), - .get_property = ab8500_charger_ac_get_property, +static struct platform_driver *const ab8500_charger_component_drivers[] = { + &ab8500_fg_driver, + &ab8500_btemp_driver, + &abx500_chargalg_driver, }; -static const struct power_supply_desc ab8500_usb_chg_desc = { - .name = "ab8500_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = ab8500_charger_usb_props, - .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), - .get_property = ab8500_charger_usb_get_property, -}; +static int ab8500_charger_compare_dev(struct device *dev, void *data) +{ + return dev == data; +} static int ab8500_charger_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct component_match *match = NULL; struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; struct ab8500_charger *di; - int irq, i, charger_status, ret = 0, ch_stat; - struct device *dev = &pdev->dev; + int charger_status; + int i, irq; + int ret; di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); if (!di) @@ -3393,6 +3437,38 @@ static int ab8500_charger_probe(struct platform_device *pdev) return ret; } + /* + * VDD ADC supply needs to be enabled from this driver when there + * is a charger connected to avoid erroneous BTEMP_HIGH/LOW + * interrupts during charging + */ + di->regu = devm_regulator_get(dev, "vddadc"); + if (IS_ERR(di->regu)) { + ret = PTR_ERR(di->regu); + dev_err(dev, "failed to get vddadc regulator\n"); + return ret; + } + + /* Request interrupts */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { + irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, + irq, NULL, ab8500_charger_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_charger_irq[i].name, di); + + if (ret != 0) { + dev_err(dev, "failed to request %s IRQ %d: %d\n" + , ab8500_charger_irq[i].name, irq, ret); + return ret; + } + dev_dbg(dev, "Requested %s IRQ %d: %d\n", + ab8500_charger_irq[i].name, irq, ret); + } + /* initialize lock */ spin_lock_init(&di->usb_state.usb_lock); mutex_init(&di->usb_ipt_crnt_lock); @@ -3422,11 +3498,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->ac_chg.enabled = di->bm->ac_enabled; di->ac_chg.external = false; - /*notifier for external charger enabling*/ - if (!di->ac_chg.enabled) - blocking_notifier_chain_register( - &charger_notifier_list, &charger_nb); - /* USB supply */ /* ux500_charger sub-class */ di->usb_chg.ops.enable = &ab8500_charger_usb_en; @@ -3442,14 +3513,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->usb_chg.external = false; di->usb_state.usb_current = -1; - /* Create a work queue for the charger */ - di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", - WQ_MEM_RECLAIM); - if (di->charger_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - mutex_init(&di->charger_attached_mutex); /* Init work for HW failure check */ @@ -3500,63 +3563,36 @@ static int ab8500_charger_probe(struct platform_device *pdev) INIT_WORK(&di->check_usb_thermal_prot_work, ab8500_charger_check_usb_thermal_prot_work); - /* - * VDD ADC supply needs to be enabled from this driver when there - * is a charger connected to avoid erroneous BTEMP_HIGH/LOW - * interrupts during charging - */ - di->regu = devm_regulator_get(dev, "vddadc"); - if (IS_ERR(di->regu)) { - ret = PTR_ERR(di->regu); - dev_err(dev, "failed to get vddadc regulator\n"); - goto free_charger_wq; - } - /* Initialize OVV, and other registers */ ret = ab8500_charger_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize ABB registers\n"); - goto free_charger_wq; + return ret; } /* Register AC charger class */ if (di->ac_chg.enabled) { - di->ac_chg.psy = power_supply_register(dev, + di->ac_chg.psy = devm_power_supply_register(dev, &ab8500_ac_chg_desc, &ac_psy_cfg); if (IS_ERR(di->ac_chg.psy)) { dev_err(dev, "failed to register AC charger\n"); - ret = PTR_ERR(di->ac_chg.psy); - goto free_charger_wq; + return PTR_ERR(di->ac_chg.psy); } } /* Register USB charger class */ if (di->usb_chg.enabled) { - di->usb_chg.psy = power_supply_register(dev, + di->usb_chg.psy = devm_power_supply_register(dev, &ab8500_usb_chg_desc, &usb_psy_cfg); if (IS_ERR(di->usb_chg.psy)) { dev_err(dev, "failed to register USB charger\n"); - ret = PTR_ERR(di->usb_chg.psy); - goto free_ac; + return PTR_ERR(di->usb_chg.psy); } } - di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(di->usb_phy)) { - dev_err(dev, "failed to get usb transceiver\n"); - ret = -EINVAL; - goto free_usb; - } - di->nb.notifier_call = ab8500_charger_usb_notifier_call; - ret = usb_register_notifier(di->usb_phy, &di->nb); - if (ret) { - dev_err(dev, "failed to register usb notifier\n"); - goto put_usb_phy; - } - /* Identify the connected charger types during startup */ charger_status = ab8500_charger_detect_chargers(di, true); if (charger_status & AC_PW_CONN) { @@ -3566,78 +3602,86 @@ static int ab8500_charger_probe(struct platform_device *pdev) sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); } - if (charger_status & USB_PW_CONN) { - di->vbus_detected = true; - di->vbus_detected_start = true; - queue_work(di->charger_wq, - &di->detect_usb_type_work); - } - - /* Register interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + platform_set_drvdata(pdev, di); - ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_charger_irq[i].name, di); + /* Create something that will match the subdrivers when we bind */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) { + struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver; + struct device *p = NULL, *d; - if (ret != 0) { - dev_err(dev, "failed to request %s IRQ %d: %d\n" - , ab8500_charger_irq[i].name, irq, ret); - goto free_irq; + while ((d = platform_find_device_by_driver(p, drv))) { + put_device(p); + component_match_add(dev, &match, + ab8500_charger_compare_dev, d); + p = d; } - dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_charger_irq[i].name, irq, ret); + put_device(p); + } + if (!match) { + dev_err(dev, "no matching components\n"); + return -ENODEV; + } + if (IS_ERR(match)) { + dev_err(dev, "could not create component match\n"); + return PTR_ERR(match); } - platform_set_drvdata(pdev, di); + /* Notifier for external charger enabling */ + if (!di->ac_chg.enabled) + blocking_notifier_chain_register( + &charger_notifier_list, &charger_nb); - mutex_lock(&di->charger_attached_mutex); - ch_stat = ab8500_charger_detect_chargers(di, false); - - if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->ac_charger_attached_work, - HZ); + di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(di->usb_phy)) { + dev_err(dev, "failed to get usb transceiver\n"); + ret = -EINVAL; + goto out_charger_notifier; } - if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->usb_charger_attached_work, - HZ); + di->nb.notifier_call = ab8500_charger_usb_notifier_call; + ret = usb_register_notifier(di->usb_phy, &di->nb); + if (ret) { + dev_err(dev, "failed to register usb notifier\n"); + goto put_usb_phy; } - mutex_unlock(&di->charger_attached_mutex); - return ret; + ret = component_master_add_with_match(&pdev->dev, + &ab8500_charger_comp_ops, + match); + if (ret) { + dev_err(dev, "failed to add component master\n"); + goto free_notifier; + } -free_irq: - usb_unregister_notifier(di->usb_phy, &di->nb); + return 0; - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } +free_notifier: + usb_unregister_notifier(di->usb_phy, &di->nb); put_usb_phy: usb_put_phy(di->usb_phy); -free_usb: - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); -free_ac: - if (di->ac_chg.enabled) - power_supply_unregister(di->ac_chg.psy); -free_charger_wq: - destroy_workqueue(di->charger_wq); +out_charger_notifier: + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); return ret; } +static int ab8500_charger_remove(struct platform_device *pdev) +{ + struct ab8500_charger *di = platform_get_drvdata(pdev); + + component_master_del(&pdev->dev, &ab8500_charger_comp_ops); + + usb_unregister_notifier(di->usb_phy, &di->nb); + usb_put_phy(di->usb_phy); + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); + + return 0; +} + static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); static const struct of_device_id ab8500_charger_match[] = { @@ -3657,15 +3701,24 @@ static struct platform_driver ab8500_charger_driver = { static int __init ab8500_charger_init(void) { + int ret; + + ret = platform_register_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); + if (ret) + return ret; + return platform_driver_register(&ab8500_charger_driver); } static void __exit ab8500_charger_exit(void) { + platform_unregister_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); platform_driver_unregister(&ab8500_charger_driver); } -subsys_initcall_sync(ab8500_charger_init); +module_init(ab8500_charger_init); module_exit(ab8500_charger_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 0c7c01a0d979..acf0f2471c0b 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/component.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -2980,27 +2981,6 @@ static int __maybe_unused ab8500_fg_suspend(struct device *dev) return 0; } -static int ab8500_fg_remove(struct platform_device *pdev) -{ - int ret = 0; - struct ab8500_fg *di = platform_get_drvdata(pdev); - - list_del(&di->node); - - /* Disable coulomb counter */ - ret = ab8500_fg_coulomb_counter(di, false); - if (ret) - dev_err(di->dev, "failed to disable coulomb counter\n"); - - destroy_workqueue(di->fg_wq); - ab8500_fg_sysfs_exit(di); - - flush_scheduled_work(); - ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); - return ret; -} - /* ab8500 fg driver interrupts and their respective isr */ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, @@ -3024,11 +3004,50 @@ static const struct power_supply_desc ab8500_fg_desc = { .external_power_changed = ab8500_fg_external_power_changed, }; +static int ab8500_fg_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + + /* Create a work queue for running the FG algorithm */ + di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); + if (di->fg_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Start the coulomb counter */ + ab8500_fg_coulomb_counter(di, true); + /* Run the FG algorithm */ + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + return 0; +} + +static void ab8500_fg_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + int ret; + + /* Disable coulomb counter */ + ret = ab8500_fg_coulomb_counter(di, false); + if (ret) + dev_err(dev, "failed to disable coulomb counter\n"); + + destroy_workqueue(di->fg_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_fg_component_ops = { + .bind = ab8500_fg_bind, + .unbind = ab8500_fg_unbind, +}; + static int ab8500_fg_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct power_supply_config psy_cfg = {}; struct device *dev = &pdev->dev; + struct power_supply_config psy_cfg = {}; struct ab8500_fg *di; int i, irq; int ret = 0; @@ -3074,13 +3093,6 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); - /* Create a work queue for running the FG algorithm */ - di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); - if (di->fg_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for running the fg algorithm instantly */ INIT_WORK(&di->fg_work, ab8500_fg_instant_work); @@ -3113,7 +3125,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize registers\n"); - goto free_inst_curr_wq; + return ret; } /* Consider battery unknown until we're informed otherwise */ @@ -3121,15 +3133,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->flags.batt_id_received = false; /* Register FG power supply class */ - di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); + di->fg_psy = devm_power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); if (IS_ERR(di->fg_psy)) { dev_err(dev, "failed to register FG psy\n"); - ret = PTR_ERR(di->fg_psy); - goto free_inst_curr_wq; + return PTR_ERR(di->fg_psy); } di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); - ab8500_fg_coulomb_counter(di, true); /* * Initialize completion used to notify completion and start @@ -3141,19 +3151,18 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Register primary interrupt handlers */ for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_fg_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_fg_irq[i].name, di); if (ret != 0) { dev_err(dev, "failed to request %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); @@ -3168,14 +3177,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_sysfs_init(di); if (ret) { dev_err(dev, "failed to create sysfs entry\n"); - goto free_irq; + return ret; } ret = ab8500_fg_sysfs_psy_create_attrs(di); if (ret) { dev_err(dev, "failed to create FG psy\n"); ab8500_fg_sysfs_exit(di); - goto free_irq; + return ret; } /* Calibrate the fg first time */ @@ -3185,24 +3194,21 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Use room temp as default value until we get an update from driver. */ di->bat_temp = 210; - /* Run the FG algorithm */ - queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); - list_add_tail(&di->node, &ab8500_fg_list); - return ret; + return component_add(dev, &ab8500_fg_component_ops); +} -free_irq: - /* We also have to free all registered irqs */ - while (--i >= 0) { - /* Last assignment of i from primary interrupt handlers */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - free_irq(irq, di); - } +static int ab8500_fg_remove(struct platform_device *pdev) +{ + int ret = 0; + struct ab8500_fg *di = platform_get_drvdata(pdev); + + component_del(&pdev->dev, &ab8500_fg_component_ops); + list_del(&di->node); + ab8500_fg_sysfs_exit(di); + ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); -free_inst_curr_wq: - destroy_workqueue(di->fg_wq); return ret; } @@ -3213,7 +3219,7 @@ static const struct of_device_id ab8500_fg_match[] = { { }, }; -static struct platform_driver ab8500_fg_driver = { +struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, .remove = ab8500_fg_remove, .driver = { @@ -3222,20 +3228,6 @@ static struct platform_driver ab8500_fg_driver = { .pm = &ab8500_fg_pm_ops, }, }; - -static int __init ab8500_fg_init(void) -{ - return platform_driver_register(&ab8500_fg_driver); -} - -static void __exit ab8500_fg_exit(void) -{ - platform_driver_unregister(&ab8500_fg_driver); -} - -subsys_initcall_sync(ab8500_fg_init); -module_exit(ab8500_fg_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); MODULE_ALIAS("platform:ab8500-fg"); diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c index f5b792243727..599684ce0e4b 100644 --- a/drivers/power/supply/abx500_chargalg.c +++ b/drivers/power/supply/abx500_chargalg.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/hrtimer.h> #include <linux/interrupt.h> #include <linux/delay.h> @@ -1943,13 +1944,44 @@ static int __maybe_unused abx500_chargalg_suspend(struct device *dev) return 0; } -static int abx500_chargalg_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_fg", +}; + </cut>
3 years, 3 months
4
3
0
0
[CI-NOTIFY]: TCWG Bisect tcwg_kernel/llvm-release-aarch64-next-allmodconfig - Build # 26 - Successful!
by ci_notify@linaro.org
Successfully identified regression in *linux* in CI configuration tcwg_kernel/llvm-release-aarch64-next-allmodconfig. So far, this commit has regressed CI configurations: - tcwg_kernel/llvm-release-aarch64-next-allmodconfig Culprit: <cut> commit 3d463dd5023b5a58b3c37207d65eeb5acbac2be3 Author: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Date: Thu Jul 29 12:40:19 2021 +0200 nfc: fdp: constify several pointers Several functions do not modify pointed data so arguments and local variables can be const for correctness and safety. This allows also making file-scope nci_core_get_config_otp_ram_version array const. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Signed-off-by: David S. Miller <davem(a)davemloft.net> </cut> Results regressed to (for first_bad == 3d463dd5023b5a58b3c37207d65eeb5acbac2be3) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 21802 # First few build errors in logs: # 00:03:45 drivers/nfc/fdp/fdp.c:116:60: error: passing 'const char *' to parameter of type '__u8 *' (aka 'unsigned char *') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers] # 00:03:45 make[3]: *** [drivers/nfc/fdp/fdp.o] Error 1 # 00:03:49 make[2]: *** [drivers/nfc/fdp] Error 2 # 00:04:01 make[1]: *** [drivers/nfc] Error 2 # 00:09:25 make: *** [drivers] Error 2 from (for last_good == c3e26b6dc1b4e3e8f57be4f004b1f2a410c5c468) # reset_artifacts: -10 # build_abe binutils: -9 # build_llvm: -5 # build_abe qemu: -2 # linux_n_obj: 29857 # linux build successful: all # linux boot successful: boot Artifacts of last_good build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
Artifacts of first_bad build:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
Build top page/logs:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
Configuration details: rr[linux_git]="
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git#cb16362…
" Reproduce builds: <cut> mkdir investigate-linux-3d463dd5023b5a58b3c37207d65eeb5acbac2be3 cd investigate-linux-3d463dd5023b5a58b3c37207d65eeb5acbac2be3 git clone
https://git.linaro.org/toolchain/jenkins-scripts
mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
--fail curl -o artifacts/manifests/build-parameters.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
--fail curl -o artifacts/test.sh
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
--fail chmod +x artifacts/test.sh # Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh # Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /linux/ ./ ./bisect/baseline/ cd linux # Reproduce first_bad build git checkout --detach 3d463dd5023b5a58b3c37207d65eeb5acbac2be3 ../artifacts/test.sh # Reproduce last_good build git checkout --detach c3e26b6dc1b4e3e8f57be4f004b1f2a410c5c468 ../artifacts/test.sh cd .. </cut> History of pending regressions and results:
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
Build log:
https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-release-aarch64-next…
Full commit (up to 1000 lines): <cut> commit 3d463dd5023b5a58b3c37207d65eeb5acbac2be3 Author: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Date: Thu Jul 29 12:40:19 2021 +0200 nfc: fdp: constify several pointers Several functions do not modify pointed data so arguments and local variables can be const for correctness and safety. This allows also making file-scope nci_core_get_config_otp_ram_version array const. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski(a)canonical.com> Signed-off-by: David S. Miller <davem(a)davemloft.net> --- drivers/nfc/fdp/fdp.c | 18 +++++++++--------- drivers/nfc/fdp/fdp.h | 2 +- drivers/nfc/fdp/i2c.c | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index 3f5fba922c4d..c6b3334f24c9 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c @@ -52,7 +52,7 @@ struct fdp_nci_info { u32 limited_otp_version; u8 key_index; - u8 *fw_vsc_cfg; + const u8 *fw_vsc_cfg; u8 clock_type; u32 clock_freq; @@ -65,7 +65,7 @@ struct fdp_nci_info { wait_queue_head_t setup_wq; }; -static u8 nci_core_get_config_otp_ram_version[5] = { +static const u8 nci_core_get_config_otp_ram_version[5] = { 0x04, NCI_PARAM_ID_FW_RAM_VERSION, NCI_PARAM_ID_FW_OTP_VERSION, @@ -111,7 +111,7 @@ static inline int fdp_nci_patch_cmd(struct nci_dev *ndev, u8 type) } static inline int fdp_nci_set_production_data(struct nci_dev *ndev, u8 len, - char *data) + const char *data) { return nci_prop_cmd(ndev, NCI_OP_PROP_SET_PDATA_OID, len, data); } @@ -236,7 +236,7 @@ static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) static int fdp_nci_open(struct nci_dev *ndev) { - struct fdp_nci_info *info = nci_get_drvdata(ndev); + const struct fdp_nci_info *info = nci_get_drvdata(ndev); return info->phy_ops->enable(info->phy); } @@ -260,7 +260,7 @@ static int fdp_nci_request_firmware(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; - u8 *data; + const u8 *data; int r; r = request_firmware(&info->ram_patch, FDP_RAM_PATCH_NAME, dev); @@ -269,7 +269,7 @@ static int fdp_nci_request_firmware(struct nci_dev *ndev) return r; } - data = (u8 *) info->ram_patch->data; + data = info->ram_patch->data; info->ram_patch_version = data[FDP_FW_HEADER_SIZE] | (data[FDP_FW_HEADER_SIZE + 1] << 8) | @@ -610,9 +610,9 @@ static int fdp_nci_core_get_config_rsp_packet(struct nci_dev *ndev, { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; - struct nci_core_get_config_rsp *rsp = (void *) skb->data; + const struct nci_core_get_config_rsp *rsp = (void *) skb->data; unsigned int i; - u8 *p; + const u8 *p; if (rsp->status == NCI_STATUS_OK) { @@ -691,7 +691,7 @@ static const struct nci_ops nci_ops = { int fdp_nci_probe(struct fdp_i2c_phy *phy, const struct nfc_phy_ops *phy_ops, struct nci_dev **ndevp, int tx_headroom, int tx_tailroom, u8 clock_type, u32 clock_freq, - u8 *fw_vsc_cfg) + const u8 *fw_vsc_cfg) { struct device *dev = &phy->i2c_dev->dev; struct fdp_nci_info *info; diff --git a/drivers/nfc/fdp/fdp.h b/drivers/nfc/fdp/fdp.h index dc048d4b977e..2e9161a4d7bf 100644 --- a/drivers/nfc/fdp/fdp.h +++ b/drivers/nfc/fdp/fdp.h @@ -23,7 +23,7 @@ struct fdp_i2c_phy { int fdp_nci_probe(struct fdp_i2c_phy *phy, const struct nfc_phy_ops *phy_ops, struct nci_dev **ndev, int tx_headroom, int tx_tailroom, - u8 clock_type, u32 clock_freq, u8 *fw_vsc_cfg); + u8 clock_type, u32 clock_freq, const u8 *fw_vsc_cfg); void fdp_nci_remove(struct nci_dev *ndev); #endif /* __LOCAL_FDP_H_ */ diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c index 98e1876c9468..051c43a2a52f 100644 --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -36,7 +36,7 @@ print_hex_dump(KERN_DEBUG, prefix": ", DUMP_PREFIX_OFFSET, \ 16, 1, (skb)->data, (skb)->len, 0) -static void fdp_nci_i2c_reset(struct fdp_i2c_phy *phy) +static void fdp_nci_i2c_reset(const struct fdp_i2c_phy *phy) { /* Reset RST/WakeUP for at least 100 micro-second */ gpiod_set_value_cansleep(phy->power_gpio, FDP_POWER_OFF); @@ -47,7 +47,7 @@ static void fdp_nci_i2c_reset(struct fdp_i2c_phy *phy) static int fdp_nci_i2c_enable(void *phy_id) { - struct fdp_i2c_phy *phy = phy_id; + const struct fdp_i2c_phy *phy = phy_id; fdp_nci_i2c_reset(phy); @@ -56,7 +56,7 @@ static int fdp_nci_i2c_enable(void *phy_id) static void fdp_nci_i2c_disable(void *phy_id) { - struct fdp_i2c_phy *phy = phy_id; + const struct fdp_i2c_phy *phy = phy_id; fdp_nci_i2c_reset(phy); } </cut>
3 years, 3 months
3
2
0
0
← Newer
1
...
69
70
71
72
73
74
75
...
549
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
Results per page:
10
25
50
100
200