* Re: [PATCH v12 04/13] mfd: Add Ingenic TCU driver
From: Paul Cercueil @ 2019-06-22 12:21 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Ralf Baechle, Paul Burton, James Hogan,
Jonathan Corbet, Daniel Lezcano, Thomas Gleixner,
Michael Turquette, Stephen Boyd, Jason Cooper, Marc Zyngier,
Lee Jones
Cc: Mathieu Malaterre, linux-kernel, devicetree, linux-mips,
linux-doc, linux-clk, od
In-Reply-To: <20190521145141.9813-5-paul@crapouillou.net>
Hi,
I'll make a V13 of this patchset on top of -rc6, any feedback
for this MFD driver? It's been already one month.
Thanks,
-Paul
Le mar. 21 mai 2019 à 16:51, Paul Cercueil <paul@crapouillou.net> a
écrit :
> This driver will provide a regmap that can be retrieved very early in
> the boot process through the API function ingenic_tcu_get_regmap().
>
> Additionally, it will call devm_of_platform_populate() so that all the
> children devices will be probed.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>
> Notes:
> v12: New patch
>
> drivers/mfd/Kconfig | 8 +++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/ingenic-tcu.c | 113
> ++++++++++++++++++++++++++++++++
> include/linux/mfd/ingenic-tcu.h | 8 +++
> 4 files changed, 130 insertions(+)
> create mode 100644 drivers/mfd/ingenic-tcu.c
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 294d9567cc71..a13544474e05 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -494,6 +494,14 @@ config HTC_I2CPLD
> This device provides input and output GPIOs through an I2C
> interface to one or more sub-chips.
>
> +config INGENIC_TCU
> + bool "Ingenic Timer/Counter Unit (TCU) support"
> + depends on MIPS || COMPILE_TEST
> + select REGMAP_MMIO
> + help
> + Say yes here to support the Timer/Counter Unit (TCU) IP present
> + in the JZ47xx SoCs from Ingenic.
> +
> config MFD_INTEL_QUARK_I2C_GPIO
> tristate "Intel Quark MFD I2C GPIO"
> depends on PCI
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 52b1a90ff515..fb89e131ae98 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -180,6 +180,7 @@ obj-$(CONFIG_AB8500_CORE) += ab8500-core.o
> ab8500-sysctrl.o
> obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
> obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
> obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o
> +obj-$(CONFIG_INGENIC_TCU) += ingenic-tcu.o
> obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO) += intel_quark_i2c_gpio.o
> obj-$(CONFIG_LPC_SCH) += lpc_sch.o
> obj-$(CONFIG_LPC_ICH) += lpc_ich.o
> diff --git a/drivers/mfd/ingenic-tcu.c b/drivers/mfd/ingenic-tcu.c
> new file mode 100644
> index 000000000000..6c1d5e4310c1
> --- /dev/null
> +++ b/drivers/mfd/ingenic-tcu.c
> @@ -0,0 +1,113 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * JZ47xx SoCs TCU MFD driver
> + * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net>
> + */
> +
> +#include <linux/mfd/ingenic-tcu.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +struct ingenic_soc_info {
> + unsigned int num_channels;
> +};
> +
> +static struct regmap *tcu_regmap __initdata;
> +
> +static const struct regmap_config ingenic_tcu_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = TCU_REG_OST_CNTHBUF,
> +};
> +
> +static const struct ingenic_soc_info jz4740_soc_info = {
> + .num_channels = 8,
> +};
> +
> +static const struct ingenic_soc_info jz4725b_soc_info = {
> + .num_channels = 6,
> +};
> +
> +static const struct of_device_id ingenic_tcu_of_match[] = {
> + { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
> + { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
> + { .compatible = "ingenic,jz4770-tcu", .data = &jz4740_soc_info, },
> + { }
> +};
> +
> +static struct regmap * __init ingenic_tcu_create_regmap(struct
> device_node *np)
> +{
> + struct resource res;
> + void __iomem *base;
> + struct regmap *map;
> +
> + if (!of_match_node(ingenic_tcu_of_match, np))
> + return ERR_PTR(-EINVAL);
> +
> + base = of_io_request_and_map(np, 0, "TCU");
> + if (IS_ERR(base))
> + return ERR_PTR(PTR_ERR(base));
> +
> + map = regmap_init_mmio(NULL, base, &ingenic_tcu_regmap_config);
> + if (IS_ERR(map))
> + goto err_iounmap;
> +
> + return map;
> +
> +err_iounmap:
> + iounmap(base);
> + of_address_to_resource(np, 0, &res);
> + release_mem_region(res.start, resource_size(&res));
> +
> + return map;
> +}
> +
> +static int __init ingenic_tcu_probe(struct platform_device *pdev)
> +{
> + struct regmap *map = ingenic_tcu_get_regmap(pdev->dev.of_node);
> +
> + platform_set_drvdata(pdev, map);
> +
> + regmap_attach_dev(&pdev->dev, map, &ingenic_tcu_regmap_config);
> +
> + return devm_of_platform_populate(&pdev->dev);
> +}
> +
> +static struct platform_driver ingenic_tcu_driver = {
> + .driver = {
> + .name = "ingenic-tcu",
> + .of_match_table = ingenic_tcu_of_match,
> + },
> +};
> +
> +static int __init ingenic_tcu_platform_init(void)
> +{
> + return platform_driver_probe(&ingenic_tcu_driver,
> + ingenic_tcu_probe);
> +}
> +subsys_initcall(ingenic_tcu_platform_init);
> +
> +struct regmap * __init ingenic_tcu_get_regmap(struct device_node *np)
> +{
> + if (!tcu_regmap)
> + tcu_regmap = ingenic_tcu_create_regmap(np);
> +
> + return tcu_regmap;
> +}
> +
> +bool ingenic_tcu_pwm_can_use_chn(struct device *dev, unsigned int
> channel)
> +{
> + const struct ingenic_soc_info *soc =
> device_get_match_data(dev->parent);
> +
> + /* Enable all TCU channels for PWM use by default except channels
> 0/1 */
> + u32 pwm_channels_mask = GENMASK(soc->num_channels - 1, 2);
> +
> + device_property_read_u32(dev->parent, "ingenic,pwm-channels-mask",
> + &pwm_channels_mask);
> +
> + return !!(pwm_channels_mask & BIT(channel));
> +}
> +EXPORT_SYMBOL_GPL(ingenic_tcu_pwm_can_use_chn);
> diff --git a/include/linux/mfd/ingenic-tcu.h
> b/include/linux/mfd/ingenic-tcu.h
> index 2083fa20821d..21df23916cd2 100644
> --- a/include/linux/mfd/ingenic-tcu.h
> +++ b/include/linux/mfd/ingenic-tcu.h
> @@ -6,6 +6,11 @@
> #define __LINUX_MFD_INGENIC_TCU_H_
>
> #include <linux/bitops.h>
> +#include <linux/init.h>
> +
> +struct device;
> +struct device_node;
> +struct regmap;
>
> #define TCU_REG_WDT_TDR 0x00
> #define TCU_REG_WDT_TCER 0x04
> @@ -53,4 +58,7 @@
> #define TCU_REG_TCNTc(c) (TCU_REG_TCNT0 + ((c) * TCU_CHANNEL_STRIDE))
> #define TCU_REG_TCSRc(c) (TCU_REG_TCSR0 + ((c) * TCU_CHANNEL_STRIDE))
>
> +struct regmap * __init ingenic_tcu_get_regmap(struct device_node
> *np);
> +bool ingenic_tcu_pwm_can_use_chn(struct device *dev, unsigned int
> channel);
> +
> #endif /* __LINUX_MFD_INGENIC_TCU_H_ */
> --
> 2.21.0.593.g511ec345e18
>
^ permalink raw reply
* Re: [PATCH 1/3] Docs: An initial automarkup extension for sphinx
From: Jonathan Corbet @ 2019-06-22 14:43 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-doc, Matthew Wilcox, Jani Nikula, linux-kernel
In-Reply-To: <20190621220046.3de30d9d@coco.lan>
On Fri, 21 Jun 2019 22:00:46 -0300
Mauro Carvalho Chehab <mchehab+samsung@kernel.org> wrote:
> > +#
> > +# The DVB docs create references for these basic system calls, leading
> > +# to lots of confusing links. So just don't link them.
> > +#
> > +Skipfuncs = [ 'open', 'close', 'write' ]
>
> and yeah, of course, if there's something weird, it has to be at
> the media docs :-)
>
> Btw, if I'm not mistaken, we do the same for ioctl.
So that's actually interesting. In, for example,
Documentation/media/uapi/v4l/func-ioctl.rst, you see something that looks
like this:
> .. c:function:: int ioctl( int fd, int request, void *argp )
> :name: v4l2-ioctl
Some digging around didn't turn up any documentation for :name:, but it
seems to prevent ioctl() from going into the list of functions that can be
cross-referenced. I wonder if the same should be done for the others? I
think that would be better than putting a special-case hack into the
toolchain.
> I'm wandering if this could also handle the Documentation/* auto-replace.
I think it's the obvious place for it, yes. Let's make sure I haven't
badly broken anything with the existing change first, though :)
Thanks,
jon
^ permalink raw reply
* Re: [PATCH v12 07/13] clocksource: Add a new timer-ingenic driver
From: Paul Cercueil @ 2019-06-22 12:23 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Ralf Baechle, Paul Burton, James Hogan,
Jonathan Corbet, Daniel Lezcano, Thomas Gleixner,
Michael Turquette, Stephen Boyd, Jason Cooper, Marc Zyngier,
Lee Jones
Cc: Mathieu Malaterre, linux-kernel, devicetree, linux-mips,
linux-doc, linux-clk, od
In-Reply-To: <20190521145141.9813-8-paul@crapouillou.net>
Hi,
I'll make a V13 of this patchset on top of -rc6, any feedback
for this clocksource driver? It's been already one month.
Thanks,
-Paul
Le mar. 21 mai 2019 à 16:51, Paul Cercueil <paul@crapouillou.net> a
écrit :
> This driver handles the TCU (Timer Counter Unit) present on the
> Ingenic
> JZ47xx SoCs, and provides the kernel with a system timer, a
> clocksource
> and a sched_clock.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>
> Notes:
> v2: Use SPDX identifier for the license
>
> v3: - Move documentation to its own patch
> - Search the devicetree for PWM clients, and use all the TCU
> channels that won't be used for PWM
>
> v4: - Add documentation about why we search for PWM clients
> - Verify that the PWM clients are for the TCU PWM driver
>
> v5: Major overhaul. Too many changes to list. Consider it's a new
> patch.
>
> v6: - Add two API functions ingenic_tcu_request_channel and
> ingenic_tcu_release_channel. To be used by the PWM driver to
> request the use of a TCU channel. The driver will now
> dynamically
> move away the system timer or clocksource to a new TCU channel.
> - The system timer now defaults to channel 0, the clocksource now
> defaults to channel 1 and is no more optional. The
> ingenic,timer-channel and ingenic,clocksource-channel
> devicetree
> properties are now gone.
> - Fix round_rate / set_rate not calculating the prescale divider
> the same way. This caused problems when (parent_rate / div)
> would
> give a non-integer result. The behaviour is correct now.
> - The clocksource clock is turned off on suspend now.
>
> v7: Fix section mismatch by using builtin_platform_driver_probe()
>
> v8: - Removed ingenic_tcu_[request,release]_channel, and the
> mechanism
> to dynamically change the TCU channel of the system timer or
> the clocksource.
> - The driver's devicetree node can now have two more children
> nodes, that correspond to the system timer and clocksource.
> For these two, the driver will use the TCU timer that
> correspond to the memory resource supplied in their
> respective node.
>
> v9: - Removed support for clocksource / timer children devicetree
> nodes. Now, we use a property "ingenic,pwm-channels-mask" to
> know which PWM channels are reserved for PWM use and should
> not be used as OS timers.
>
> v10: - Use CLK_SET_RATE_UNGATE instead of CLK_SET_RATE_GATE +
> manually
> un-gating the clock before changing rate. Same for
> re-parenting.
> - Unconditionally create the clocksource and sched_clock even if
> the SoC possesses a OS Timer. That gives the choice back to
> the
> user which clocksource should be selected.
> - Use subsys_initcall() instead of
> builtin_platform_driver_probe().
> The OS Timer driver calls builtin_platform_driver_probe, which
> requires the device to be created before that.
> - Cosmetic cleanups
>
> v11: - Change prototype of exported function
> ingenic_tcu_pwm_can_use_chn(), use a struct device * as first
> argument.
> - Read clocksource using the regmap instead of bypassing it.
> Bypassing the regmap makes sense only for the sched_clock
> where
> the read operation must be as fast as possible.
> - Fix incorrect format in pr_crit() macro
>
> v12: - Clock handling and IRQ handling are gone, and are now
> handled
> in their own driver.
> - Obtain regmap from the ingenic-tcu MFD driver. As a result, we
> cannot bypass the regmap anymore for the sched_clock.
>
> drivers/clocksource/Kconfig | 11 +
> drivers/clocksource/Makefile | 1 +
> drivers/clocksource/ingenic-timer.c | 357
> ++++++++++++++++++++++++++++
> 3 files changed, 369 insertions(+)
> create mode 100644 drivers/clocksource/ingenic-timer.c
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 6bcaa4e2e72c..bb5d5c044341 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -672,4 +672,15 @@ config MILBEAUT_TIMER
> help
> Enables the support for Milbeaut timer driver.
>
> +config INGENIC_TIMER
> + bool "Clocksource/timer using the TCU in Ingenic JZ SoCs"
> + default MACH_INGENIC
> + depends on MIPS || COMPILE_TEST
> + depends on COMMON_CLK
> + select INGENIC_TCU
> + select TIMER_OF
> + select IRQ_DOMAIN
> + help
> + Support for the timer/counter unit of the Ingenic JZ SoCs.
> +
> endmenu
> diff --git a/drivers/clocksource/Makefile
> b/drivers/clocksource/Makefile
> index 236858fa7fbf..553f3c61717a 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -78,6 +78,7 @@ obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
> obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o
> obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
> obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
> +obj-$(CONFIG_INGENIC_TIMER) += ingenic-timer.o
> obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
> obj-$(CONFIG_X86_NUMACHIP) += numachip.o
> obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o
> diff --git a/drivers/clocksource/ingenic-timer.c
> b/drivers/clocksource/ingenic-timer.c
> new file mode 100644
> index 000000000000..9f4df64390f4
> --- /dev/null
> +++ b/drivers/clocksource/ingenic-timer.c
> @@ -0,0 +1,357 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * JZ47xx SoCs TCU IRQ driver
> + * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net>
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/clockchips.h>
> +#include <linux/clocksource.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/ingenic-tcu.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/sched_clock.h>
> +
> +#include <dt-bindings/clock/ingenic,tcu.h>
> +
> +struct ingenic_soc_info {
> + unsigned int num_channels;
> +};
> +
> +struct ingenic_tcu {
> + struct regmap *map;
> + struct clk *timer_clk, *cs_clk;
> +
> + unsigned int timer_channel, cs_channel;
> + struct clock_event_device cevt;
> + struct clocksource cs;
> + char name[4];
> +
> + unsigned long pwm_channels_mask;
> +};
> +
> +static struct ingenic_tcu *ingenic_tcu;
> +
> +static u64 notrace ingenic_tcu_timer_read(void)
> +{
> + struct ingenic_tcu *tcu = ingenic_tcu;
> + unsigned int count;
> +
> + regmap_read(tcu->map, TCU_REG_TCNTc(tcu->cs_channel), &count);
> +
> + return count;
> +}
> +
> +static u64 notrace ingenic_tcu_timer_cs_read(struct clocksource *cs)
> +{
> + return ingenic_tcu_timer_read();
> +}
> +
> +static inline struct ingenic_tcu *to_ingenic_tcu(struct
> clock_event_device *evt)
> +{
> + return container_of(evt, struct ingenic_tcu, cevt);
> +}
> +
> +static int ingenic_tcu_cevt_set_state_shutdown(struct
> clock_event_device *evt)
> +{
> + struct ingenic_tcu *tcu = to_ingenic_tcu(evt);
> +
> + regmap_write(tcu->map, TCU_REG_TECR, BIT(tcu->timer_channel));
> +
> + return 0;
> +}
> +
> +static int ingenic_tcu_cevt_set_next(unsigned long next,
> + struct clock_event_device *evt)
> +{
> + struct ingenic_tcu *tcu = to_ingenic_tcu(evt);
> +
> + if (next > 0xffff)
> + return -EINVAL;
> +
> + regmap_write(tcu->map, TCU_REG_TDFRc(tcu->timer_channel), next);
> + regmap_write(tcu->map, TCU_REG_TCNTc(tcu->timer_channel), 0);
> + regmap_write(tcu->map, TCU_REG_TESR, BIT(tcu->timer_channel));
> +
> + return 0;
> +}
> +
> +static irqreturn_t ingenic_tcu_cevt_cb(int irq, void *dev_id)
> +{
> + struct clock_event_device *evt = dev_id;
> + struct ingenic_tcu *tcu = to_ingenic_tcu(evt);
> +
> + regmap_write(tcu->map, TCU_REG_TECR, BIT(tcu->timer_channel));
> +
> + if (evt->event_handler)
> + evt->event_handler(evt);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static struct clk * __init ingenic_tcu_get_clock(struct device_node
> *np, int id)
> +{
> + struct of_phandle_args args;
> +
> + args.np = np;
> + args.args_count = 1;
> + args.args[0] = id;
> +
> + return of_clk_get_from_provider(&args);
> +}
> +
> +static int __init ingenic_tcu_timer_init(struct device_node *np,
> + struct ingenic_tcu *tcu)
> +{
> + unsigned int timer_virq, channel = tcu->timer_channel;
> + struct irq_domain *domain;
> + unsigned long rate;
> + int err;
> +
> + tcu->timer_clk = ingenic_tcu_get_clock(np, channel);
> + if (IS_ERR(tcu->timer_clk))
> + return PTR_ERR(tcu->timer_clk);
> +
> + err = clk_prepare_enable(tcu->timer_clk);
> + if (err)
> + goto err_clk_put;
> +
> + rate = clk_get_rate(tcu->timer_clk);
> + if (!rate) {
> + err = -EINVAL;
> + goto err_clk_disable;
> + }
> +
> + domain = irq_find_host(np);
> + if (!domain) {
> + err = -ENODEV;
> + goto err_clk_disable;
> + }
> +
> + timer_virq = irq_create_mapping(domain, channel);
> + if (!timer_virq) {
> + err = -EINVAL;
> + goto err_clk_disable;
> + }
> +
> + snprintf(tcu->name, sizeof(tcu->name), "TCU");
> +
> + err = request_irq(timer_virq, ingenic_tcu_cevt_cb, IRQF_TIMER,
> + tcu->name, &tcu->cevt);
> + if (err)
> + goto err_irq_dispose_mapping;
> +
> + tcu->cevt.cpumask = cpumask_of(smp_processor_id());
> + tcu->cevt.features = CLOCK_EVT_FEAT_ONESHOT;
> + tcu->cevt.name = tcu->name;
> + tcu->cevt.rating = 200;
> + tcu->cevt.set_state_shutdown = ingenic_tcu_cevt_set_state_shutdown;
> + tcu->cevt.set_next_event = ingenic_tcu_cevt_set_next;
> +
> + clockevents_config_and_register(&tcu->cevt, rate, 10, 0xffff);
> +
> + return 0;
> +
> +err_irq_dispose_mapping:
> + irq_dispose_mapping(timer_virq);
> +err_clk_disable:
> + clk_disable_unprepare(tcu->timer_clk);
> +err_clk_put:
> + clk_put(tcu->timer_clk);
> + return err;
> +}
> +
> +static int __init ingenic_tcu_clocksource_init(struct device_node
> *np,
> + struct ingenic_tcu *tcu)
> +{
> + unsigned int channel = tcu->cs_channel;
> + struct clocksource *cs = &tcu->cs;
> + unsigned long rate;
> + int err;
> +
> + tcu->cs_clk = ingenic_tcu_get_clock(np, channel);
> + if (IS_ERR(tcu->cs_clk))
> + return PTR_ERR(tcu->cs_clk);
> +
> + err = clk_prepare_enable(tcu->cs_clk);
> + if (err)
> + goto err_clk_put;
> +
> + rate = clk_get_rate(tcu->cs_clk);
> + if (!rate) {
> + err = -EINVAL;
> + goto err_clk_disable;
> + }
> +
> + /* Reset channel */
> + regmap_update_bits(tcu->map, TCU_REG_TCSRc(channel),
> + 0xffff & ~TCU_TCSR_RESERVED_BITS, 0);
> +
> + /* Reset counter */
> + regmap_write(tcu->map, TCU_REG_TDFRc(channel), 0xffff);
> + regmap_write(tcu->map, TCU_REG_TCNTc(channel), 0);
> +
> + /* Enable channel */
> + regmap_write(tcu->map, TCU_REG_TESR, BIT(channel));
> +
> + cs->name = "ingenic-timer";
> + cs->rating = 200;
> + cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
> + cs->mask = CLOCKSOURCE_MASK(16);
> + cs->read = ingenic_tcu_timer_cs_read;
> +
> + err = clocksource_register_hz(cs, rate);
> + if (err)
> + goto err_clk_disable;
> +
> + return 0;
> +
> +err_clk_disable:
> + clk_disable_unprepare(tcu->cs_clk);
> +err_clk_put:
> + clk_put(tcu->cs_clk);
> + return err;
> +}
> +
> +static const struct ingenic_soc_info jz4740_soc_info = {
> + .num_channels = 8,
> +};
> +
> +static const struct ingenic_soc_info jz4725b_soc_info = {
> + .num_channels = 6,
> +};
> +
> +static const struct of_device_id ingenic_tcu_of_match[] = {
> + { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
> + { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
> + { .compatible = "ingenic,jz4770-tcu", .data = &jz4740_soc_info, },
> + { }
> +};
> +
> +static int __init ingenic_tcu_init(struct device_node *np)
> +{
> + const struct of_device_id *id = of_match_node(ingenic_tcu_of_match,
> np);
> + const struct ingenic_soc_info *soc_info = id->data;
> + struct ingenic_tcu *tcu;
> + struct regmap *map;
> + long rate;
> + int ret;
> +
> + of_node_clear_flag(np, OF_POPULATED);
> +
> + map = ingenic_tcu_get_regmap(np);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> +
> + tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
> + if (!tcu)
> + return -ENOMEM;
> +
> + /* Enable all TCU channels for PWM use by default except channels
> 0/1 */
> + tcu->pwm_channels_mask = GENMASK(soc_info->num_channels - 1, 2);
> + of_property_read_u32(np, "ingenic,pwm-channels-mask",
> + (u32 *)&tcu->pwm_channels_mask);
> +
> + /* Verify that we have at least two free channels */
> + if (hweight8(tcu->pwm_channels_mask) > soc_info->num_channels - 2) {
> + pr_crit("%s: Invalid PWM channel mask: 0x%02lx\n", __func__,
> + tcu->pwm_channels_mask);
> + ret = -EINVAL;
> + goto err_free_ingenic_tcu;
> + }
> +
> + tcu->map = map;
> + ingenic_tcu = tcu;
> +
> + tcu->timer_channel = find_first_zero_bit(&tcu->pwm_channels_mask,
> + soc_info->num_channels);
> + tcu->cs_channel = find_next_zero_bit(&tcu->pwm_channels_mask,
> + soc_info->num_channels,
> + tcu->timer_channel + 1);
> +
> + ret = ingenic_tcu_clocksource_init(np, tcu);
> + if (ret) {
> + pr_crit("%s: Unable to init clocksource: %i\n", __func__, ret);
> + goto err_free_ingenic_tcu;
> + }
> +
> + ret = ingenic_tcu_timer_init(np, tcu);
> + if (ret)
> + goto err_tcu_clocksource_cleanup;
> +
> + /* Register the sched_clock at the end as there's no way to undo it
> */
> + rate = clk_get_rate(tcu->cs_clk);
> + sched_clock_register(ingenic_tcu_timer_read, 16, rate);
> +
> + return 0;
> +
> +err_tcu_clocksource_cleanup:
> + clocksource_unregister(&tcu->cs);
> + clk_disable_unprepare(tcu->cs_clk);
> + clk_put(tcu->cs_clk);
> +err_free_ingenic_tcu:
> + kfree(tcu);
> + return ret;
> +}
> +
> +TIMER_OF_DECLARE(jz4740_tcu_intc, "ingenic,jz4740-tcu",
> ingenic_tcu_init);
> +TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu",
> ingenic_tcu_init);
> +TIMER_OF_DECLARE(jz4770_tcu_intc, "ingenic,jz4770-tcu",
> ingenic_tcu_init);
> +
> +
> +static int __init ingenic_tcu_probe(struct platform_device *pdev)
> +{
> + platform_set_drvdata(pdev, ingenic_tcu);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused ingenic_tcu_suspend(struct device *dev)
> +{
> + struct ingenic_tcu *tcu = dev_get_drvdata(dev);
> +
> + clk_disable(tcu->cs_clk);
> + clk_disable(tcu->timer_clk);
> + return 0;
> +}
> +
> +static int __maybe_unused ingenic_tcu_resume(struct device *dev)
> +{
> + struct ingenic_tcu *tcu = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = clk_enable(tcu->timer_clk);
> + if (ret)
> + return ret;
> +
> + ret = clk_enable(tcu->cs_clk);
> + if (ret) {
> + clk_disable(tcu->timer_clk);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops __maybe_unused ingenic_tcu_pm_ops = {
> + /* _noirq: We want the TCU clocks to be gated last / ungated first
> */
> + .suspend_noirq = ingenic_tcu_suspend,
> + .resume_noirq = ingenic_tcu_resume,
> +};
> +
> +static struct platform_driver ingenic_tcu_driver = {
> + .driver = {
> + .name = "ingenic-tcu-timer",
> +#ifdef CONFIG_PM_SLEEP
> + .pm = &ingenic_tcu_pm_ops,
> +#endif
> + .of_match_table = ingenic_tcu_of_match,
> + },
> +};
> +builtin_platform_driver_probe(ingenic_tcu_driver, ingenic_tcu_probe);
> --
> 2.21.0.593.g511ec345e18
>
^ permalink raw reply
* Re: [PATCH v12 06/13] irqchip: Add irq-ingenic-tcu driver
From: Paul Cercueil @ 2019-06-22 12:22 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Ralf Baechle, Paul Burton, James Hogan,
Jonathan Corbet, Daniel Lezcano, Thomas Gleixner,
Michael Turquette, Stephen Boyd, Jason Cooper, Marc Zyngier,
Lee Jones
Cc: Mathieu Malaterre, linux-kernel, devicetree, linux-mips,
linux-doc, linux-clk, od
In-Reply-To: <20190521145141.9813-7-paul@crapouillou.net>
Hi,
I'll make a V13 of this patchset on top of -rc6, any feedback
for this IRQ driver? It's been already one month.
Thanks,
-Paul
Le mar. 21 mai 2019 à 16:51, Paul Cercueil <paul@crapouillou.net> a
écrit :
> This driver handles the interrupt controller built in the
> Timer/Counter
> Unit (TCU) of the JZ47xx SoCs from Ingenic.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
> drivers/irqchip/Kconfig | 11 ++
> drivers/irqchip/Makefile | 1 +
> drivers/irqchip/irq-ingenic-tcu.c | 182
> ++++++++++++++++++++++++++++++
> 3 files changed, 194 insertions(+)
> create mode 100644 drivers/irqchip/irq-ingenic-tcu.c
>
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 1c1f3f66dfd3..2d0700e52db7 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -293,6 +293,17 @@ config INGENIC_IRQ
> depends on MACH_INGENIC
> default y
>
> +config INGENIC_TCU_IRQ
> + bool "Ingenic JZ47xx TCU interrupt controller"
> + default MACH_INGENIC
> + depends on MIPS || COMPILE_TEST
> + select INGENIC_TCU
> + help
> + Support for interrupts in the Timer/Counter Unit (TCU) of the
> Ingenic
> + JZ47xx SoCs.
> +
> + If unsure, say N.
> +
> config RENESAS_H8300H_INTC
> bool
> select IRQ_DOMAIN
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 606a003a0000..f403b2c221e4 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_RENESAS_H8300H_INTC) +=
> irq-renesas-h8300h.o
> obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
> obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
> obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
> +obj-$(CONFIG_INGENIC_TCU_IRQ) += irq-ingenic-tcu.o
> obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
> obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o
> obj-$(CONFIG_MSCC_OCELOT_IRQ) += irq-mscc-ocelot.o
> diff --git a/drivers/irqchip/irq-ingenic-tcu.c
> b/drivers/irqchip/irq-ingenic-tcu.c
> new file mode 100644
> index 000000000000..738ed06c983f
> --- /dev/null
> +++ b/drivers/irqchip/irq-ingenic-tcu.c
> @@ -0,0 +1,182 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * JZ47xx SoCs TCU IRQ driver
> + * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/mfd/ingenic-tcu.h>
> +#include <linux/of_irq.h>
> +#include <linux/regmap.h>
> +
> +struct ingenic_tcu {
> + struct regmap *map;
> + struct clk *clk;
> +
> + struct irq_domain *domain;
> + unsigned int nb_parent_irqs;
> + u32 parent_irqs[3];
> +};
> +
> +static void ingenic_tcu_intc_cascade(struct irq_desc *desc)
> +{
> + struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
> + struct irq_domain *domain = irq_desc_get_handler_data(desc);
> + struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain,
> 0);
> + struct regmap *map = gc->private;
> + uint32_t irq_reg, irq_mask;
> + unsigned int i;
> +
> + regmap_read(map, TCU_REG_TFR, &irq_reg);
> + regmap_read(map, TCU_REG_TMR, &irq_mask);
> +
> + chained_irq_enter(irq_chip, desc);
> +
> + irq_reg &= ~irq_mask;
> +
> + for_each_set_bit(i, (unsigned long *)&irq_reg, 32)
> + generic_handle_irq(irq_linear_revmap(domain, i));
> +
> + chained_irq_exit(irq_chip, desc);
> +}
> +
> +static void ingenic_tcu_gc_unmask_enable_reg(struct irq_data *d)
> +{
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> + struct irq_chip_type *ct = irq_data_get_chip_type(d);
> + struct regmap *map = gc->private;
> + u32 mask = d->mask;
> +
> + irq_gc_lock(gc);
> + regmap_write(map, ct->regs.ack, mask);
> + regmap_write(map, ct->regs.enable, mask);
> + *ct->mask_cache |= mask;
> + irq_gc_unlock(gc);
> +}
> +
> +static void ingenic_tcu_gc_mask_disable_reg(struct irq_data *d)
> +{
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> + struct irq_chip_type *ct = irq_data_get_chip_type(d);
> + struct regmap *map = gc->private;
> + u32 mask = d->mask;
> +
> + irq_gc_lock(gc);
> + regmap_write(map, ct->regs.disable, mask);
> + *ct->mask_cache &= ~mask;
> + irq_gc_unlock(gc);
> +}
> +
> +static void ingenic_tcu_gc_mask_disable_reg_and_ack(struct irq_data
> *d)
> +{
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> + struct irq_chip_type *ct = irq_data_get_chip_type(d);
> + struct regmap *map = gc->private;
> + u32 mask = d->mask;
> +
> + irq_gc_lock(gc);
> + regmap_write(map, ct->regs.ack, mask);
> + regmap_write(map, ct->regs.disable, mask);
> + irq_gc_unlock(gc);
> +}
> +
> +static int __init ingenic_tcu_irq_init(struct device_node *np,
> + struct device_node *parent)
> +{
> + struct irq_chip_generic *gc;
> + struct irq_chip_type *ct;
> + struct ingenic_tcu *tcu;
> + struct regmap *map;
> + unsigned int i;
> + int ret, irqs;
> +
> + map = ingenic_tcu_get_regmap(np);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> +
> + tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
> + if (!tcu)
> + return -ENOMEM;
> +
> + tcu->map = map;
> +
> + irqs = of_property_count_elems_of_size(np, "interrupts",
> sizeof(u32));
> + if (irqs < 0 || irqs > ARRAY_SIZE(tcu->parent_irqs)) {
> + pr_crit("%s: Invalid 'interrupts' property\n", __func__);
> + ret = -EINVAL;
> + goto err_free_tcu;
> + }
> +
> + tcu->nb_parent_irqs = irqs;
> +
> + tcu->domain = irq_domain_add_linear(np, 32, &irq_generic_chip_ops,
> + NULL);
> + if (!tcu->domain) {
> + ret = -ENOMEM;
> + goto err_free_tcu;
> + }
> +
> + ret = irq_alloc_domain_generic_chips(tcu->domain, 32, 1, "TCU",
> + handle_level_irq, 0,
> + IRQ_NOPROBE | IRQ_LEVEL, 0);
> + if (ret) {
> + pr_crit("%s: Invalid 'interrupts' property\n", __func__);
> + goto out_domain_remove;
> + }
> +
> + gc = irq_get_domain_generic_chip(tcu->domain, 0);
> + ct = gc->chip_types;
> +
> + gc->wake_enabled = IRQ_MSK(32);
> + gc->private = tcu->map;
> +
> + ct->regs.disable = TCU_REG_TMSR;
> + ct->regs.enable = TCU_REG_TMCR;
> + ct->regs.ack = TCU_REG_TFCR;
> + ct->chip.irq_unmask = ingenic_tcu_gc_unmask_enable_reg;
> + ct->chip.irq_mask = ingenic_tcu_gc_mask_disable_reg;
> + ct->chip.irq_mask_ack = ingenic_tcu_gc_mask_disable_reg_and_ack;
> + ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
> +
> + /* Mask all IRQs by default */
> + regmap_write(tcu->map, TCU_REG_TMSR, IRQ_MSK(32));
> +
> + /*
> + * On JZ4740, timer 0 and timer 1 have their own interrupt line;
> + * timers 2-7 share one interrupt.
> + * On SoCs >= JZ4770, timer 5 has its own interrupt line;
> + * timers 0-4 and 6-7 share one single interrupt.
> + *
> + * To keep things simple, we just register the same handler to
> + * all parent interrupts. The handler will properly detect which
> + * channel fired the interrupt.
> + */
> + for (i = 0; i < irqs; i++) {
> + tcu->parent_irqs[i] = irq_of_parse_and_map(np, i);
> + if (!tcu->parent_irqs[i]) {
> + ret = -EINVAL;
> + goto out_unmap_irqs;
> + }
> +
> + irq_set_chained_handler_and_data(tcu->parent_irqs[i],
> + ingenic_tcu_intc_cascade,
> + tcu->domain);
> + }
> +
> + return 0;
> +
> +out_unmap_irqs:
> + for (; i > 0; i--)
> + irq_dispose_mapping(tcu->parent_irqs[i - 1]);
> +out_domain_remove:
> + irq_domain_remove(tcu->domain);
> +err_free_tcu:
> + kfree(tcu);
> + return ret;
> +}
> +IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu",
> ingenic_tcu_irq_init);
> +IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu",
> ingenic_tcu_irq_init);
> +IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu",
> ingenic_tcu_irq_init);
> --
> 2.21.0.593.g511ec345e18
>
^ permalink raw reply
* From:Miss: Fatima Yusuf.
From: Miss.Fatima Yusuf @ 2019-06-22 16:28 UTC (permalink / raw)
From:Miss: Fatima Yusuf.
For sure this mail would definitely come to you as a surprise, but do take your good time to go through it, My name is Ms. Fatima Yusuf,i am from Ivory Coast.
I lost my parents a year and couple of months ago. My father was a serving director of the Agro-exporting board until his death. He was assassinated by his business partners.Before his death, he made a deposit of US$9.7 Million Dollars here in Cote d'ivoire which was for the purchase of cocoa processing machine and development of another factory before his untimely death.
Being that this part of the world experiences political and crises time without number, there is no guarantee of lives and properties. I cannot invest this money here any long, despite the fact it had been my late father's industrial plans.
I want you to do me a favor to receive this funds into your country or any safer place as the beneficiary, I have plans to invest this money in continuation with the investment vision of my late father, but not in this place again rather in your country. I have the vision of going into real estate and industrial production or any profitable business venture.
I will be ready to compensate you with 20% of the total Amount, now all my hope is banked on you and i really wants to invest this money in your country, where there is stability of Government, political and economic welfare.
My greatest worry now is how to move out of this country because my uncle is threatening to kill me as he killed my father,Please do not let anybody hear about this, it is between me and you alone because of my security reason.
I am waiting to hear from you.
Yours Sincerely,
Miss.Fatima Yusuf.
^ permalink raw reply
* [PATCH 10/12] docs: kernel_abi.py: use --enable-lineno for get_abi.pl
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
Just like kernel-doc extension, we need to be able to identify
what part of an imported document has issues, as reporting them
as:
get_abi.pl rest --dir $srctree/Documentation/ABI/obsolete --rst-source:1689: ERROR: Unexpected indentation.
Makes a lot harder for someone to fix.
It should be noticed that it the line which will be reported is
the line where the "What:" definition is, and not the line
with actually has an error.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index 5d43cac73d0a..efa338e18764 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -35,6 +35,7 @@ import codecs
import os
import subprocess
import sys
+import re
from os import path
@@ -92,7 +93,7 @@ class KernelCmd(Directive):
env = doc.settings.env
cwd = path.dirname(doc.current_source)
- cmd = "get_abi.pl rest --dir "
+ cmd = "get_abi.pl rest --enable-lineno --dir "
cmd += self.arguments[0]
srctree = path.abspath(os.environ["srctree"])
@@ -136,7 +137,7 @@ class KernelCmd(Directive):
% (self.name, ErrorString(exc)))
return out
- def nestedParse(self, lines, fname):
+ def nestedParse(self, lines, f):
content = ViewList()
node = nodes.section()
@@ -146,8 +147,17 @@ class KernelCmd(Directive):
code_block += "\n " + l
lines = code_block + "\n\n"
- for c, l in enumerate(lines.split("\n")):
- content.append(l, fname, c)
+ line_regex = re.compile("^#define LINENO (\S+)\#([0-9]+)$")
+ ln = 0
+
+ for line in lines.split("\n"):
+ match = line_regex.search(line)
+ if match:
+ f = match.group(1)
+ # sphinx counts lines from 0
+ ln = int(match.group(2)) - 1
+ else:
+ content.append(line, f, ln)
buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
--
2.21.0
^ permalink raw reply related
* [PATCH 11/12] docs: kernel_abi.py: Handle with a lazy Sphinx parser
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
The Sphinx docutils parser is lazy: if the content is bigger than
a certain number of lines, it silenlty stops parsing it,
producing an incomplete content. This seems to be worse on newer
Sphinx versions, like 2.0.
So, change the logic to parse the contents per input file.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 39 ++++++++++++++++++++----------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index efa338e18764..a417026ed690 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -36,6 +36,7 @@ import os
import subprocess
import sys
import re
+import kernellog
from os import path
@@ -79,12 +80,6 @@ class KernelCmd(Directive):
"debug" : directives.flag
}
- def warn(self, message, **replace):
- replace["fname"] = self.state.document.current_source
- replace["line_no"] = replace.get("line_no", self.lineno)
- message = ("%(fname)s:%(line_no)s: [kernel-abi WARN] : " + message) % replace
- self.state.document.settings.env.app.warn(message, prefix="")
-
def run(self):
doc = self.state.document
@@ -110,7 +105,7 @@ class KernelCmd(Directive):
shell_env["srctree"] = srctree
lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
- nodeList = self.nestedParse(lines, fname)
+ nodeList = self.nestedParse(lines, self.arguments[0])
return nodeList
def runCmd(self, cmd, **kwargs):
@@ -137,9 +132,9 @@ class KernelCmd(Directive):
% (self.name, ErrorString(exc)))
return out
- def nestedParse(self, lines, f):
+ def nestedParse(self, lines, fname):
content = ViewList()
- node = nodes.section()
+ node = nodes.section()
if "debug" in self.options:
code_block = "\n\n.. code-block:: rst\n :linenos:\n"
@@ -149,22 +144,42 @@ class KernelCmd(Directive):
line_regex = re.compile("^#define LINENO (\S+)\#([0-9]+)$")
ln = 0
+ n = 0
+ f = fname
for line in lines.split("\n"):
+ n = n + 1
match = line_regex.search(line)
if match:
- f = match.group(1)
+ new_f = match.group(1)
+
+ # Sphinx parser is lazy: it stops parsing contents in the
+ # middle, if it is too big. So, handle it per input file
+ if new_f != f and content:
+ self.do_parse(content, node)
+ content = ViewList()
+
+ f = new_f
+
# sphinx counts lines from 0
ln = int(match.group(2)) - 1
else:
content.append(line, f, ln)
- buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+ kernellog.info(self.state.document.settings.env.app, "%s: parsed %i lines" % (fname, n))
+ if content:
+ self.do_parse(content, node)
+
+ return node.children
+
+ def do_parse(self, content, node):
if Use_SSI:
with switch_source_input(self.state, content):
self.state.nested_parse(content, 0, node, match_titles=1)
else:
+ buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+
self.state.memo.title_styles = []
self.state.memo.section_level = 0
self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
@@ -172,5 +187,3 @@ class KernelCmd(Directive):
self.state.nested_parse(content, 0, node, match_titles=1)
finally:
self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
-
- return node.children
--
2.21.0
^ permalink raw reply related
* [PATCH 09/12] docs: kernel_abi.py: add a SPDX header file
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
This file is released under GPL v2.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index ef91b1e1ff4b..5d43cac73d0a 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -1,4 +1,5 @@
# coding=utf-8
+# SPDX-License-Identifier: GPL-2.0
#
u"""
kernel-abi
--
2.21.0
^ permalink raw reply related
* [PATCH 12/12] docs: add ABI documentation to the admin-guide book
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
As we don't want a generic Sphinx extension to execute commands,
change the one proposed to Markus to call the abi_book.pl
script.
Use a script to parse the Documentation/ABI directory and output
it at the admin-guide.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/admin-guide/abi-obsolete.rst | 10 ++++++++++
Documentation/admin-guide/abi-removed.rst | 4 ++++
Documentation/admin-guide/abi-stable.rst | 13 +++++++++++++
Documentation/admin-guide/abi-testing.rst | 19 +++++++++++++++++++
Documentation/admin-guide/abi.rst | 11 +++++++++++
Documentation/admin-guide/index.rst | 1 +
Documentation/conf.py | 2 +-
7 files changed, 59 insertions(+), 1 deletion(-)
create mode 100644 Documentation/admin-guide/abi-obsolete.rst
create mode 100644 Documentation/admin-guide/abi-removed.rst
create mode 100644 Documentation/admin-guide/abi-stable.rst
create mode 100644 Documentation/admin-guide/abi-testing.rst
create mode 100644 Documentation/admin-guide/abi.rst
diff --git a/Documentation/admin-guide/abi-obsolete.rst b/Documentation/admin-guide/abi-obsolete.rst
new file mode 100644
index 000000000000..cda9168445a5
--- /dev/null
+++ b/Documentation/admin-guide/abi-obsolete.rst
@@ -0,0 +1,10 @@
+ABI obsolete symbols
+====================
+
+Documents interfaces that are still remaining in the kernel, but are
+marked to be removed at some later point in time.
+
+The description of the interface will document the reason why it is
+obsolete and when it can be expected to be removed.
+
+.. kernel-abi:: $srctree/Documentation/ABI/obsolete
diff --git a/Documentation/admin-guide/abi-removed.rst b/Documentation/admin-guide/abi-removed.rst
new file mode 100644
index 000000000000..497978fc9632
--- /dev/null
+++ b/Documentation/admin-guide/abi-removed.rst
@@ -0,0 +1,4 @@
+ABI removed symbols
+===================
+
+.. kernel-abi:: $srctree/Documentation/ABI/removed
diff --git a/Documentation/admin-guide/abi-stable.rst b/Documentation/admin-guide/abi-stable.rst
new file mode 100644
index 000000000000..7495d7a35048
--- /dev/null
+++ b/Documentation/admin-guide/abi-stable.rst
@@ -0,0 +1,13 @@
+ABI stable symbols
+==================
+
+Documents the interfaces that the developer has defined to be stable.
+
+Userspace programs are free to use these interfaces with no
+restrictions, and backward compatibility for them will be guaranteed
+for at least 2 years.
+
+Most interfaces (like syscalls) are expected to never change and always
+be available.
+
+.. kernel-abi:: $srctree/Documentation/ABI/stable
diff --git a/Documentation/admin-guide/abi-testing.rst b/Documentation/admin-guide/abi-testing.rst
new file mode 100644
index 000000000000..5c886fc50b9e
--- /dev/null
+++ b/Documentation/admin-guide/abi-testing.rst
@@ -0,0 +1,19 @@
+ABI testing symbols
+===================
+
+Documents interfaces that are felt to be stable,
+as the main development of this interface has been completed.
+
+The interface can be changed to add new features, but the
+current interface will not break by doing this, unless grave
+errors or security problems are found in them.
+
+Userspace programs can start to rely on these interfaces, but they must
+be aware of changes that can occur before these interfaces move to
+be marked stable.
+
+Programs that use these interfaces are strongly encouraged to add their
+name to the description of these interfaces, so that the kernel
+developers can easily notify them if any changes occur.
+
+.. kernel-abi:: $srctree/Documentation/ABI/testing
diff --git a/Documentation/admin-guide/abi.rst b/Documentation/admin-guide/abi.rst
new file mode 100644
index 000000000000..3b9645c77469
--- /dev/null
+++ b/Documentation/admin-guide/abi.rst
@@ -0,0 +1,11 @@
+=====================
+Linux ABI description
+=====================
+
+.. toctree::
+ :maxdepth: 1
+
+ abi-stable
+ abi-testing
+ abi-obsolete
+ abi-removed
diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
index 8001917ee012..20c3020fd73c 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -16,6 +16,7 @@ etc.
README
kernel-parameters
devices
+ abi
This section describes CPU vulnerabilities and their mitigations.
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 7ace3f8852bd..598256fb5c98 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -34,7 +34,7 @@ needs_sphinx = '1.3'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure', 'sphinx.ext.ifconfig']
+extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure', 'sphinx.ext.ifconfig', 'kernel_abi']
# The name of the math extension changed on Sphinx 1.4
if (major == 1 and minor > 3) or (major > 1):
--
2.21.0
^ permalink raw reply related
* [PATCH 03/12] scripts/get_abi.pl: Allow optionally record from where a line came from
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
The get_abi.pl reads a lot of files and can join them on a
single output file. Store where each "What:" output came from,
in order to be able to optionally display it.
This is useful for the Sphinx extension, with can now be
able to blame what ABI file has issues, and on what line
the What: description with problems begin.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
scripts/get_abi.pl | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
index 0c403af86fd5..6a4d387ebf3b 100755
--- a/scripts/get_abi.pl
+++ b/scripts/get_abi.pl
@@ -10,6 +10,7 @@ use Fcntl ':mode';
my $help;
my $man;
my $debug;
+my $enable_lineno;
my $prefix="Documentation/ABI";
#
@@ -19,6 +20,7 @@ my $description_is_rst = 0;
GetOptions(
"debug|d+" => \$debug,
+ "enable-lineno" => \$enable_lineno,
"rst-source!" => \$description_is_rst,
"dir=s" => \$prefix,
'help|?' => \$help,
@@ -67,6 +69,7 @@ sub parse_abi {
$data{$nametag}->{file} = $name;
$data{$nametag}->{filepath} = $file;
$data{$nametag}->{is_file} = 1;
+ $data{$nametag}->{line_no} = 1;
my $type = $file;
$type =~ s,.*/(.*)/.*,$1,;
@@ -126,6 +129,8 @@ sub parse_abi {
if ($tag ne "" && $new_tag) {
$tag = $new_tag;
+ $data{$what}->{line_no} = $ln;
+
if ($new_what) {
@{$data{$what}->{label}} = @labels if ($data{$nametag}->{what});
@labels = ();
@@ -221,6 +226,12 @@ sub output_rest {
my $file = $data{$what}->{file};
my $filepath = $data{$what}->{filepath};
+ if ($enable_lineno) {
+ printf "#define LINENO %s%s#%s\n\n",
+ $prefix, $data{$what}->{file},
+ $data{$what}->{line_no};
+ }
+
my $w = $what;
$w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g;
@@ -369,6 +380,10 @@ sub search_symbols {
}
}
+# Ensure that the prefix will always end with a slash
+# While this is not needed for find, it makes the patch nicer
+# with --enable-lineno
+$prefix =~ s,/?$,/,;
#
# Parses all ABI files located at $prefix dir
@@ -395,7 +410,8 @@ abi_book.pl - parse the Linux ABI files and produce a ReST book.
=head1 SYNOPSIS
-B<abi_book.pl> [--debug] [--man] [--help] --[(no-)rst-source] [--dir=<dir>] <COMAND> [<ARGUMENT>]
+B<abi_book.pl> [--debug] [--enable-lineno] [--man] [--help]
+ [--(no-)rst-source] [--dir=<dir>] <COMAND> [<ARGUMENT>]
Where <COMMAND> can be:
@@ -425,6 +441,10 @@ selecting between a rst-compliant source ABI (--rst-source), or a
plain text that may be violating ReST spec, so it requres some escaping
logic (--no-rst-source).
+=item B<--enable-lineno>
+
+Enable output of #define LINENO lines.
+
=item B<--debug>
Put the script in verbose mode, useful for debugging. Can be called multiple
--
2.21.0
^ permalink raw reply related
* [PATCH 06/12] docs: kernel_abi.py: fix UTF-8 support
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
The parser breaks with UTF-8 characters with Sphinx 1.4.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index 32ce90775d96..0f3e51e67e8d 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -1,4 +1,5 @@
-# -*- coding: utf-8; mode: python -*-
+# coding=utf-8
+#
u"""
kernel-abi
~~~~~~~~~~
@@ -28,6 +29,7 @@ u"""
"""
+import codecs
import sys
import os
from os import path
@@ -43,14 +45,6 @@ from docutils.utils.error_reporting import ErrorString
__version__ = '1.0'
-# We can't assume that six is installed
-PY3 = sys.version_info[0] == 3
-PY2 = sys.version_info[0] == 2
-if PY3:
- # pylint: disable=C0103, W0622
- unicode = str
- basestring = str
-
def setup(app):
app.add_directive("kernel-abi", KernelCmd)
@@ -115,12 +109,12 @@ class KernelCmd(Directive):
cmd
, stdout = subprocess.PIPE
, stderr = subprocess.PIPE
- , universal_newlines = True
, **kwargs
)
out, err = proc.communicate()
- if err:
- self.warn(err)
+
+ out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
+
if proc.returncode != 0:
raise self.severe(
u"command '%s' failed with return code %d"
@@ -129,7 +123,7 @@ class KernelCmd(Directive):
except OSError as exc:
raise self.severe(u"problems with '%s' directive: %s."
% (self.name, ErrorString(exc)))
- return unicode(out)
+ return out
def nestedParse(self, lines, fname):
content = ViewList()
--
2.21.0
^ permalink raw reply related
* [PATCH 00/12] Add the ABI documentation to the admin guide
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
Hi Greg/Jon,
That's the rebased patches with add the ABI documentation to the
admin-guide. It is rebased on the top of driver-core/driver-core-next,
and it can work both on the "old" mode, where the scripts will
avoid codes that would cause troubles for ReST, or at the new mode,
with parses the description to the ReST output untouched.
Patches 1 to 3 improves the get_abi.pl for it to parse ReST format,
and to report where the errors/warnings occur at the ABI file.
Patch 4 is implements support for a Sphinx log facility (info).
Patches 5 to 10 adds the new kernel ABI extension, making it ready
to parse files in ether "normal" or "rst-source" mode.
Patch 11 addresses a Sphinx issue, with is there since old vesions,
but it gets worse on Sphins 2.0: basically, the ReST parser is lazy:
if it receives too much stuff, it silently ignores the end of the content.
So, the extension needs to split the content on small chunks.
IMO, it is safe to apply patches 1 to 11 via Greg's tree. The only
potential conflict would be at patch 4, but looking at docs-next,
I don't see any changes at Documentation/scripts/kernelog.py.
Patch 12 actually enables everything.
If Patch 12 gets merged via Greg's tree, it may rise a single-line
trivial conflict with docs-next, as it will be adding kernel_abi to the
list of extensions at Documentation/conf.py, and Jon is likely
adding another extension. too.
So, it could be wise postpone patch 12 to be merged after both
trees got merged upstream.
Patch 12 adds ABI with ReST-scaping code. I'll submit soon a
second version for the RFC patches with turns it to "clean" mode.
The entire ABI series (plus Documentation/features) is at:
https://git.linuxtv.org/mchehab/experimental.git/log/?h=abi_patches_v4.2
And the ReST output (with Sphinx 2.0 - with IMO provides a nicer
output) is at:
https://www.infradead.org/~mchehab/rst_features/admin-guide/abi.html
Mauro Carvalho Chehab (12):
scripts/get_abi.pl: change script to allow parsing in ReST mode
scripts/get_abi.pl: fix parsing on ReST mode
scripts/get_abi.pl: Allow optionally record from where a line came
from
docs: kernellog.py: add support for info()
docs: kernel_abi.py: add a script to parse ABI documentation
docs: kernel_abi.py: fix UTF-8 support
docs: kernel_abi.py: make it compatible with Sphinx 1.7+
docs: kernel_abi.py: Update copyrights
docs: kernel_abi.py: add a SPDX header file
docs: kernel_abi.py: use --enable-lineno for get_abi.pl
docs: kernel_abi.py: Handle with a lazy Sphinx parser
docs: add ABI documentation to the admin-guide book
Documentation/admin-guide/abi-obsolete.rst | 10 ++
Documentation/admin-guide/abi-removed.rst | 4 +
Documentation/admin-guide/abi-stable.rst | 13 ++
Documentation/admin-guide/abi-testing.rst | 19 +++
Documentation/admin-guide/abi.rst | 11 ++
Documentation/admin-guide/index.rst | 1 +
Documentation/conf.py | 2 +-
Documentation/sphinx/kernel_abi.py | 189 +++++++++++++++++++++
Documentation/sphinx/kernellog.py | 6 +-
scripts/get_abi.pl | 104 ++++++++----
10 files changed, 325 insertions(+), 34 deletions(-)
create mode 100644 Documentation/admin-guide/abi-obsolete.rst
create mode 100644 Documentation/admin-guide/abi-removed.rst
create mode 100644 Documentation/admin-guide/abi-stable.rst
create mode 100644 Documentation/admin-guide/abi-testing.rst
create mode 100644 Documentation/admin-guide/abi.rst
create mode 100644 Documentation/sphinx/kernel_abi.py
--
2.21.0
^ permalink raw reply
* [PATCH 04/12] docs: kernellog.py: add support for info()
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
An extension may want to just inform about something. So, add
support for it.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernellog.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/sphinx/kernellog.py b/Documentation/sphinx/kernellog.py
index af924f51a7dc..8ac7d274f542 100644
--- a/Documentation/sphinx/kernellog.py
+++ b/Documentation/sphinx/kernellog.py
@@ -25,4 +25,8 @@ def verbose(app, message):
else:
app.verbose(message)
-
+def info(app, message):
+ if UseLogging:
+ logger.info(message)
+ else:
+ app.info(message)
--
2.21.0
^ permalink raw reply related
* [PATCH 02/12] scripts/get_abi.pl: fix parsing on ReST mode
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
When the source ABI file is using ReST notation, the script
should handle whitespaces and lines with care, as otherwise
the file won't be properly recognized.
Address the bugs that are on such part of the script.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
scripts/get_abi.pl | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
index 107672cdacb3..0c403af86fd5 100755
--- a/scripts/get_abi.pl
+++ b/scripts/get_abi.pl
@@ -151,7 +151,8 @@ sub parse_abi {
$content = $2;
}
while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
- $data{$what}->{$tag} .= $content;
+
+ $data{$what}->{$tag} .= "$content\n" if ($content);
} else {
$data{$what}->{$tag} = $content;
}
@@ -166,31 +167,28 @@ sub parse_abi {
}
if ($tag eq "description") {
+ my $content = $_;
+ while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
if (!$data{$what}->{description}) {
- s/^($space)//;
- if (m/^(\s*)(.*)/) {
- my $sp = $1;
- while ($sp =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
- my $content = "$sp$2";
-
- $content =~ s/^($space)//;
-
- $data{$what}->{$tag} .= "$content";
+ # Preserve initial spaces for the first line
+ if ($content =~ m/^(\s*)(.*)$/) {
+ $space = $1;
+ $content = $2;
}
+
+ $data{$what}->{$tag} .= "$content\n" if ($content);
} else {
- my $content = $_;
if (m/^\s*\n/) {
$data{$what}->{$tag} .= $content;
next;
}
- while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
$space = "" if (!($content =~ s/^($space)//));
- # Compress spaces with tabs
- $content =~ s<^ {8}> <\t>;
- $content =~ s<^ {1,7}\t> <\t>;
- $content =~ s< {1,7}\t> <\t>;
+# # Compress spaces with tabs
+# $content =~ s<^ {8}> <\t>;
+# $content =~ s<^ {1,7}\t> <\t>;
+# $content =~ s< {1,7}\t> <\t>;
$data{$what}->{$tag} .= $content;
}
next;
--
2.21.0
^ permalink raw reply related
* [PATCH 05/12] docs: kernel_abi.py: add a script to parse ABI documentation
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
The ABI documentation is special: it is not plain text files,
but, instead, files with an strict format, as specified by
Documentation/ABI/README.
Add a parser for it.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 155 +++++++++++++++++++++++++++++
1 file changed, 155 insertions(+)
create mode 100644 Documentation/sphinx/kernel_abi.py
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
new file mode 100644
index 000000000000..32ce90775d96
--- /dev/null
+++ b/Documentation/sphinx/kernel_abi.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8; mode: python -*-
+u"""
+ kernel-abi
+ ~~~~~~~~~~
+
+ Implementation of the ``kernel-abi`` reST-directive.
+
+ :copyright: Copyright (C) 2016 Markus Heiser
+ :copyright: Copyright (C) 2016 Mauro Carvalho Chehab
+ :license: GPL Version 2, June 1991 see Linux/COPYING for details.
+
+ The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
+ scripts/get_abi.pl script to parse the Kernel ABI files.
+
+ Overview of directive's argument and options.
+
+ .. code-block:: rst
+
+ .. kernel-abi:: <ABI directory location>
+ :debug:
+
+ The argument ``<ABI directory location>`` is required. It contains the
+ location of the ABI files to be parsed.
+
+ ``debug``
+ Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
+ what reST is generated.
+
+"""
+
+import sys
+import os
+from os import path
+import subprocess
+
+from sphinx.ext.autodoc import AutodocReporter
+
+from docutils import nodes
+from docutils.parsers.rst import Directive, directives
+from docutils.statemachine import ViewList
+from docutils.utils.error_reporting import ErrorString
+
+
+__version__ = '1.0'
+
+# We can't assume that six is installed
+PY3 = sys.version_info[0] == 3
+PY2 = sys.version_info[0] == 2
+if PY3:
+ # pylint: disable=C0103, W0622
+ unicode = str
+ basestring = str
+
+def setup(app):
+
+ app.add_directive("kernel-abi", KernelCmd)
+ return dict(
+ version = __version__
+ , parallel_read_safe = True
+ , parallel_write_safe = True
+ )
+
+class KernelCmd(Directive):
+
+ u"""KernelABI (``kernel-abi``) directive"""
+
+ required_arguments = 1
+ optional_arguments = 0
+ has_content = False
+ final_argument_whitespace = True
+
+ option_spec = {
+ "debug" : directives.flag
+ }
+
+ def warn(self, message, **replace):
+ replace["fname"] = self.state.document.current_source
+ replace["line_no"] = replace.get("line_no", self.lineno)
+ message = ("%(fname)s:%(line_no)s: [kernel-abi WARN] : " + message) % replace
+ self.state.document.settings.env.app.warn(message, prefix="")
+
+ def run(self):
+
+ doc = self.state.document
+ if not doc.settings.file_insertion_enabled:
+ raise self.warning("docutils: file insertion disabled")
+
+ env = doc.settings.env
+ cwd = path.dirname(doc.current_source)
+ cmd = "get_abi.pl rest --dir "
+ cmd += self.arguments[0]
+
+ srctree = path.abspath(os.environ["srctree"])
+
+ fname = cmd
+
+ # extend PATH with $(srctree)/scripts
+ path_env = os.pathsep.join([
+ srctree + os.sep + "scripts",
+ os.environ["PATH"]
+ ])
+ shell_env = os.environ.copy()
+ shell_env["PATH"] = path_env
+ shell_env["srctree"] = srctree
+
+ lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
+ nodeList = self.nestedParse(lines, fname)
+ return nodeList
+
+ def runCmd(self, cmd, **kwargs):
+ u"""Run command ``cmd`` and return it's stdout as unicode."""
+
+ try:
+ proc = subprocess.Popen(
+ cmd
+ , stdout = subprocess.PIPE
+ , stderr = subprocess.PIPE
+ , universal_newlines = True
+ , **kwargs
+ )
+ out, err = proc.communicate()
+ if err:
+ self.warn(err)
+ if proc.returncode != 0:
+ raise self.severe(
+ u"command '%s' failed with return code %d"
+ % (cmd, proc.returncode)
+ )
+ except OSError as exc:
+ raise self.severe(u"problems with '%s' directive: %s."
+ % (self.name, ErrorString(exc)))
+ return unicode(out)
+
+ def nestedParse(self, lines, fname):
+ content = ViewList()
+ node = nodes.section()
+
+ if "debug" in self.options:
+ code_block = "\n\n.. code-block:: rst\n :linenos:\n"
+ for l in lines.split("\n"):
+ code_block += "\n " + l
+ lines = code_block + "\n\n"
+
+ for c, l in enumerate(lines.split("\n")):
+ content.append(l, fname, c)
+
+ buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+ self.state.memo.title_styles = []
+ self.state.memo.section_level = 0
+ self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
+ try:
+ self.state.nested_parse(content, 0, node, match_titles=1)
+ finally:
+ self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+ return node.children
--
2.21.0
^ permalink raw reply related
* [PATCH 07/12] docs: kernel_abi.py: make it compatible with Sphinx 1.7+
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
The same way kerneldoc.py needed changes to work with newer
Sphinx, this script needs the same changes.
While here, reorganize the include order to match kerneldoc.py.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 39 +++++++++++++++++++++---------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index 0f3e51e67e8d..2d5d582207f7 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -30,18 +30,27 @@ u"""
"""
import codecs
-import sys
import os
-from os import path
import subprocess
+import sys
-from sphinx.ext.autodoc import AutodocReporter
+from os import path
-from docutils import nodes
-from docutils.parsers.rst import Directive, directives
+from docutils import nodes, statemachine
from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives, Directive
from docutils.utils.error_reporting import ErrorString
+#
+# AutodocReporter is only good up to Sphinx 1.7
+#
+import sphinx
+
+Use_SSI = sphinx.__version__[:3] >= '1.7'
+if Use_SSI:
+ from sphinx.util.docutils import switch_source_input
+else:
+ from sphinx.ext.autodoc import AutodocReporter
__version__ = '1.0'
@@ -139,11 +148,17 @@ class KernelCmd(Directive):
content.append(l, fname, c)
buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
- self.state.memo.title_styles = []
- self.state.memo.section_level = 0
- self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
- try:
- self.state.nested_parse(content, 0, node, match_titles=1)
- finally:
- self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+
+ if Use_SSI:
+ with switch_source_input(self.state, content):
+ self.state.nested_parse(content, 0, node, match_titles=1)
+ else:
+ self.state.memo.title_styles = []
+ self.state.memo.section_level = 0
+ self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
+ try:
+ self.state.nested_parse(content, 0, node, match_titles=1)
+ finally:
+ self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+
return node.children
--
2.21.0
^ permalink raw reply related
* [PATCH 08/12] docs: kernel_abi.py: Update copyrights
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
As Markus doesn't want to maintain ths file, update it to
put me as its maintainer.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_abi.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index 2d5d582207f7..ef91b1e1ff4b 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -7,7 +7,8 @@ u"""
Implementation of the ``kernel-abi`` reST-directive.
:copyright: Copyright (C) 2016 Markus Heiser
- :copyright: Copyright (C) 2016 Mauro Carvalho Chehab
+ :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab
+ :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
:license: GPL Version 2, June 1991 see Linux/COPYING for details.
The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
--
2.21.0
^ permalink raw reply related
* [PATCH 01/12] scripts/get_abi.pl: change script to allow parsing in ReST mode
From: Mauro Carvalho Chehab @ 2019-06-22 16:58 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561221403.git.mchehab+samsung@kernel.org>
Right now, several ABI files won't parse as ReST, as they
contain severe violations to the spec, with makes the script
to crash.
So, the code has a sanity logic with escapes bad code and
cleans tags that can cause Sphinx to crash.
Add support for disabling this mode.
Right now, as enabling rst-mode causes crash, it is disabled
by default.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
scripts/get_abi.pl | 74 ++++++++++++++++++++++++++++++----------------
1 file changed, 48 insertions(+), 26 deletions(-)
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
index c738cb795514..107672cdacb3 100755
--- a/scripts/get_abi.pl
+++ b/scripts/get_abi.pl
@@ -12,8 +12,14 @@ my $man;
my $debug;
my $prefix="Documentation/ABI";
+#
+# If true, assumes that the description is formatted with ReST
+#
+my $description_is_rst = 0;
+
GetOptions(
"debug|d+" => \$debug,
+ "rst-source!" => \$description_is_rst,
"dir=s" => \$prefix,
'help|?' => \$help,
man => \$man
@@ -137,14 +143,15 @@ sub parse_abi {
next;
}
if ($tag eq "description") {
- next if ($content =~ m/^\s*$/);
- if ($content =~ m/^(\s*)(.*)/) {
- my $new_content = $2;
- $space = $new_tag . $sep . $1;
- while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
- $space =~ s/./ /g;
- $data{$what}->{$tag} .= "$new_content\n";
+ # Preserve initial spaces for the first line
+ $content = ' ' x length($new_tag) . $sep . $content;
+ $content =~ s,^(\s*):,$1 ,;
+ if ($content =~ m/^(\s*)(.*)$/) {
+ $space = $1;
+ $content = $2;
}
+ while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+ $data{$what}->{$tag} .= $content;
} else {
$data{$what}->{$tag} = $content;
}
@@ -160,11 +167,15 @@ sub parse_abi {
if ($tag eq "description") {
if (!$data{$what}->{description}) {
- next if (m/^\s*\n/);
+ s/^($space)//;
if (m/^(\s*)(.*)/) {
- $space = $1;
- while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
- $data{$what}->{$tag} .= "$2\n";
+ my $sp = $1;
+ while ($sp =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+ my $content = "$sp$2";
+
+ $content =~ s/^($space)//;
+
+ $data{$what}->{$tag} .= "$content";
}
} else {
my $content = $_;
@@ -274,23 +285,27 @@ sub output_rest {
print "Defined on file :ref:`$file <$fileref>`\n\n" if ($type ne "File");
my $desc = $data{$what}->{description};
- $desc =~ s/^\s+//;
-
- # Remove title markups from the description, as they won't work
- $desc =~ s/\n[\-\*\=\^\~]+\n/\n/g;
if (!($desc =~ /^\s*$/)) {
- if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
- # put everything inside a code block
- $desc =~ s/\n/\n /g;
-
- print "::\n\n";
- print " $desc\n\n";
- } else {
- # Escape any special chars from description
- $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
-
+ if ($description_is_rst) {
print "$desc\n\n";
+ } else {
+ $desc =~ s/^\s+//;
+
+ # Remove title markups from the description, as they won't work
+ $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g;
+
+ if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
+ # put everything inside a code block
+ $desc =~ s/\n/\n /g;
+
+ print "::\n\n";
+ print " $desc\n\n";
+ } else {
+ # Escape any special chars from description
+ $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
+ print "$desc\n\n";
+ }
}
} else {
print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file});
@@ -382,7 +397,7 @@ abi_book.pl - parse the Linux ABI files and produce a ReST book.
=head1 SYNOPSIS
-B<abi_book.pl> [--debug] [--man] [--help] [--dir=<dir>] <COMAND> [<ARGUMENT>]
+B<abi_book.pl> [--debug] [--man] [--help] --[(no-)rst-source] [--dir=<dir>] <COMAND> [<ARGUMENT>]
Where <COMMAND> can be:
@@ -405,6 +420,13 @@ B<validate> - validate the ABI contents
Changes the location of the ABI search. By default, it uses
the Documentation/ABI directory.
+=item B<--rst-source> and B<--no-rst-source>
+
+The input file may be using ReST syntax or not. Those two options allow
+selecting between a rst-compliant source ABI (--rst-source), or a
+plain text that may be violating ReST spec, so it requres some escaping
+logic (--no-rst-source).
+
=item B<--debug>
Put the script in verbose mode, useful for debugging. Can be called multiple
--
2.21.0
^ permalink raw reply related
* [PATCH 2/4] scripts/get_feat.pl: handle ".." special case
From: Mauro Carvalho Chehab @ 2019-06-22 17:17 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561222784.git.mchehab+samsung@kernel.org>
The status ".." Means that the feature can't be implemented
on a given architecture.
The problem is that this doesn't show anything at the
output, so replace it by "---", with is a markup for a long
hyphen.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
scripts/get_feat.pl | 2 ++
1 file changed, 2 insertions(+)
diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl
index 401cbc820caa..79d83595addd 100755
--- a/scripts/get_feat.pl
+++ b/scripts/get_feat.pl
@@ -141,6 +141,8 @@ sub parse_feat {
$max_size_arch = length($a);
}
+ $status = "---" if ($status =~ m/^\.\.$/);
+
$archs{$a} = 1;
$arch_table{$a} = $status;
next;
--
2.21.0
^ permalink raw reply related
* [PATCH 4/4] docs: admin-guide, x86: add a features list
From: Mauro Carvalho Chehab @ 2019-06-22 17:17 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
x86
In-Reply-To: <cover.1561222784.git.mchehab+samsung@kernel.org>
Add a feature list matrix at the admin-guide and a x86-specific
feature list to the respective Kernel books.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/admin-guide/features.rst | 3 +++
Documentation/admin-guide/index.rst | 1 +
Documentation/conf.py | 2 +-
Documentation/x86/features.rst | 3 +++
Documentation/x86/index.rst | 1 +
5 files changed, 9 insertions(+), 1 deletion(-)
create mode 100644 Documentation/admin-guide/features.rst
create mode 100644 Documentation/x86/features.rst
diff --git a/Documentation/admin-guide/features.rst b/Documentation/admin-guide/features.rst
new file mode 100644
index 000000000000..8c167082a84f
--- /dev/null
+++ b/Documentation/admin-guide/features.rst
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features
diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
index 20c3020fd73c..14c8464f6ca9 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -17,6 +17,7 @@ etc.
kernel-parameters
devices
abi
+ features
This section describes CPU vulnerabilities and their mitigations.
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 598256fb5c98..a0ef76ce5615 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -34,7 +34,7 @@ needs_sphinx = '1.3'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure', 'sphinx.ext.ifconfig', 'kernel_abi']
+extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure', 'sphinx.ext.ifconfig', 'kernel_abi', 'kernel_feat']
# The name of the math extension changed on Sphinx 1.4
if (major == 1 and minor > 3) or (major > 1):
diff --git a/Documentation/x86/features.rst b/Documentation/x86/features.rst
new file mode 100644
index 000000000000..b663f15053ce
--- /dev/null
+++ b/Documentation/x86/features.rst
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features x86
diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst
index ae36fc5fc649..ed42c8c9154d 100644
--- a/Documentation/x86/index.rst
+++ b/Documentation/x86/index.rst
@@ -29,3 +29,4 @@ x86-specific Documentation
usb-legacy-support
i386/index
x86_64/index
+ features
--
2.21.0
^ permalink raw reply related
* [PATCH 3/4] sphinx/kernel_feat.py: add a script to parse feature files
From: Mauro Carvalho Chehab @ 2019-06-22 17:17 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561222784.git.mchehab+samsung@kernel.org>
The feature files have a special well-defined format. Add
a script that parses them, allowing to search for a feature
and/or by an architecture and to produce ReST-compatible
outputs.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/sphinx/kernel_feat.py | 169 ++++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 Documentation/sphinx/kernel_feat.py
diff --git a/Documentation/sphinx/kernel_feat.py b/Documentation/sphinx/kernel_feat.py
new file mode 100644
index 000000000000..2fee04f1dedd
--- /dev/null
+++ b/Documentation/sphinx/kernel_feat.py
@@ -0,0 +1,169 @@
+# coding=utf-8
+# SPDX-License-Identifier: GPL-2.0
+#
+u"""
+ kernel-feat
+ ~~~~~~~~~~~
+
+ Implementation of the ``kernel-feat`` reST-directive.
+
+ :copyright: Copyright (C) 2016 Markus Heiser
+ :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab
+ :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+ :license: GPL Version 2, June 1991 see Linux/COPYING for details.
+
+ The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
+ scripts/get_feat.pl script to parse the Kernel ABI files.
+
+ Overview of directive's argument and options.
+
+ .. code-block:: rst
+
+ .. kernel-feat:: <ABI directory location>
+ :debug:
+
+ The argument ``<ABI directory location>`` is required. It contains the
+ location of the ABI files to be parsed.
+
+ ``debug``
+ Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
+ what reST is generated.
+
+"""
+
+import codecs
+import os
+import subprocess
+import sys
+
+from os import path
+
+from docutils import nodes, statemachine
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives, Directive
+from docutils.utils.error_reporting import ErrorString
+
+#
+# AutodocReporter is only good up to Sphinx 1.7
+#
+import sphinx
+
+Use_SSI = sphinx.__version__[:3] >= '1.7'
+if Use_SSI:
+ from sphinx.util.docutils import switch_source_input
+else:
+ from sphinx.ext.autodoc import AutodocReporter
+
+__version__ = '1.0'
+
+def setup(app):
+
+ app.add_directive("kernel-feat", KernelFeat)
+ return dict(
+ version = __version__
+ , parallel_read_safe = True
+ , parallel_write_safe = True
+ )
+
+class KernelFeat(Directive):
+
+ u"""KernelFeat (``kernel-feat``) directive"""
+
+ required_arguments = 1
+ optional_arguments = 2
+ has_content = False
+ final_argument_whitespace = True
+
+ option_spec = {
+ "debug" : directives.flag
+ }
+
+ def warn(self, message, **replace):
+ replace["fname"] = self.state.document.current_source
+ replace["line_no"] = replace.get("line_no", self.lineno)
+ message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
+ self.state.document.settings.env.app.warn(message, prefix="")
+
+ def run(self):
+
+ doc = self.state.document
+ if not doc.settings.file_insertion_enabled:
+ raise self.warning("docutils: file insertion disabled")
+
+ env = doc.settings.env
+ cwd = path.dirname(doc.current_source)
+ cmd = "get_feat.pl rest --dir "
+ cmd += self.arguments[0]
+
+ if len(self.arguments) > 1:
+ cmd += " --arch " + self.arguments[1]
+
+ srctree = path.abspath(os.environ["srctree"])
+
+ fname = cmd
+
+ # extend PATH with $(srctree)/scripts
+ path_env = os.pathsep.join([
+ srctree + os.sep + "scripts",
+ os.environ["PATH"]
+ ])
+ shell_env = os.environ.copy()
+ shell_env["PATH"] = path_env
+ shell_env["srctree"] = srctree
+
+ lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
+ nodeList = self.nestedParse(lines, fname)
+ return nodeList
+
+ def runCmd(self, cmd, **kwargs):
+ u"""Run command ``cmd`` and return it's stdout as unicode."""
+
+ try:
+ proc = subprocess.Popen(
+ cmd
+ , stdout = subprocess.PIPE
+ , stderr = subprocess.PIPE
+ , **kwargs
+ )
+ out, err = proc.communicate()
+
+ out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
+
+ if proc.returncode != 0:
+ raise self.severe(
+ u"command '%s' failed with return code %d"
+ % (cmd, proc.returncode)
+ )
+ except OSError as exc:
+ raise self.severe(u"problems with '%s' directive: %s."
+ % (self.name, ErrorString(exc)))
+ return out
+
+ def nestedParse(self, lines, fname):
+ content = ViewList()
+ node = nodes.section()
+
+ if "debug" in self.options:
+ code_block = "\n\n.. code-block:: rst\n :linenos:\n"
+ for l in lines.split("\n"):
+ code_block += "\n " + l
+ lines = code_block + "\n\n"
+
+ for c, l in enumerate(lines.split("\n")):
+ content.append(l, fname, c)
+
+ buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+
+ if Use_SSI:
+ with switch_source_input(self.state, content):
+ self.state.nested_parse(content, 0, node, match_titles=1)
+ else:
+ self.state.memo.title_styles = []
+ self.state.memo.section_level = 0
+ self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
+ try:
+ self.state.nested_parse(content, 0, node, match_titles=1)
+ finally:
+ self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+
+ return node.children
--
2.21.0
^ permalink raw reply related
* [PATCH 0/4] Add Documentation/features to admin-guide and x86
From: Mauro Carvalho Chehab @ 2019-06-22 17:17 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel,
Borislav Petkov, H. Peter Anvin, Ingo Molnar, Thomas Gleixner,
x86
Jon, Greg & all:
Not sure what tree this would fit better.
The first 2 patches on this series reimplement the logic at:
Documentation/features/list-arch.sh
I opted to not remove the old script, as someone could depend on
its specific format. The new script does the same with:
./scripts/get_feat.pl current
The difference is that it outputs with using ascii table artwork.
The way it works is that it parse all feature files and produce 3 different
types of contents, depending on its arguments:
- a feature x arch matrix:
./scripts/get_feat.pl rest
- a per-architecture feature table:
./scripts/get_feat.pl current
or
./scripts/get_feat.pl rest --arch=arm64
- a per-feature table:
./scripts/get_feat.pl rest --feat=perf-regs
All outputs are compatible with the ReST format.
Patch 3 adds a new Sphinx plugin with handles its output.
Patch 4 adds the feature x arch matrix at the admin-guide.
Patch 4 also adds the features supported on x86 at the x86 arch guide.
IMHO, it makes sense to have a similar table on all other architectures, but
the best is to wait for the next Kernel version, in order to see what arch
conversion files got included.
So far, I didn't add the per-feature table anywhere.
Mauro Carvalho Chehab (4):
scripts/get_feat.pl: add a script to handle Documentation/features
scripts/get_feat.pl: handle ".." special case
sphinx/kernel_feat.py: add a script to parse feature files
docs: admin-guide, x86: add a features list
Documentation/admin-guide/features.rst | 3 +
Documentation/admin-guide/index.rst | 1 +
Documentation/conf.py | 2 +-
Documentation/sphinx/kernel_feat.py | 169 +++++++++
Documentation/x86/features.rst | 3 +
Documentation/x86/index.rst | 1 +
scripts/get_feat.pl | 474 +++++++++++++++++++++++++
7 files changed, 652 insertions(+), 1 deletion(-)
create mode 100644 Documentation/admin-guide/features.rst
create mode 100644 Documentation/sphinx/kernel_feat.py
create mode 100644 Documentation/x86/features.rst
create mode 100755 scripts/get_feat.pl
--
2.21.0
^ permalink raw reply
* [PATCH 1/4] scripts/get_feat.pl: add a script to handle Documentation/features
From: Mauro Carvalho Chehab @ 2019-06-22 17:17 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh, Jonathan Corbet
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <cover.1561222784.git.mchehab+samsung@kernel.org>
The Documentation/features contains a set of parseable files.
It is not worth converting them to ReST format, as they're
useful the way it is. It is, however, interesting to parse
them and produce output on different formats:
1) Output the contents of a feature in ReST format;
2) Output what features a given architecture supports;
3) Output a matrix with features x architectures.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
scripts/get_feat.pl | 472 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 472 insertions(+)
create mode 100755 scripts/get_feat.pl
diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl
new file mode 100755
index 000000000000..401cbc820caa
--- /dev/null
+++ b/scripts/get_feat.pl
@@ -0,0 +1,472 @@
+#!/usr/bin/perl
+# SPDX-License-Identifier: GPL-2.0
+
+use strict;
+use Pod::Usage;
+use Getopt::Long;
+use File::Find;
+use Fcntl ':mode';
+
+my $help;
+my $man;
+my $debug;
+my $arch;
+my $feat;
+my $prefix="Documentation/features";
+
+GetOptions(
+ "debug|d+" => \$debug,
+ "dir=s" => \$prefix,
+ 'help|?' => \$help,
+ 'arch=s' => \$arch,
+ 'feat=s' => \$feat,
+ man => \$man
+) or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2);
+
+my ($cmd, $arg) = @ARGV;
+
+pod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate");
+
+require Data::Dumper if ($debug);
+
+my %data;
+my %archs;
+
+#
+# Displays an error message, printing file name and line
+#
+sub parse_error($$$$) {
+ my ($file, $ln, $msg, $data) = @_;
+
+ $data =~ s/\s+$/\n/;
+
+ print STDERR "Warning: file $file#$ln:\n\t$msg";
+
+ if ($data ne "") {
+ print STDERR ". Line\n\t\t$data";
+ } else {
+ print STDERR "\n";
+ }
+}
+
+#
+# Parse a features file, storing its contents at %data
+#
+
+my $h_name = "Feature";
+my $h_kconfig = "Kconfig";
+my $h_description = "Description";
+my $h_subsys = "Subsystem";
+my $h_status = "Status";
+my $h_arch = "Architecture";
+
+my $max_size_name = length($h_name);
+my $max_size_kconfig = length($h_kconfig);
+my $max_size_description = length($h_description);
+my $max_size_subsys = length($h_subsys);
+my $max_size_status = length($h_status);
+my $max_size_arch = length($h_arch);
+
+sub parse_feat {
+ my $file = $File::Find::name;
+
+ my $mode = (stat($file))[2];
+ return if ($mode & S_IFDIR);
+ return if ($file =~ m,($prefix)/arch-support.txt,);
+ return if (!($file =~ m,arch-support.txt$,));
+
+ my $subsys = "";
+ $subsys = $2 if ( m,.*($prefix)/([^/]+).*,);
+
+ if (length($subsys) > $max_size_subsys) {
+ $max_size_subsys = length($subsys);
+ }
+
+ my $name;
+ my $kconfig;
+ my $description;
+ my $comments = "";
+ my $last_status;
+ my $ln;
+ my %arch_table;
+
+ print STDERR "Opening $file\n" if ($debug > 1);
+ open IN, $file;
+
+ while(<IN>) {
+ $ln++;
+
+ if (m/^\#\s+Feature\s+name:\s*(.*\S)/) {
+ $name = $1;
+ if (length($name) > $max_size_name) {
+ $max_size_name = length($name);
+ }
+ next;
+ }
+ if (m/^\#\s+Kconfig:\s*(.*\S)/) {
+ $kconfig = $1;
+ if (length($kconfig) > $max_size_kconfig) {
+ $max_size_kconfig = length($kconfig);
+ }
+ next;
+ }
+ if (m/^\#\s+description:\s*(.*\S)/) {
+ $description = $1;
+ if (length($description) > $max_size_description) {
+ $max_size_description = length($description);
+ }
+ next;
+ }
+ next if (m/^\\s*$/);
+ next if (m/^\s*\-+\s*$/);
+ next if (m/^\s*\|\s*arch\s*\|\s*status\s*\|\s*$/);
+
+ if (m/^\#\s*(.*)/) {
+ $comments .= "$1\n";
+ next;
+ }
+ if (m/^\s*\|\s*(\S+):\s*\|\s*(\S+)\s*\|\s*$/) {
+ my $a = $1;
+ my $status = $2;
+
+ if (length($status) > $max_size_status) {
+ $max_size_status = length($status);
+ }
+ if (length($a) > $max_size_arch) {
+ $max_size_arch = length($a);
+ }
+
+ $archs{$a} = 1;
+ $arch_table{$a} = $status;
+ next;
+ }
+
+ #Everything else is an error
+ parse_error($file, $ln, "line is invalid", $_);
+ }
+ close IN;
+
+ if (!$name) {
+ parse_error($file, $ln, "Feature name not found", "");
+ return;
+ }
+
+ parse_error($file, $ln, "Subsystem not found", "") if (!$subsys);
+ parse_error($file, $ln, "Kconfig not found", "") if (!$kconfig);
+ parse_error($file, $ln, "Description not found", "") if (!$description);
+
+ if (!%arch_table) {
+ parse_error($file, $ln, "Architecture table not found", "");
+ return;
+ }
+
+ $data{$name}->{where} = $file;
+ $data{$name}->{subsys} = $subsys;
+ $data{$name}->{kconfig} = $kconfig;
+ $data{$name}->{description} = $description;
+ $data{$name}->{comments} = $comments;
+ $data{$name}->{table} = \%arch_table;
+}
+
+#
+# Output feature(s) for a given architecture
+#
+sub output_arch_table {
+ my $title = "Feature status on $arch architecture";
+
+ print "=" x length($title) . "\n";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_status;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+ printf "%-${max_size_subsys}s ", $h_subsys;
+ printf "%-${max_size_name}s ", $h_name;
+ printf "%-${max_size_kconfig}s ", $h_kconfig;
+ printf "%-${max_size_status}s ", $h_status;
+ printf "%-${max_size_description}s\n", $h_description;
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_status;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+
+ foreach my $name (sort {
+ ($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
+ ($data{$a}->{name} cmp $data{$b}->{name})
+ } keys %data) {
+ next if ($feat && $name ne $feat);
+
+ my %arch_table = %{$data{$name}->{table}};
+ printf "%-${max_size_subsys}s ", $data{$name}->{subsys};
+ printf "%-${max_size_name}s ", $name;
+ printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig};
+ printf "%-${max_size_status}s ", $arch_table{$arch};
+ printf "%-${max_size_description}s\n", $data{$name}->{description};
+ }
+
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_status;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+}
+
+#
+# Output a feature on all architectures
+#
+sub output_feature {
+ my $title = "Feature $feat";
+
+ print "=" x length($title) . "\n";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+ print ":Subsystem: $data{$feat}->{subsys} \n" if ($data{$feat}->{subsys});
+ print ":Kconfig: $data{$feat}->{kconfig} \n" if ($data{$feat}->{kconfig});
+
+ my $desc = $data{$feat}->{description};
+ $desc =~ s/^([a-z])/\U$1/;
+ $desc =~ s/\.?\s*//;
+ print "\n$desc.\n\n";
+
+ my $com = $data{$feat}->{comments};
+ $com =~ s/^\s+//;
+ $com =~ s/\s+$//;
+ if ($com) {
+ print "Comments\n";
+ print "--------\n\n";
+ print "$com\n\n";
+ }
+
+ print "=" x $max_size_arch;
+ print " ";
+ print "=" x $max_size_status;
+ print "\n";
+
+ printf "%-${max_size_arch}s ", $h_arch;
+ printf "%-${max_size_status}s", $h_status . "\n";
+
+ print "=" x $max_size_arch;
+ print " ";
+ print "=" x $max_size_status;
+ print "\n";
+
+ my %arch_table = %{$data{$feat}->{table}};
+ foreach my $arch (sort keys %arch_table) {
+ printf "%-${max_size_arch}s ", $arch;
+ printf "%-${max_size_status}s\n", $arch_table{$arch};
+ }
+
+ print "=" x $max_size_arch;
+ print " ";
+ print "=" x $max_size_status;
+ print "\n";
+}
+
+#
+# Output all features for all architectures
+#
+
+sub matrix_lines {
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+
+ foreach my $arch (sort keys %archs) {
+ my $len = $max_size_status;
+
+ $len = length($arch) if ($len < length($arch));
+
+ print "=" x $len;
+ print " ";
+ }
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+}
+
+sub output_matrix {
+
+ my $title = "Feature List (feature x architecture)";
+
+ print "=" x length($title) . "\n";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+ matrix_lines;
+
+ printf "%-${max_size_subsys}s ", $h_subsys;
+ printf "%-${max_size_name}s ", $h_name;
+
+ foreach my $arch (sort keys %archs) {
+ printf "%-${max_size_status}s ", $arch;
+ }
+ printf "%-${max_size_kconfig}s ", $h_kconfig;
+ printf "%-${max_size_description}s\n", $h_description;
+
+ matrix_lines;
+
+ foreach my $name (sort {
+ ($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
+ ($data{$a}->{name} cmp $data{$b}->{name})
+ } keys %data) {
+ printf "%-${max_size_subsys}s ", $data{$name}->{subsys};
+ printf "%-${max_size_name}s ", $name;
+
+ my %arch_table = %{$data{$name}->{table}};
+
+ foreach my $arch (sort keys %arch_table) {
+ my $len = $max_size_status;
+
+ $len = length($arch) if ($len < length($arch));
+
+ printf "%-${len}s ", $arch_table{$arch};
+ }
+ printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig};
+ printf "%-${max_size_description}s\n", $data{$name}->{description};
+ }
+
+ matrix_lines;
+}
+
+
+#
+# Parses all feature files located at $prefix dir
+#
+find({wanted =>\&parse_feat, no_chdir => 1}, $prefix);
+
+print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
+
+#
+# Handles the command
+#
+if ($cmd eq "current") {
+ $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
+ $arch =~s/\s+$//;
+}
+
+if ($cmd ne "validate") {
+ if ($arch) {
+ output_arch_table;
+ } elsif ($feat) {
+ output_feature;
+ } else {
+ output_matrix;
+ }
+}
+
+__END__
+
+=head1 NAME
+
+get_feat.pl - parse the Linux Feature files and produce a ReST book.
+
+=head1 SYNOPSIS
+
+B<get_feat.pl> [--debug] [--man] [--help] [--dir=<dir>]
+ [--arch=<arch>] [--feat=<feature>] <COMAND> [<ARGUMENT>]
+
+Where <COMMAND> can be:
+
+=over 8
+
+B<current> - output features for this machine's architecture
+
+B<rest> - output features in ReST markup language
+
+B<validate> - validate the feature contents
+
+=back
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--arch>
+
+Output features for an specific architecture, optionally filtering for
+a single specific feature.
+
+=item B<--feat>
+
+Output features for a single specific architecture.
+
+=item B<--dir>
+
+Changes the location of the Feature files. By default, it uses
+the Documentation/features directory.
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging. Can be called multiple
+times, to increase verbosity.
+
+=item B<--help>
+
+Prints a brief help message and exits.
+
+=item B<--man>
+
+Prints the manual page and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Parse the Linux feature files from Documentation/features (by default),
+optionally producing results at ReST format.
+
+It supports output data per architecture, per feature or a
+feature x arch matrix.
+
+When used with B<rest> command, it will use either one of the tree formats:
+
+If neither B<--arch> or B<--feature> arguments are used, it will output a
+matrix with features per architecture.
+
+If B<--arch> argument is used, it will output the features availability for
+a given architecture.
+
+If B<--feat> argument is used, it will output the content of the feature
+file using ReStructured Text markup.
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
--
2.21.0
^ permalink raw reply related
* [RFC v2 5/8] docs: ABI: create a 2-depth index for ABI
From: Mauro Carvalho Chehab @ 2019-06-22 17:31 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel,
Jonathan Corbet
In-Reply-To: <cover.1561224093.git.mchehab+samsung@kernel.org>
That helps to identify what ABI files are adding titles.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/admin-guide/abi.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/abi.rst b/Documentation/admin-guide/abi.rst
index 3b9645c77469..bcab3ef2597c 100644
--- a/Documentation/admin-guide/abi.rst
+++ b/Documentation/admin-guide/abi.rst
@@ -3,7 +3,7 @@ Linux ABI description
=====================
.. toctree::
- :maxdepth: 1
+ :maxdepth: 2
abi-stable
abi-testing
--
2.21.0
^ permalink raw reply related
* [RFC v2 8/8] docs: Kconfig/Makefile: add a check for broken ABI files
From: Mauro Carvalho Chehab @ 2019-06-22 17:31 UTC (permalink / raw)
To: Linux Doc Mailing List, gregkh
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel,
Jonathan Corbet
In-Reply-To: <cover.1561224093.git.mchehab+samsung@kernel.org>
The files under Documentation/ABI should follow the syntax
as defined at Documentation/ABI/README.
Allow checking if they're following the syntax by running
the ABI parser script on COMPILE_TEST.
With that, when there's a problem with a file under
Documentation/ABI, it would produce a warning like:
Warning: file ./Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats#14:
What '/sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_cor' doesn't have a description
Warning: file ./Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats#21:
What '/sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_fatal' doesn't have a description
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/Kconfig | 11 +++++++++++
Documentation/Makefile | 5 +++++
lib/Kconfig.debug | 2 ++
scripts/get_abi.pl | 14 +++++++++++---
4 files changed, 29 insertions(+), 3 deletions(-)
create mode 100644 Documentation/Kconfig
diff --git a/Documentation/Kconfig b/Documentation/Kconfig
new file mode 100644
index 000000000000..a8b0701c1422
--- /dev/null
+++ b/Documentation/Kconfig
@@ -0,0 +1,11 @@
+config WARN_ABI_ERRORS
+ bool "Warn if there are errors at ABI files"
+ depends on COMPILE_TEST
+ help
+ The files under Documentation/ABI should follow what's
+ described at Documentation/ABI/README. Yet, as they're manually
+ written, it would be possible that some of those files would
+ have errors that would break them for being parsed by
+ scripts/get_abi.pl. Add a check to verify them.
+
+ If unsure, select 'N'.
diff --git a/Documentation/Makefile b/Documentation/Makefile
index e889e7cb8511..c6480ed22884 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -4,6 +4,11 @@
subdir-y := devicetree/bindings/
+# Check for broken ABI files
+ifeq ($(CONFIG_WARN_ABI_ERRORS),y)
+$(shell $(srctree)/scripts/get_abi.pl validate --dir $(srctree)/Documentation/ABI)
+endif
+
# You can set these variables from the command line.
SPHINXBUILD = sphinx-build
SPHINXOPTS =
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index cbdfae379896..b1b7e141ca99 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2110,4 +2110,6 @@ config IO_STRICT_DEVMEM
source "arch/$(SRCARCH)/Kconfig.debug"
+source "Documentation/Kconfig"
+
endmenu # Kernel hacking
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
index 6a4d387ebf3b..e80f9ab2ed26 100755
--- a/scripts/get_abi.pl
+++ b/scripts/get_abi.pl
@@ -47,7 +47,15 @@ my %data;
sub parse_error($$$$) {
my ($file, $ln, $msg, $data) = @_;
- print STDERR "file $file#$ln: $msg at\n\t$data";
+ $data =~ s/\s+$/\n/;
+
+ print STDERR "Warning: file $file#$ln:\n\t$msg";
+
+ if ($data ne "") {
+ print STDERR ". Line\n\t\t$data";
+ } else {
+ print STDERR "\n";
+ }
}
#
@@ -104,7 +112,7 @@ sub parse_abi {
# Invalid, but it is a common mistake
if ($new_tag eq "where") {
- parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", $_);
+ parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", "");
$new_tag = "what";
}
@@ -205,7 +213,7 @@ sub parse_abi {
}
# Everything else is error
- parse_error($file, $ln, "Unexpected line:", $_);
+ parse_error($file, $ln, "Unexpected content", $_);
}
$data{$nametag}->{description} =~ s/^\n+//;
close IN;
--
2.21.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox