* [RFC PATCH v1] EP93XX: Add ADC support
From: Ryan Mallon @ 2009-10-12 20:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20091012142413.30881.62391.stgit@archeopterix.techworks.local>
Christian Gagneraud wrote:
> This patch add support for the ADC found in the EP93XX.
>
> This work is based on S3C platform ADC, apart from hardware related
> stuff, the following modifications have been done:
> - Remove touchscreen support:
> On S3C the TS is a "normal" ADC client, but it has priority over all
> other clients. On EP93XX the TS controller is built-in and offer
> advanced features.
> - Remove convert and select callbacks:
> This was done for the shake of simplicity, it can be added easily.
> - Channel definition:
> On S3c, channel is just an index (unsigned char). On EP93xx channel
> is the analog switch configuration (unsigned long), it gives the
> client full freedom on how to make the analog conversion (including
> routing VRef+ and VRef-, activationg PU/PD resistors, connecting
> pins to VDD/GND, ...)
>
>
> This is a first draft. Comments and criticism welcome.
Hi Christian, some comments below.
>
> Signed-off-by: Christian Gagneraud <cgagneraud@techworks.ie>
> ---
>
> arch/arm/mach-ep93xx/Makefile | 2
> arch/arm/mach-ep93xx/adc.c | 415 +++++++++++++++++++++++
> arch/arm/mach-ep93xx/clock.c | 7
> arch/arm/mach-ep93xx/core.c | 31 ++
> arch/arm/mach-ep93xx/include/mach/adc.h | 54 +++
> arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 21 +
> arch/arm/mach-ep93xx/include/mach/hwmon.h | 43 ++
> arch/arm/mach-ep93xx/ts72xx.c | 78 ++++
> drivers/hwmon/Kconfig | 17 +
> drivers/hwmon/Makefile | 1
> drivers/hwmon/ep93xx-hwmon.c | 416 +++++++++++++++++++++++
> 11 files changed, 1083 insertions(+), 2 deletions(-)
> create mode 100644 arch/arm/mach-ep93xx/adc.c
> create mode 100644 arch/arm/mach-ep93xx/include/mach/adc.h
> create mode 100644 arch/arm/mach-ep93xx/include/mach/hwmon.h
> create mode 100644 drivers/hwmon/ep93xx-hwmon.c
>
> diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
> index eae6199..e3c62fe 100644
> --- a/arch/arm/mach-ep93xx/Makefile
> +++ b/arch/arm/mach-ep93xx/Makefile
> @@ -6,6 +6,8 @@ obj-m :=
> obj-n :=
> obj- :=
>
> +obj-$(CONFIG_EP93XX_ADC) += adc.o
> +
> obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
> obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
> obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
> diff --git a/arch/arm/mach-ep93xx/adc.c b/arch/arm/mach-ep93xx/adc.c
> new file mode 100644
> index 0000000..78dc074
> --- /dev/null
> +++ b/arch/arm/mach-ep93xx/adc.c
> @@ -0,0 +1,415 @@
> +/*
> + * arch/arm/mach-ep93xx/adc.c
> + *
> + * ADC support for Cirrus EP93xx chips.
> + *
> + * Copyright (C) 2009 Christian Gagneraud <cgagneraud@techworks.ie>
> + *
> + * Based on arch/arm/plat-s3c24xx/adc.c by Simtec Electronics
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +
> +/*
> + * Touchscreen and Direct ADC:
> + *
> + * +------------------------+-----+-----+-----+-----+
> + * |ADC/TS driver in use | n/n | y/n | n/y | y/y |
> + * +------------------------+-----+-----+-----+-----+
> + * |SYSCON_DEVCFG_ADCPD | 1 | 0 | 0 | 0 |
> + * |SYSCON_DEVCFG_TIN | X | 1 | 0 | 1/0 |
> + * |SYSCON_KEYTCHCLKDIV_TSEN| 0 | 1 | 1 | 1 |
> + * |TS_SETUP_ENABLE (*) | 0 | 0 | 1 | 0/1 |
> + * +------------------------+-----+-----+-----+-----+
> + * (*)
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +#include <linux/list.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/delay.h>
> +#include <linux/sched.h>
> +
> +#include <mach/hardware.h>
> +
> +static inline void ep93xx_adc_set_reg(void __iomem *reg,
> + unsigned long val)
> +{
> + __raw_writel(EP93XX_TS_SWLOCK_UNLOCK, EP93XX_TS_SWLOCK);
> + __raw_writel(val, reg);
> +}
> +
> +static inline void ep93xx_adc_clr_reg_bits(void __iomem *reg,
> + unsigned long bits)
> +{
> + unsigned long val = __raw_readl(reg);
> + val &= ~bits;
> + ep93xx_adc_set_reg(reg,val);
> +}
> +
> +static inline void ep93xx_adc_set_reg_bits(void __iomem *reg,
> + unsigned long bits)
> +{
> + unsigned long val = __raw_readl(reg);
> + val |= bits;
> + ep93xx_adc_set_reg(reg,val);
> +}
> +
> +struct ep93xx_adc_client {
> + struct platform_device *pdev;
> + struct list_head pend;
> + wait_queue_head_t *wait;
> + unsigned int nr_samples;
> + int result;
> + unsigned int channel;
Tab delimiting can make these easier to read, ie:
struct ep93xx_adc_client {
struct platform_device *pdev;
struct list_head pend;
wait_queue_head_t *wait;
...
};
> +};
> +
> +struct adc_device {
> + struct platform_device *pdev;
> + struct platform_device *owner;
> + struct clk *clk;
> + struct ep93xx_adc_client *cur;
> + void __iomem *regs;
> + int irq;
> + unsigned int refm; /* Reading when Vin = Vref- */
> + unsigned int refp; /* Reading when Vin = Vref+ */
> +};
> +
> +static struct adc_device *adc_dev;
> +
> +static LIST_HEAD(adc_pending);
> +
> +#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
Bit of a nitpick, but can you move the structure definitions and
variable declarations above the first functions in this file.
> +
> +static inline void ep93xx_adc_convert(struct adc_device *adc)
> +{
> + unsigned long prev_switch;
> + unsigned long next_switch;
> +
> + /* Configure the switches */
> + prev_switch = __raw_readl(EP93XX_TS_DIRECT);
> + next_switch = adc->cur->channel;
> + if (next_switch != prev_switch) {
> + ep93xx_adc_set_reg(EP93XX_TS_DIRECT, next_switch);
> + /* Channel switch settling time */
> + /* TODO: depends on clock speed (500us or 2ms) */
> + /* FIXME: the caller has disabled interrupts and the
> + * caller can even be the irq handler. Should we
> + * better fire a timer? */
> + mdelay(2);
Perhaps make the mdelay value a platform data in the meantime then?
> + }
> +
> + /* Fire ADC engine with Sync Data Ready IRQ enabled */
> + ep93xx_adc_set_reg_bits(EP93XX_TS_SETUP2, EP93XX_TS_SETUP2_RINTEN);
> + __raw_readl(EP93XX_TS_XYRESULT);
> +}
> +
> +static void ep93xx_adc_try(struct adc_device *adc)
> +{
> + struct ep93xx_adc_client *next;
> +
> + if (!list_empty(&adc_pending)) {
> + next = list_first_entry(&adc_pending,
> + struct ep93xx_adc_client, pend);
> + list_del(&next->pend);
Are all of the callers of ep93xx_adc_try safely locked?
> + adc_dbg(adc, "new client is %p\n", next);
> + adc->cur = next;
> + ep93xx_adc_convert(adc);
> + }
> +}
> +
> +int ep93xx_adc_start(struct ep93xx_adc_client *client,
> + unsigned long channel, unsigned int nr_samples)
> +{
> + struct adc_device *adc = adc_dev;
> + unsigned long flags;
> +
> + if (!adc) {
> + printk(KERN_ERR "%s: failed to find adc\n", __func__);
Change to:
pr_error("ep93xx_adc: %s: Failed to find adc\n", __func__);
> + return -EINVAL;
> + }
> +
> + local_irq_save(flags);
> +
> + client->channel = channel;
> + client->nr_samples = nr_samples;
> +
> + list_add_tail(&client->pend, &adc_pending);
> +
> + if (!adc->cur)
> + ep93xx_adc_try(adc);
> + local_irq_restore(flags);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ep93xx_adc_start);
> +
> +static void ep93xx_convert_done(struct ep93xx_adc_client *client,
> + unsigned val, unsigned *left)
> +{
> + client->result = val;
> + wake_up(client->wait);
> +}
> +
> +int ep93xx_adc_read(struct ep93xx_adc_client *client, unsigned int ch)
> +{
> + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
> + int ret;
> +
> + client->wait = &wake;
> + client->result = -1;
> +
> + ret = ep93xx_adc_start(client, ch, 1);
> + if (ret < 0)
> + goto err;
> +
> + ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
> + if (client->result < 0) {
> + ret = -ETIMEDOUT;
> + goto err;
> + }
> +
> + return client->result;
> + err:
> + return ret;
> +}
> +
> +EXPORT_SYMBOL_GPL(ep93xx_adc_convert);
The function ep93xx_adc_convert is static inline, so this doesn't make
sense (unless I'm missing something). The s3c code also looks broken is
this regard (s3c_adc_convert isn't used anywhere but the driver). I
think this should be exporting ep93xx_adc_read?
> +
> +struct ep93xx_adc_client *ep93xx_adc_register(struct platform_device *pdev)
> +{
> + struct ep93xx_adc_client *client;
> +
> + printk("adc_register: %s\n", pdev->name);
Do we need to print this? Maybe use pr_debug or dev_dbg?
> +
> + WARN_ON(!pdev);
You dereference pdev above this line so you will have already bugged :-).
> +
> + if (!pdev)
> + return ERR_PTR(-EINVAL);
> +
> + client = kzalloc(sizeof(struct ep93xx_adc_client), GFP_KERNEL);
> + if (!client) {
> + dev_err(&pdev->dev, "no memory for adc client\n");
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + client->pdev = pdev;
> +
> + return client;
> +}
> +
> +EXPORT_SYMBOL_GPL(ep93xx_adc_register);
> +
> +void ep93xx_adc_release(struct ep93xx_adc_client *client)
> +{
> + struct list_head *p, *n;
> + struct ep93xx_adc_client *tmp;
> +
> + /* We should really check that nothing is in progress. */
> + if (adc_dev->cur == client)
> + adc_dev->cur = NULL;
> +
> + list_for_each_safe(p, n, &adc_pending) {
> + tmp = list_entry(p, struct ep93xx_adc_client, pend);
> + if (tmp == client)
> + list_del(&tmp->pend);
> + }
> +
> + if (adc_dev->cur == NULL)
> + ep93xx_adc_try(adc_dev);
> + kfree(client);
> +}
> +
> +EXPORT_SYMBOL_GPL(ep93xx_adc_release);
> +
> +static irqreturn_t ep93xx_adc_irq(int irq, void *pw)
> +{
> + struct adc_device *adc = pw;
> + struct ep93xx_adc_client *client = adc->cur;
> + unsigned long flags;
> + unsigned long data;
> +
> + if (!client) {
> + dev_warn(&adc->pdev->dev, "%s: no adc pending\n",
> + __func__);
> + return IRQ_HANDLED;
> + }
> +
> + /* Read and convert data */
> + data = __raw_readl(EP93XX_TS_XYRESULT);
> + data &= 0x0000FFFF;
data &= 0xffff; is fine.
> + if (data < 0x7000)
> + data += 0x10000;
Nitpick: data |= 0x10000 is a bit more clear.
> + data -= adc->refm;
> +
> + client->nr_samples--;
> +
> + ep93xx_convert_done(client, data, &client->nr_samples);
> +
> + /* If all samples are done, disable IRQ, and kick start the next
> + * one if any. */
This comment doesn't make sense. If all samples are done, kick start the
next one? Am I missing something?
> + if (client->nr_samples == 0) {
> + local_irq_save(flags);
> + adc->cur = NULL;
> + ep93xx_adc_clr_reg_bits(EP93XX_TS_SETUP2,
> + EP93XX_TS_SETUP2_RINTEN);
> + ep93xx_adc_try(adc);
> + local_irq_restore(flags);
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int ep93xx_adc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct adc_device *adc;
> + struct resource *regs;
> + int ret;
> +
> + printk("adc_probe: %s\n", pdev->name);
pr_debug.
> +
> + adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
> + if (adc == NULL) {
> + dev_err(dev, "failed to allocate adc_device\n");
> + return -ENOMEM;
> + }
> +
> + adc->pdev = pdev;
> +
> + adc->irq = platform_get_irq(pdev, 0);
> + if (adc->irq <= 0) {
> + dev_err(dev, "failed to get adc irq\n");
> + ret = -ENOENT;
> + goto err_alloc;
> + }
> +
> + ret = request_irq(adc->irq, ep93xx_adc_irq, IRQF_DISABLED,
> + dev_name(dev), adc);
> + if (ret < 0) {
> + dev_err(dev, "failed to attach adc irq\n");
> + goto err_alloc;
> + }
> +
> + adc->clk = clk_get(dev, "ep93xx-analog");
> + if (IS_ERR(adc->clk)) {
> + dev_err(dev, "failed to get ADC clock\n");
> + ret = PTR_ERR(adc->clk);
> + goto err_irq;
> + }
> +
> + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!regs) {
> + dev_err(dev, "failed to find registers\n");
> + ret = -ENXIO;
> + goto err_clk;
> + }
> +
> + adc->regs = ioremap(regs->start, resource_size(regs));
> + if (!adc->regs) {
> + dev_err(dev, "failed to map registers\n");
> + ret = -ENXIO;
> + goto err_clk;
> + }
> +
> + clk_enable(adc->clk);
> +
> + // Enable ADC, inactivate TS controller
/* */ comments please.
> + ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN,
> + EP93XX_SYSCON_DEVCFG_ADCPD);
> + // Disable TS engine
> + ep93xx_adc_clr_reg_bits(EP93XX_TS_SETUP, EP93XX_TS_SETUP_ENABLE);
> + // Set ADC to signed mode
> + ep93xx_adc_clr_reg_bits(EP93XX_TS_SETUP2, EP93XX_TS_SETUP2_NSIGND);
> +
> + dev_info(dev, "attached adc driver\n");
Don't really need to pollute the dmesg output.
> +
> + platform_set_drvdata(pdev, adc);
> +
> + /* Defaults from datasheet (approximated values) */
> + adc->refm = 0xFFFF - 25000;
Erk, why two different bases? Can we just #define these values somewhere.
> + adc->refp = 25000;
> + adc_dev = adc;
> +
> + return 0;
> +
> + err_clk:
> + clk_put(adc->clk);
clk_disable?
> +
> + err_irq:
> + free_irq(adc->irq, adc);
> +
> + err_alloc:
> + kfree(adc);
> + return ret;
> +
> +}
> +
> +static int ep93xx_adc_remove(struct platform_device *pdev)
> +{
> + struct adc_device *adc = platform_get_drvdata(pdev);
> +
> + iounmap(adc->regs);
> + free_irq(adc->irq, adc);
> + clk_disable(adc->clk);
> + clk_put(adc->clk);
> + kfree(adc);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int ep93xx_adc_suspend(struct platform_device *pdev,
> + pm_message_t state)
> +{
> + struct adc_device *adc = platform_get_drvdata(pdev);
> + ep93xx_devcfg_clear(EP93XX_SYSCON_DEVCFG_ADCPD);
> + clk_disable(adc->clk);
> + return 0;
> +}
> +
> +static int ep93xx_adc_resume(struct platform_device *pdev)
> +{
> + struct adc_device *adc = platform_get_drvdata(pdev);
> + clk_enable(adc->clk);
> + ep93xx_devcfg_set(EP93XX_SYSCON_DEVCFG_ADCPD);
> + return 0;
> +}
> +
> +#else
> +#define ep93xx_adc_suspend NULL
> +#define ep93xx_adc_resume NULL
> +#endif
> +
> +static struct platform_driver ep93xx_adc_driver = {
> + .driver = {
> + .name = "ep93xx-analog",
Why not ep93xx-adc?
> + .owner = THIS_MODULE,
> + },
> + .probe = ep93xx_adc_probe,
> + .remove = __devexit_p(ep93xx_adc_remove),
> + .suspend = ep93xx_adc_suspend,
> + .resume = ep93xx_adc_resume,
> +};
> +
> +static int __init adc_init(void)
> +{
> + int ret;
> +
> + ret = platform_driver_register(&ep93xx_adc_driver);
> + if (ret)
> + printk(KERN_ERR "%s: failed to add adc driver\n",
> + __func__);
pr_error.
> +
> + return ret;
> +}
> +
> +arch_initcall(adc_init);
> diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
> index dda19cd..d604e37 100644
> --- a/arch/arm/mach-ep93xx/clock.c
> +++ b/arch/arm/mach-ep93xx/clock.c
> @@ -72,6 +72,12 @@ static struct clk clk_keypad = {
> .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
> .set_rate = set_keytchclk_rate,
> };
> +static struct clk clk_analog = {
> + .sw_locked = 1,
> + .enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV,
> + .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
> + .set_rate = set_keytchclk_rate,
> +};
> static struct clk clk_pwm = {
> .rate = EP93XX_EXT_CLK_RATE,
> };
> @@ -147,6 +153,7 @@ static struct clk_lookup clocks[] = {
> INIT_CK(NULL, "pll2", &clk_pll2),
> INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
> INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
> + INIT_CK("ep93xx-analog", NULL, &clk_analog),
> INIT_CK("ep93xx-fb", NULL, &clk_video),
> INIT_CK(NULL, "pwm_clk", &clk_pwm),
> INIT_CK(NULL, "m2p0", &clk_m2p0),
> diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
> index f7ebed9..17d3c11 100644
> --- a/arch/arm/mach-ep93xx/core.c
> +++ b/arch/arm/mach-ep93xx/core.c
> @@ -684,6 +684,37 @@ EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
>
>
> /*************************************************************************
> + * EP93xx Analog Touch Screen Interface peripheral handling.
> + * Note: TS and ADC share the same resource
> + *************************************************************************/
> +static struct resource ep93xx_analog_resource[] = {
> + [0] = {
> + .start = EP93XX_TS_PHYS_BASE,
> + .end = EP93XX_TS_PHYS_BASE + 0x24 - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = IRQ_EP93XX_TOUCH,
> + .end = IRQ_EP93XX_TOUCH,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +struct platform_device ep93xx_analog_device = {
> + .name = "ep93xx-analog",
> + .id = -1,
> + .num_resources = ARRAY_SIZE(ep93xx_analog_resource),
> + .resource = ep93xx_analog_resource,
> +};
> +
> +/* HWMON */
> +struct platform_device ep93xx_hwmon_device = {
> + .name = "ep93xx-hwmon",
> + .id = -1,
> + .dev.parent = &ep93xx_analog_device.dev,
> +};
> +
> +/*************************************************************************
> * EP93xx video peripheral handling
> *************************************************************************/
> static struct ep93xxfb_mach_info ep93xxfb_data;
> diff --git a/arch/arm/mach-ep93xx/include/mach/adc.h b/arch/arm/mach-ep93xx/include/mach/adc.h
> new file mode 100644
> index 0000000..c4c6a5a
> --- /dev/null
> +++ b/arch/arm/mach-ep93xx/include/mach/adc.h
> @@ -0,0 +1,54 @@
> +/* arch/arm/mach-ep93xx/include/arch/adc.h
> + *
> + * Copyright 2009, Christian Gagneraud <cgagneraud@techworks.ie>
> + *
> + * Based on arch/arm/plat-s3c/include/plat/adc.h by Simtec Electronics
> + *
> + * EP93XX ADC driver information
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#ifndef __ASM_ARCH_ADC_H
> +#define __ASM_ARCH_ADC_H __FILE__
> +
> +/* ADC Channels definition (switches) */
> +#define ADC_SW_XP_IN (1<<0)
> +#define ADC_SW_XM_IN (1<<1)
> +#define ADC_SW_YP_IN (1<<2)
> +#define ADC_SW_YM_IN (1<<3)
> +#define ADC_SW_SXP_IN (1<<4)
> +#define ADC_SW_SXM_IN (1<<5)
> +#define ADC_SW_SYP_IN (1<<6)
> +#define ADC_SW_SYM_IN (1<<7)
> +#define ADC_SW_VBAT_IN (1<<8)
> +#define ADC_SW_AVDD_REFP (1<<9)
> +#define ADC_SW_AGND_REFM (1<<10)
> +#define ADC_SW_SXP_REFP (1<<24)
> +#define ADC_SW_SXM_REFM (1<<25)
> +#define ADC_SW_SYP_REFP (1<<26)
> +#define ADC_SW_SYM_REFM (1<<27)
> +#define ADC_SW_DAC_IN (1<<29)
> +#define ADC_SW_IN_LOAD (1<<30)
Nitpick, spaces around <<
> +
> +/* AGND as VREF-, AVDD as VREF+ */
> +#define ADC_SW_APWR_REF (ADC_SW_AVDD_REFP|ADC_SW_AGND_REFM)
Spaces around |
> +
> +struct ep93xx_adc_client;
> +
> +extern struct platform_device ep93xx_analog_device;
> +
> +extern int ep93xx_adc_start(struct ep93xx_adc_client *client,
> + unsigned int channel, unsigned int nr_samples);
> +
> +extern int ep93xx_adc_read(struct ep93xx_adc_client *client,
> + unsigned int ch);
> +
> +extern struct ep93xx_adc_client *ep93xx_adc_register(struct platform_device
> + *pdev);
> +
> +extern void ep93xx_adc_release(struct ep93xx_adc_client *client);
> +
> +#endif /* __ASM_ARCH_ADC_H */
> diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
> index 0fbf87b..7453c08 100644
> --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
> +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
> @@ -145,8 +145,25 @@
>
> #define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000)
>
> -#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000)
> -#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000)
> +/* Note:
> + * The EP9301 and EP9302 processors support a general 12-bit ADC, but
> + * no touchscreen, the EP9307, EP9312 and EP9315 processors each
> + * support up to an 8-wire touch screen or a general 12-bit ADC
> + */
> +#define EP93XX_TS_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00100000)
> +#define EP93XX_TS_BASE EP93XX_APB_IOMEM(0x00100000)
> +#define EP93XX_TS_REG(x) (EP93XX_TS_BASE + (x))
> +#define EP93XX_TS_SETUP EP93XX_TS_REG(0x00)
> +#define EP93XX_TS_SETUP_ENABLE (1<<15)
> +#define EP93XX_TS_XYRESULT EP93XX_TS_REG(0x08)
> +#define EP93XX_TS_XYRESULT_SDR (1<<31)
> +#define EP93XX_TS_DIRECT EP93XX_TS_REG(0x18)
> +#define EP93XX_TS_SWLOCK EP93XX_TS_REG(0x20)
> +#define EP93XX_TS_SWLOCK_UNLOCK 0x000000AA
> +#define EP93XX_TS_SETUP2 EP93XX_TS_REG(0x24)
> +#define EP93XX_TS_SETUP2_RINTEN (1<<11)
> +#define EP93XX_TS_SETUP2_NSIGND (1<<9)
> +
>
> #define EP93XX_PWM_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00110000)
> #define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000)
> diff --git a/arch/arm/mach-ep93xx/include/mach/hwmon.h b/arch/arm/mach-ep93xx/include/mach/hwmon.h
> new file mode 100644
> index 0000000..fec3db9
> --- /dev/null
> +++ b/arch/arm/mach-ep93xx/include/mach/hwmon.h
> @@ -0,0 +1,43 @@
> +/* linux/arch/arm/mach-ep93xx/include/arch/hwmon.h
> + *
> + * Copyright (C) 2009 Christian Gagneraud <cgagneraud@techworks.ie>
> + *
> + * Based on linux/arch/arm/plat-s3c/include/plat/hwmon.h by Simtec Electronics
> + *
> + * EP93XX - HWMon interface for ADC
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#ifndef __ASM_ARCH_HWMON_H
> +#define __ASM_ARCH_HWMON_H __FILE__
Stray __FILE__?
> +
> +extern struct platform_device ep93xx_hwmon_device;
> +
> +/**
> + * ep93xx_hwmon_chcfg - channel configuration
> + * @name: The name to give this channel.
> + * @mult: Multiply the ADC value read by this.
> + * @div: Divide the value from the ADC by this.
> + *
> + * The value read from the ADC is converted to a value that
> + * hwmon expects (mV) by result = (value_read * @mult) / @div.
> + */
> +struct ep93xx_hwmon_chcfg {
> + const char *name;
> + unsigned long channel;
> + unsigned long mult;
> + unsigned long div;
> +};
> +
> +/**
> + * ep93xx_hwmon_pdata - HWMON platform data
> + * @in: One configuration for each possible channel used.
> + */
> +struct ep93xx_hwmon_data {
> + struct ep93xx_hwmon_chcfg *in[7];
> +};
> +
> +#endif /* __ASM_ARCH_HWMON_H */
> diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> index 259f782..2bbf05b 100644
> --- a/arch/arm/mach-ep93xx/ts72xx.c
> +++ b/arch/arm/mach-ep93xx/ts72xx.c
> @@ -18,6 +18,8 @@
> #include <linux/mtd/physmap.h>
>
> #include <mach/hardware.h>
> +#include <mach/adc.h>
> +#include <mach/hwmon.h>
> #include <mach/ts72xx.h>
>
> #include <asm/mach-types.h>
> @@ -92,6 +94,8 @@ static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = {
> }
> };
>
> +static struct ep93xx_hwmon_data ts72xx_hwmon_info;
> +
> static void __init ts72xx_map_io(void)
> {
> ep93xx_map_io();
> @@ -109,6 +113,8 @@ static void __init ts72xx_map_io(void)
> ARRAY_SIZE(ts72xx_nand_io_desc));
> }
> }
> +
> + ep93xx_hwmon_device.dev.platform_data = &ts72xx_hwmon_info;
> }
>
> /*************************************************************************
> @@ -170,6 +176,74 @@ static struct ep93xx_eth_data ts72xx_eth_data = {
> .phy_id = 1,
> };
>
> +
> +#define TS72XX_ADC0 (ADC_SW_YM_IN | ADC_SW_APWR_REF)
> +#define TS72XX_ADC1 (ADC_SW_SXP_IN | ADC_SW_APWR_REF)
> +#define TS72XX_ADC2 (ADC_SW_SXM_IN | ADC_SW_APWR_REF)
> +#define TS72XX_ADC3 (ADC_SW_SYP_IN | ADC_SW_APWR_REF)
> +#define TS72XX_ADC4 (ADC_SW_SYM_IN | ADC_SW_APWR_REF)
> +
> +// TODO: board dependant
> +// TS-7200: ADC0, ADC4
> +// TS-7250: ADC0 to ADC4
> +// TS-7260: Vin, 5V_104, ADC2, Vcore, ADC4
> +// TS-7300: 5V, 1.2V, ADC2, 1.8V, ADC4
> +
> +// 0V gives 0, 3.3V gives c. 50000
> +// TODO: self calibrate by using VBAT and Load resistor switches
/* */ comments please.
> +static struct ep93xx_hwmon_data ts72xx_hwmon_info = {
> + /* POWER_IN*10K/150K (4.5-20V) */
> + .in[0] = &(struct ep93xx_hwmon_chcfg) {
That cast looks really ugly, is there a better way?
> + .name = "ts72xx-vin",
> + .channel = TS72XX_ADC0,
> + .mult = 33*(15+1),
> + .div = 500*1,
Spaces around operators please. Also why the explict multiplies
(especially by 1)?
> + },
> + /* PC104_5V*10K/54.9K (5V) */
> + .in[1] = &(struct ep93xx_hwmon_chcfg) {
> + .name = "ts72xx-v5",
> + .channel = TS72XX_ADC4,
> + .mult = 33*(549+100),
> + .div = 500*100,
> + },
> + /* Vcore (1.8V) */
> + .in[2] = &(struct ep93xx_hwmon_chcfg) {
> + .name = "ts72xx-vcore",
> + .channel = TS72XX_ADC2,
> + .mult = 33*1,
> + .div = 500*1,
> + },
> + /* User ADC on DIO2.8 (0-3.3V) */
> + .in[3] = &(struct ep93xx_hwmon_chcfg) {
> + .name = "ts72xx-dio2.8",
> + .channel = TS72XX_ADC3,
> + .mult = 33*1,
> + .div = 500*1,
> + },
> + /* User ADC on DIO2.10 (0-3.3V) */
> + .in[4] = &(struct ep93xx_hwmon_chcfg) {
> + .name = "ts72xx-dio2.10",
> + .channel = TS72XX_ADC1,
> + .mult = 33*1,
> + .div = 500*1,
> + },
> + /* EP93XX.VBAT (1.8V) */
> + .in[5] = &(struct ep93xx_hwmon_chcfg) {
> + .name = "ep93xx-vbat",
> + .channel = ADC_SW_VBAT_IN|ADC_SW_APWR_REF,
> + .mult = 33*1,
> + .div = 500*1,
> + },
> + /* EP93XX.DAC (?) */
> + .in[6] = &(struct ep93xx_hwmon_chcfg) {
> + .name = "ep93xx-vdac",
> + .channel = ADC_SW_DAC_IN|ADC_SW_APWR_REF,
> + .mult = 33*1,
> + .div = 500*1,
> + },
> +};
> +
> +
> static void __init ts72xx_init_machine(void)
> {
> ep93xx_init_devices();
> @@ -177,6 +251,10 @@ static void __init ts72xx_init_machine(void)
> platform_device_register(&ts72xx_rtc_device);
>
> ep93xx_register_eth(&ts72xx_eth_data, 1);
> +
> + platform_device_register(&ep93xx_analog_device);
> +
> + platform_device_register(&ep93xx_hwmon_device);
> }
>
> MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 700e93a..af6f08a 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -690,6 +690,23 @@ config SENSORS_S3C_RAW
> Say Y here if you want to include raw copies of all the ADC
> channels in sysfs.
>
> +config SENSORS_EP93XX
> + tristate "EP93XX on-chip ADC"
> + depends on ARCH_EP93XX
> + help
> + If you say yes here you get support for the on-board ADCs of
> + the Cirrus Logic EP93XX series of SoC
> +
> + This driver can also be built as a module. If so, the module
> + will be called ep93xx-hwmo.
> +
> +config SENSORS_EP93XX_RAW
> + bool "Include raw channel attributes in sysfs"
> + depends on SENSORS_EP93XX
> + help
> + Say Y here if you want to include raw copies of all the ADC
> + channels in sysfs.
> +
> config SENSORS_SIS5595
> tristate "Silicon Integrated Systems Corp. SiS5595"
> depends on PCI
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 9f46cb0..eea13fc 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -77,6 +77,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
> obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
> obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
> obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
> +obj-$(CONFIG_SENSORS_EP93XX) += ep93xx-hwmon.o
> obj-$(CONFIG_SENSORS_SHT15) += sht15.o
> obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
> obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
> diff --git a/drivers/hwmon/ep93xx-hwmon.c b/drivers/hwmon/ep93xx-hwmon.c
> new file mode 100644
> index 0000000..2e4a9f7
> --- /dev/null
> +++ b/drivers/hwmon/ep93xx-hwmon.c
> @@ -0,0 +1,416 @@
> +/* linux/drivers/hwmon/ep93xx-hwmon.c
> + *
> + * Copyright 2009, Christian Gagneraud <cgagneraud@techworks.ie>
> + *
> + * Based on linux/drivers/hwmon/s3c-hwmon.c by Simtec Electronics
> + *
> + * EP93XX ADC hwmon support
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> +*/
> +
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/init.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +#include <mach/adc.h>
> +#include <mach/hwmon.h>
> +
> +struct ep93xx_hwmon_attr {
> + struct sensor_device_attribute in;
> + struct sensor_device_attribute label;
> + char in_name[12];
> + char label_name[12];
> +};
> +
> +/**
> + * struct ep93xx_hwmon - ADC hwmon client information
> + * @lock: Access lock to serialise the conversions.
> + * @client: The client we registered with the EP93XX ADC core.
> + * @hwmon_dev: The hwmon device we created.
> + * @attr: The holders for the channel attributes.
> +*/
> +struct ep93xx_hwmon {
> + struct semaphore lock;
> + struct ep93xx_adc_client *client;
> + struct device *hwmon_dev;
> + struct ep93xx_hwmon_attr attrs[7];
> +};
> +
> +/**
> + * ep93xx_hwmon_read_ch - read a value from a given adc channel.
> + * @dev: The device.
> + * @hwmon: Our state.
> + * @channel: The channel we're reading from.
> + *
> + * Read a value from the @channel with the proper locking and sleep until
> + * either the read completes or we timeout awaiting the ADC core to get
> + * back to us.
> + */
> +static int ep93xx_hwmon_read_ch(struct device *dev,
> + struct ep93xx_hwmon *hwmon, int channel)
> +{
> + int ret;
> +
> + ret = down_interruptible(&hwmon->lock);
> + if (ret < 0)
> + return ret;
> +
> + dev_dbg(dev, "reading channel %d\n", channel);
> +
> + ret = ep93xx_adc_read(hwmon->client, channel);
> + up(&hwmon->lock);
> +
> + return ret;
> +}
> +
> +#ifdef CONFIG_SENSORS_EP93XX_RAW
> +/**
> + * ep93xx_hwmon_show_raw - show a conversion from the raw channel number.
> + * @dev: The device that the attribute belongs to.
> + * @attr: The attribute being read.
> + * @buf: The result buffer.
> + *
> + * This show deals with the raw attribute, registered for each possible
> + * ADC channel. This does a conversion and returns the raw (un-scaled)
> + * value returned from the hardware.
> + */
> +static ssize_t ep93xx_hwmon_show_raw(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct ep93xx_hwmon *adc =
> + platform_get_drvdata(to_platform_device(dev));
> + struct sensor_device_attribute *sa = to_sensor_dev_attr(attr);
> + struct ep93xx_hwmon_data *pdata = dev->platform_data;
> + struct ep93xx_hwmon_chcfg *cfg;
> + int ret;
> +
> + cfg = pdata->in[sa->index];
> +
> + ret = ep93xx_hwmon_read_ch(dev, adc, cfg->channel);
> +
> + return (ret < 0) ? ret : snprintf(buf, PAGE_SIZE, "%d\n", ret);
> +}
> +
> +#define DEF_ADC_ATTR(x) \
> + static SENSOR_DEVICE_ATTR(adc##x##_raw, S_IRUGO, ep93xx_hwmon_show_raw, NULL, x)
> +
> +DEF_ADC_ATTR(0);
> +DEF_ADC_ATTR(1);
> +DEF_ADC_ATTR(2);
> +DEF_ADC_ATTR(3);
> +DEF_ADC_ATTR(4);
> +DEF_ADC_ATTR(5);
> +DEF_ADC_ATTR(6);
> +
> +static struct attribute *ep93xx_hwmon_attrs[8] = {
> + &sensor_dev_attr_adc0_raw.dev_attr.attr,
> + &sensor_dev_attr_adc1_raw.dev_attr.attr,
> + &sensor_dev_attr_adc2_raw.dev_attr.attr,
> + &sensor_dev_attr_adc3_raw.dev_attr.attr,
> + &sensor_dev_attr_adc4_raw.dev_attr.attr,
> + &sensor_dev_attr_adc5_raw.dev_attr.attr,
> + &sensor_dev_attr_adc6_raw.dev_attr.attr,
> + NULL,
> +};
> +
> +static struct attribute_group ep93xx_hwmon_attrgroup = {
> + .attrs = ep93xx_hwmon_attrs,
> +};
> +
> +static inline int ep93xx_hwmon_add_raw(struct device *dev)
> +{
> + return sysfs_create_group(&dev->kobj, &ep93xx_hwmon_attrgroup);
> +}
> +
> +static inline void ep93xx_hwmon_remove_raw(struct device *dev)
> +{
> + sysfs_remove_group(&dev->kobj, &ep93xx_hwmon_attrgroup);
> +}
> +
> +#else
> +
> +static inline void ep93xx_hwmon_add_raw(struct device *dev)
> +{
> +}
> +
> +static inline void ep93xx_hwmon_remove_raw(struct device *dev)
> +{
> +}
> +
> +#endif /* CONFIG_SENSORS_EP93XX_RAW */
> +
> +/**
> + * ep93xx_hwmon_ch_show - show value of a given channel
> + * @dev: The device that the attribute belongs to.
> + * @attr: The attribute being read.
> + * @buf: The result buffer.
> + *
> + * Read a value from the ADC and scale it before returning it to the
> + * caller. The scale factor is gained from the channel configuration
> + * passed via the platform data when the device was registered.
> + */
> +static ssize_t ep93xx_hwmon_ch_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct sensor_device_attribute *sen_attr =
> + to_sensor_dev_attr(attr);
> + struct ep93xx_hwmon *hwmon =
> + platform_get_drvdata(to_platform_device(dev));
> + struct ep93xx_hwmon_data *pdata = dev->platform_data;
> + struct ep93xx_hwmon_chcfg *cfg;
> + int ret;
> +
> + cfg = pdata->in[sen_attr->index];
> +
> + ret = ep93xx_hwmon_read_ch(dev, hwmon, cfg->channel);
> + if (ret < 0)
> + return ret;
> +
> + ret *= cfg->mult;
> + ret = DIV_ROUND_CLOSEST(ret, cfg->div);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", ret);
> +}
> +
> +/**
> + * ep93xx_hwmon_label_show - show label name of the given channel.
> + * @dev: The device that the attribute belongs to.
> + * @attr: The attribute being read.
> + * @buf: The result buffer.
> + *
> + * Return the label name of a given channel
> + */
> +static ssize_t ep93xx_hwmon_label_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct sensor_device_attribute *sen_attr =
> + to_sensor_dev_attr(attr);
> + struct ep93xx_hwmon_data *pdata = dev->platform_data;
> + struct ep93xx_hwmon_chcfg *cfg;
> +
> + cfg = pdata->in[sen_attr->index];
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n", cfg->name);
> +}
> +
> +/**
> + * ep93xx_hwmon_create_attr - create hwmon attribute for given channel.
> + * @dev: The device to create the attribute on.
> + * @cfg: The channel configuration passed from the platform data.
> + * @channel: The ADC channel number to process.
> + *
> + * Create the scaled attribute for use with hwmon from the specified
> + * platform data in @pdata. The sysfs entry is handled by the routine
> + * ep93xx_hwmon_ch_show().
> + *
> + * The attribute name is taken from the configuration data if present
> + * otherwise the name is taken by concatenating in_ with the channel
> + * number.
> + */
> +static int ep93xx_hwmon_create_attr(struct device *dev,
> + struct ep93xx_hwmon_chcfg *cfg,
> + struct ep93xx_hwmon_attr *attrs,
> + int channel)
> +{
> + struct sensor_device_attribute *attr;
> + int ret;
> +
> + snprintf(attrs->in_name, sizeof(attrs->in_name), "in%d_input",
> + channel);
> +
> + attr = &attrs->in;
> + attr->index = channel;
> + attr->dev_attr.attr.name = attrs->in_name;
> + attr->dev_attr.attr.mode = S_IRUGO;
> + attr->dev_attr.attr.owner = THIS_MODULE;
> + attr->dev_attr.show = ep93xx_hwmon_ch_show;
> +
> + ret = device_create_file(dev, &attr->dev_attr);
> + if (ret < 0) {
> + dev_err(dev, "failed to create input attribute\n");
> + return ret;
> + }
> +
> + /* if this has a name, add a label */
> + if (cfg->name) {
> + snprintf(attrs->label_name, sizeof(attrs->label_name),
> + "in%d_label", channel);
> +
> + attr = &attrs->label;
> + attr->index = channel;
> + attr->dev_attr.attr.name = attrs->label_name;
> + attr->dev_attr.attr.mode = S_IRUGO;
> + attr->dev_attr.attr.owner = THIS_MODULE;
> + attr->dev_attr.show = ep93xx_hwmon_label_show;
> +
> + ret = device_create_file(dev, &attr->dev_attr);
> + if (ret < 0) {
> + device_remove_file(dev, &attrs->in.dev_attr);
> + dev_err(dev, "failed to create label attribute\n");
> + }
> + }
> +
> + return ret;
> +}
> +
> +static void ep93xx_hwmon_remove_attr(struct device *dev,
> + struct ep93xx_hwmon_attr *attrs)
> +{
> + device_remove_file(dev, &attrs->in.dev_attr);
> + device_remove_file(dev, &attrs->label.dev_attr);
> +}
> +
> +/**
> + * ep93xx_hwmon_probe - device probe entry.
> + * @dev: The device being probed.
> +*/
> +static int __devinit ep93xx_hwmon_probe(struct platform_device *dev)
> +{
> + struct ep93xx_hwmon_data *pdata = dev->dev.platform_data;
> + struct ep93xx_hwmon *hwmon;
> + int ret = 0;
> + int i;
> +
> + if (!pdata) {
> + dev_err(&dev->dev, "no platform data supplied\n");
> + return -EINVAL;
> + }
> +
> + hwmon = kzalloc(sizeof(struct ep93xx_hwmon), GFP_KERNEL);
> + if (hwmon == NULL) {
> + dev_err(&dev->dev, "no memory\n");
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(dev, hwmon);
> +
> + init_MUTEX(&hwmon->lock);
> +
> + /* Register with the core ADC driver. */
> +
> + hwmon->client = ep93xx_adc_register(dev);
> + if (IS_ERR(hwmon->client)) {
> + dev_err(&dev->dev, "cannot register adc\n");
> + ret = PTR_ERR(hwmon->client);
> + goto err_mem;
> + }
> +
> + /* add attributes for our adc devices. */
> +
> + ret = ep93xx_hwmon_add_raw(&dev->dev);
> + if (ret)
> + goto err_registered;
> +
> + /* register with the hwmon core */
> +
> + hwmon->hwmon_dev = hwmon_device_register(&dev->dev);
> + if (IS_ERR(hwmon->hwmon_dev)) {
> + dev_err(&dev->dev, "error registering with hwmon\n");
> + ret = PTR_ERR(hwmon->hwmon_dev);
> + goto err_raw_attribute;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(pdata->in); i++) {
> + if (!pdata->in[i])
> + continue;
> +
> + if (pdata->in[i]->mult >= 0x10000)
> + dev_warn(&dev->dev,
> + "channel %d multiplier too large\n", i);
> +
> + ret = ep93xx_hwmon_create_attr(&dev->dev, pdata->in[i],
> + &hwmon->attrs[i], i);
> + if (ret) {
> + dev_err(&dev->dev,
> + "error creating channel %d\n", i);
> +
> + for (i--; i >= 0; i--)
> + ep93xx_hwmon_remove_attr(&dev->dev,
> + &hwmon->attrs[i]);
> +
> + goto err_hwmon_register;
> + }
> + }
> +
> + return 0;
> +
> + err_hwmon_register:
> + hwmon_device_unregister(hwmon->hwmon_dev);
> +
> + err_raw_attribute:
> + ep93xx_hwmon_remove_raw(&dev->dev);
> +
> + err_registered:
> + ep93xx_adc_release(hwmon->client);
> +
> + err_mem:
> + kfree(hwmon);
> + return ret;
> +}
> +
> +static int __devexit ep93xx_hwmon_remove(struct platform_device *dev)
> +{
> + struct ep93xx_hwmon *hwmon = platform_get_drvdata(dev);
> + int i;
> +
> + ep93xx_hwmon_remove_raw(&dev->dev);
> +
> + for (i = 0; i < ARRAY_SIZE(hwmon->attrs); i++)
> + ep93xx_hwmon_remove_attr(&dev->dev, &hwmon->attrs[i]);
> +
> + hwmon_device_unregister(hwmon->hwmon_dev);
> + ep93xx_adc_release(hwmon->client);
> +
> + return 0;
> +}
> +
> +static struct platform_driver ep93xx_hwmon_driver = {
> + .driver = {
> + .name = "ep93xx-hwmon",
> + .owner = THIS_MODULE,
> + },
> + .probe = ep93xx_hwmon_probe,
> + .remove = __devexit_p(ep93xx_hwmon_remove),
> +};
> +
> +static int __init ep93xx_hwmon_init(void)
> +{
> + return platform_driver_register(&ep93xx_hwmon_driver);
> +}
> +
> +static void __exit ep93xx_hwmon_exit(void)
> +{
> + platform_driver_unregister(&ep93xx_hwmon_driver);
> +}
> +
> +module_init(ep93xx_hwmon_init);
> +module_exit(ep93xx_hwmon_exit);
> +
> +MODULE_AUTHOR("Christian Gagneraud <cgagneraud@techworks.ie>");
> +MODULE_DESCRIPTION("EP93XX ADC HWMon driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:ep93xx-hwmon");
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Bluewater Systems Ltd - ARM Technology Solution Centre
Ryan Mallon 5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com New Zealand
Phone: +64 3 3779127 Freecall: Australia 1800 148 751
Fax: +64 3 3779135 USA 1800 261 2934
^ permalink raw reply
* Re: 2.6.32-rc4: Reported regressions from 2.6.31
From: David Woodhouse @ 2009-10-12 20:29 UTC (permalink / raw)
To: Linus Torvalds
Cc: Rafael J. Wysocki, Greg Kroah-Hartman, Linux Kernel Mailing List,
Adrian Bunk, Andrew Morton, Natalie Protasevich
In-Reply-To: <alpine.LFD.2.01.0910121028040.3438@localhost.localdomain>
On Mon, 2009-10-12 at 18:35 +0100, Linus Torvalds wrote:
>
> On Mon, 12 Oct 2009, David Woodhouse wrote:
> >
> > > The other solution would be to just _enable_ (and do all the setup) of the
> > > IOMMU early. And then just leave a legacy mapping for the IOMMU, and then
> > > _after_all_devices_are_set_up_ can you then remove the legacy mapping.
> >
> > That involves allocating a _shitload_ of page tables for a 1:1 mapping
> > of all of physical memory.
>
> I don't think that's true.
>
> Nobody cares about "all physical memory". For one thing, we know that
> anything that we consider to be normal memory (ie it's listed in the e820
> tables as RAM) can't be all that interesting, since the BIOS definitely
> released that to us.
Yeah, that's probably true. I was thinking of the 1:1 mappings we set up
for crappy drivers under Linux, which do need access to all of memory
and don't use the DMA API correctly. This is different, though.
We have talked about dma-mapping all of E820-reserved memory, but that
would allow a rogue device to scribble over arbitrary bits of memory
belonging to the BIOS, which isn't necessarily such a good thing. Even
if we did tear it down as soon as a real driver came along, the TXT
folks would still object -- and rightly so.
As you said, it's sufficient just to enable the IOMMU after the quirks
have run. So the patches I posted earlier should be just fine.
--
David Woodhouse Open Source Technology Centre
David.Woodhouse@intel.com Intel Corporation
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] tcg, tci: Add TCG and interpreter for bytecode (virtual machine)
From: Stuart Brady @ 2009-10-12 20:30 UTC (permalink / raw)
To: malc; +Cc: qemu-devel
In-Reply-To: <Pine.LNX.4.64.0910130005500.2227@linmac.oyster.ru>
On Tue, Oct 13, 2009 at 12:07:01AM +0400, malc wrote:
> On Mon, 12 Oct 2009, Stuart Brady wrote:
>
> > I'm quite aware that functions must be invoked using the *correct type*
> > of function pointer, though. Perhaps I wasn't specific enough in what
> > I said, but please, I'm not completely clueless... :-)
>
> Are you thinking of a giant switch here, or what?
Yes.
Cheers,
--
Stuart Brady
^ permalink raw reply
* [Buildroot] setting up buildroot for using OLD gcc / binutils
From: W.P. @ 2009-10-12 20:28 UTC (permalink / raw)
To: buildroot
In-Reply-To: <87my3w4bw6.fsf@macbook.be.48ers.dk>
U?ytkownik Peter Korsgaard napisa?:
>>>>>> "W" == W P <laurentp@wp.pl> writes:
>>>>>>
>
> W> Hi,
> W> how can I set up CURRENT buildroot to use OLD gcc/binutils/kernel/uClibc?
> W> I need gcc 3.4.4, kernel 2.6.12.6-venus, uClibc 0.9.28?
>
> Some older toolchain versions are available if you enable BR_DEPRECATED
> (Build options->Show packages that are deprecated or obsolete). It won't
> give you those exact options, but it might be close enough.
>
>
Almost :(
With choosing this option I am able to select gcc down-to 3.4.6,
binutils 2.17, uClibc 0.9.28.3, kernel 2.6.2x ...
Could you point me to the file where are these choices are in? If I know
in what file, then adding an option ex. to gcc 3.4.4 instead of 3.4.6
should be easy...
W.P.
^ permalink raw reply
* Re: 2.6.31.[12] ath5k regression
From: Richard Zidlicky @ 2009-10-12 20:23 UTC (permalink / raw)
To: Bob Copeland; +Cc: linux-wireless
In-Reply-To: <20091011222142.M14763@bobcopeland.com>
On Sun, Oct 11, 2009 at 06:23:56PM -0400, Bob Copeland wrote:
> On Mon, 12 Oct 2009 00:00:02 +0200, Richard Zidlicky wrote:
> > so the results are same like before. The printk message came once only,
> > I will try to gather more debug info tomorrow.
>
> Meaning it works the same as with your change (replacing "chan != null"
> with "true") or it works the same as mainline, i.e. it fails?
it works like in mainline and fails.
Richard
^ permalink raw reply
* Re: [trivial PATCH] fix typo in nmi.c of apic
From: Ingo Molnar @ 2009-10-12 20:26 UTC (permalink / raw)
To: Jiri Kosina, Thomas Gleixner, H. Peter Anvin; +Cc: Luming Yu, LKML
In-Reply-To: <alpine.LSU.2.00.0910091706350.19284@wotan.suse.de>
* Jiri Kosina <jkosina@suse.cz> wrote:
> On Fri, 11 Sep 2009, Luming Yu wrote:
>
> > I came across x86/kernel/apic/nmi.c and found several typo.
> > It's trivial in terms of doing nothing on changing execution logic.
> >
> > Please review. If make sense, please apply.
>
> Hi,
>
> I'd rather go this through x86 tree. Adding Ingo.
>
> > Ps. The patch is enclosed in attachment. The inline one
> > is c&p of it for reading.
> >
> >
> > Thanks,
> > Luming
> >
> > Signed-off-by: Yu Luming <luming.yu@intel.com>
> >
> > nmi.c | 18 +++++++++---------
> > 1 file changed, 9 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
> > index b3025b4..9ff1f6d 100644
> > --- a/arch/x86/kernel/apic/nmi.c
> > +++ b/arch/x86/kernel/apic/nmi.c
> > @@ -121,7 +121,7 @@ static void report_broken_nmi(int cpu, unsigned
> > int *prev_nmi_count)
> > atomic_dec(&nmi_active);
> > }
> >
> > -static void __acpi_nmi_disable(void *__unused)
> > +static void __apic_nmi_disable(void *__unused)
that's correctly named, as a 'git grep acpi_nmi_disable' should reveal.
Ingo
^ permalink raw reply
* Re: [PATCH 3/3] extend get/setrlimit to support setting rlimits external to a process (v6)
From: Neil Horman @ 2009-10-12 20:25 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, marcin.slusarz
In-Reply-To: <20091012201304.GG32088@hmsreliant.think-freely.org>
Define __NR_getprlimit and __NR_setprlimit syscalls for asm-generic
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
unistd.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index d76b66a..4912f71 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -623,8 +623,13 @@ __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
#define __NR_perf_event_open 241
__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
+#define __NR_getprlimit 242
+__SYSCALL(__NR_getprlimit, sys_getprlimit)
+#define __NR_setprlimit 243
+__SYSCALL(__NR_setprlimit, sys_setprlimit)
+
#undef __NR_syscalls
-#define __NR_syscalls 242
+#define __NR_syscalls 244
/*
* All syscalls below here should go away really,
^ permalink raw reply related
* Re: [patch] Staging: hv: Fix vmbus load hang caused by wrong data packing
From: Greg KH @ 2009-10-12 20:22 UTC (permalink / raw)
To: Hank Janssen
Cc: Haiyang Zhang, linux-kernel@vger.kernel.org, Tom Hanrahan,
Hashir Abdi
In-Reply-To: <8AFC7968D54FB448A30D8F38F259C5620E7B1C22@TK5EX14MBXC114.redmond.corp.microsoft.com>
On Mon, Oct 12, 2009 at 08:10:40PM +0000, Hank Janssen wrote:
>
> >Odd quoting style :(
>
> We like to keep things lively :)
>
> >> Based on our testing, the #pragma pack(push,1) can pack the data
> >> correctly for the HyperV to use, but __attribute__((packed)) couldn't
> >> do this right.
> >
> >Why? What does gcc generate differently? This should be identical.
>
> It should, but in practice in this case it does not seem to behave the same
> Way.
Can you figure out why? What is the output of gcc for both ways?
Can you show what is fixed by this change?
Also note that #pragma packed is not supported by older versions of gcc,
so I don't think that it would work at all on some compiler versions
that are still legal to use for the kernel. But I'm not quite sure when
it was added, so I might be wrong.
> >Ideally, we don't deal with packed structures at all, but with offsets
> >in memory and pick out the proper fields and put them into new
> >structures if you want to use them that way. How hard would that be to
> >do here instead?
>
> It is something that I want to look at in the future. Our primary focus
> Is to get the bug fixed. We cannot do the offset way in the time we
> Have before 2.6.32 closes and still be comfortable we have gone through
> The extensive testing cycle we do on our side.
I can't take this patch until I see what the root problem is here,
sorry.
> >I still want to figure out what the real difference here is. Especially
> >as I removed a lot of the #pragma pack(push,1) lines from the hv code.
> >If it really is different, all of those patches should be reverted,
> >right?
>
> Not sure yet if they need to be reverted, after we fixed this bug last week
> We are getting another one, it was masked by the one we just fixed.
> We are checking into that right now;
>
> BUG: unable to handle kernel NULL pointer dereference at (null)
What is the rest of the oops message? That's pretty hard to determine
anything from :)
thanks,
greg k-h
^ permalink raw reply
* Re: [REGRESSION] "bind" a device to a driver doesn't not work anymore
From: Greg KH @ 2009-10-12 19:58 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Éric Piel, Linux Kernel Mailing List, linux-input
In-Reply-To: <20091012192046.GD8345@core.coreip.homeip.net>
On Mon, Oct 12, 2009 at 12:20:46PM -0700, Dmitry Torokhov wrote:
> On Mon, Oct 12, 2009 at 11:54:17AM -0700, Greg KH wrote:
> > On Mon, Oct 12, 2009 at 11:33:13AM -0700, Dmitry Torokhov wrote:
> > > On Mon, Oct 12, 2009 at 10:35:51AM -0700, Greg KH wrote:
> > > > On Mon, Oct 12, 2009 at 08:48:46AM -0700, Dmitry Torokhov wrote:
> > > > > > So at least, unbind should fail as well as bind.
> > > > > >
> > > > >
> > > > > That would be Greg's domain s it is driver core decision whether to
> > > > > allow unbinding platform devices registered with
> > > > > platform_driver_probe().
> > > >
> > > > No, I do not see why that should not be allowed.
> > > >
> > >
> > > Because once you did unbind the device you are stuck (unless the driver
> > > is compiled as a module, but then you could just unload the module
> > > instead of unbinding). Disallowing unbind would allow discarding not
> > > only __devinit but __devexit sections when driver is built in which
> > > would make ebedded people happy[^Hier].
> >
> > Yeah, good point.
> >
> > Does anyone do bind/unbind with platform devices today?
> >
>
> Greg, meet Eric ;)
Heh, yes, I mean for a "useful" thing :)
Eric is trying to do this to resolve a bug in the driver, not a thing
that is "normally" done for platform devices.
> Although I'd really want to fix the resume issue so it works out of the
> box without needing to bind/unbind or reload i8042.
I agree.
thanks,
greg k-h
^ permalink raw reply
* Re: [stable] patch kvm-svm-fix-tsc-offset-adjustment-when-running-nested.patch added to 2.6.31-stable tree
From: Greg KH @ 2009-10-12 19:13 UTC (permalink / raw)
To: Joerg Roedel
Cc: Stefan Lippers-Hollmann, stable, gregkh, linux-kernel, mtosatti
In-Reply-To: <20091012094151.GA32228@amd.com>
On Mon, Oct 12, 2009 at 11:41:51AM +0200, Joerg Roedel wrote:
> All the nested stuff was moved into its own sub-struct in 2.6.32. Here
> is a version that works with 2.6.31.3:
>
> >From 4505a73070f341674e0d22a8c9ee51b2beeb843e Mon Sep 17 00:00:00 2001
Thanks, I've replaced the original patch with this version.
greg k-h
^ permalink raw reply
* Re: [PATCH 2/3] extend get/setrlimit to support setting rlimits external to a process (v6)
From: Neil Horman @ 2009-10-12 20:23 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, marcin.slusarz, nhorman
In-Reply-To: <20091012201304.GG32088@hmsreliant.think-freely.org>
Add syscall infrastructure for getprlimit/setprlimit
This patch adds the definitions for the get/setprlimit syscalls. They are
identical to the get/setlimit calls, except that they allow the caller to
manipulate limits for processes other than themselves.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
include/linux/syscalls.h | 4 ++
kernel/sys.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a990ace..9f357ab 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -702,11 +702,15 @@ asmlinkage long sys_newuname(struct new_utsname __user *name);
asmlinkage long sys_getrlimit(unsigned int resource,
struct rlimit __user *rlim);
+asmlinkage long sys_getprlimit(pid_t pid, unsigned int resource,
+ struct rlimit __user *rlim);
#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64))
asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);
#endif
asmlinkage long sys_setrlimit(unsigned int resource,
struct rlimit __user *rlim);
+asmlinkage long sys_setprlimit(pid_t pid, unsigned int resource,
+ struct rlimit __user *rlim);
asmlinkage long sys_getrusage(int who, struct rusage __user *ru);
asmlinkage long sys_umask(int mask);
diff --git a/kernel/sys.c b/kernel/sys.c
index 0e210a4..6ca9e7f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1213,6 +1213,50 @@ SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)
}
}
+SYSCALL_DEFINE3(getprlimit, pid_t, pid, unsigned int, resource,
+ struct rlimit __user *, rlim)
+{
+ unsigned long flags;
+ struct task_struct *tsk;
+ struct pid *ppid;
+ int retval = -EINVAL;
+
+ ppid = find_get_pid(pid);
+ if (!ppid)
+ goto out;
+
+ tsk = get_pid_task(ppid, PIDTYPE_PID);
+
+ if (!tsk)
+ goto out_put_pid;
+
+ if (resource >= RLIM_NLIMITS)
+ goto out_put_all;
+
+ retval = -EBUSY;
+ if (!lock_task_sighand(tsk, &flags))
+ goto out_put_all;
+
+ else {
+ struct rlimit val;
+
+ task_lock(tsk->group_leader);
+ val = current->signal->rlim[resource];
+ task_unlock(tsk->group_leader);
+ retval = copy_to_user(rlim, &val, sizeof(*rlim)) ? -EFAULT : 0;
+ }
+
+ unlock_task_sighand(tsk, &flags);
+
+out_put_all:
+ put_task_struct(tsk);
+out_put_pid:
+ put_pid(ppid);
+out:
+ return retval;
+}
+
+
#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
/*
@@ -1303,6 +1347,46 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
return do_setrlimit(resource, &new_rlim, current);
}
+SYSCALL_DEFINE3(setprlimit, pid_t, pid, unsigned int, resource,
+ struct rlimit __user *, rlim)
+{
+ struct task_struct *tsk;
+ struct pid *ppid;
+ unsigned long flags;
+ struct rlimit new_rlim;
+ int retval = -EINVAL;
+
+ ppid = find_get_pid(pid);
+ if (!ppid)
+ goto out;
+
+ tsk = get_pid_task(ppid, PIDTYPE_PID);
+
+ if (!tsk)
+ goto out_put_pid;
+
+ if (resource >= RLIM_NLIMITS)
+ goto out_put_all;
+
+ retval = -EFAULT;
+ if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
+ goto out_put_all;
+
+ if (!lock_task_sighand(tsk, &flags))
+ goto out_put_all;
+
+ retval = do_setrlimit(resource, &new_rlim, tsk);
+
+ unlock_task_sighand(tsk, &flags);
+
+out_put_all:
+ put_task_struct(tsk);
+out_put_pid:
+ put_pid(ppid);
+out:
+ return retval;
+}
+
/*
* It would make sense to put struct rusage in the task_struct,
* except that would make the task_struct be *really big*. After
^ permalink raw reply related
* Re: [PATCH 15/15] Do not rely on the initial state of TC/VPEbindings when doing cross VPE writes
From: Ralf Baechle @ 2009-10-12 20:25 UTC (permalink / raw)
To: Gandham, Raghu; +Cc: Kevin D. Kissell, linux-mips, Dearman, Chris
In-Reply-To: <94BD67F8AF3ED34FA362C662BA1F12C50439A11F@MTVEXCHANGE.mips.com>
On Mon, Oct 12, 2009 at 01:20:49PM -0700, Gandham, Raghu wrote:
> > -----Original Message-----
> > From: Ralf Baechle [mailto:ralf@linux-mips.org]
> > Sent: Monday, October 12, 2009 9:18 AM
> > To: Gandham, Raghu
> > Cc: Kevin D. Kissell; linux-mips@linux-mips.org; Dearman, Chris
> > Subject: Re: [PATCH 15/15] Do not rely on the initial state
> > of TC/VPEbindings when doing cross VPE writes
> >
> > On Thu, Jul 02, 2009 at 02:46:33PM -0700, Gandham, Raghu wrote:
> >
> > > > From: Kevin D. Kissell [mailto:kevink@paralogos.com]
> > > > Sent: Wednesday, July 01, 2009 9:02 PM
> > > > To: Gandham, Raghu
> > > > Cc: linux-mips@linux-mips.org; Dearman, Chris
> > > > Subject: Re: [PATCH 15/15] Do not rely on the initial state of
> > > > TC/VPE bindings when doing cross VPE writes
> > > >
> > > > Note that, regardless of the reset state, smtc_configure_tlb()
> > > > should have at least temporarily bound TC 1 to VPE1, which may be
> > > > why this never seemed to be a problem on the 34K. If one
> > wants to
> > > > support designs with more than 2 VPEs, then this is
> > probably one of
> > > > the things that needs to be fixed. That having been said, rather
> > > > than adding a usually-redundant write_vpe_c0_vpeconf0() in that
> > > > clause, wouldn't it
> > > be
> > > > cleaner to just move the MVP setting from the top of the
> > loop to the
> > > > point in the loop just after the TCs have been bound to
> > the VPE in
> > > > question, i.e.,
> > > >
> > > > 454 if (slop) {
> > > > 455 if (tc != 0) {
> > > > 456 smtc_tc_setup(vpe,tc, cpu);
> > > > 457 cpu++;
> > > > 458 }
> > > > 459 printk(" %d", tc);
> > > > 460 tc++;
> > > > 461 slop--;
> > > > 462 }
> > > >
> > > >
> > write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0()
> > > > | VPECONF0_MVP);
> > > >
> > > > 463 if (vpe != 0) {
> > > > 464 /*
> > > > 465 * Clear any stale software
> > interrupts
> > > from
> > > > VPE's Cause
> > > > 466 */
> > > >
> > > > This should definitely be OK for a 34K, because it's
> > being executed
> > > > by TC0 in VPE0 and the reset state of VPE0 has MVP set. If it
> > > > weren't,
> > > > smtc_configure_tlb() would have failed.
> > > >
> > > > Regards,
> > > >
> > > > Kevin K.
> > >
> > >
> > > I will resend this patch with your suggestion.
> >
> > Ping? Don't think I ever received that, if you sent it.
> I resent the patch and it got checked-in. It is not appended to this
> mail thread though.
> http://www.linux-mips.org/git?p=linux.git;a=commitdiff;h=d8e5f9fe5dab0e0
> 7985f2456cb6cc57788f53131
Ah, ok. Thanks!
Ralf
^ permalink raw reply
* Re: Real time kernel
From: Christoph Lameter @ 2009-10-12 20:16 UTC (permalink / raw)
To: Dragoslav Zaric; +Cc: LKML
In-Reply-To: <2d05c4580910121100v702cbdddua9bd8de971fecaa2@mail.gmail.com>
On Mon, 12 Oct 2009, Dragoslav Zaric wrote:
> If you build kernel 2.6 with preemption configured in,
> do you get real-time operation system ?
Depends on what you mean by realtime. If you want a slower kernel with
less outliers then enable preempt.
^ permalink raw reply
* S3C: Remove <plat/audio.h>
From: Ben Dooks @ 2009-10-12 20:17 UTC (permalink / raw)
To: broonie, alsa-devel; +Cc: Simtec Linux Team
[-- Attachment #1: asoc-audio-cleanups1.patch --]
[-- Type: text/plain, Size: 5487 bytes --]
Remove the <plat/audio.h> include from arch/arm/plat-s3c/include/plat/audio.h
as it provides nothing to the current kernel and is not in any future plans
for the system.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Simtec Linux Team <linux@simtec.co.uk>
---
arch/arm/plat-s3c/include/plat/audio.h | 45 ---------------------------------
sound/soc/s3c24xx/neo1973_wm8753.c | 1
sound/soc/s3c24xx/s3c-i2s-v2.c | 1
sound/soc/s3c24xx/s3c2412-i2s.c | 1
sound/soc/s3c24xx/s3c2443-ac97.c | 1
sound/soc/s3c24xx/s3c24xx-i2s.c | 2 -
sound/soc/s3c24xx/s3c24xx-pcm.c | 1
sound/soc/s3c24xx/s3c64xx-i2s.c | 1
8 files changed, 1 insertion(+), 52 deletions(-)
Index: b/arch/arm/plat-s3c/include/plat/audio.h
===================================================================
--- a/arch/arm/plat-s3c/include/plat/audio.h 2009-10-12 21:11:08.000000000 +0100
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,45 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/audio.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- * http://www.simtec.co.uk/products/SWLINUX/
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX - Audio platfrom_device info
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_AUDIO_H
-#define __ASM_ARCH_AUDIO_H __FILE__
-
-/* struct s3c24xx_iis_ops
- *
- * called from the s3c24xx audio core to deal with the architecture
- * or the codec's setup and control.
- *
- * the pointer to itself is passed through in case the caller wants to
- * embed this in an larger structure for easy reference to it's context.
-*/
-
-struct s3c24xx_iis_ops {
- struct module *owner;
-
- int (*startup)(struct s3c24xx_iis_ops *me);
- void (*shutdown)(struct s3c24xx_iis_ops *me);
- int (*suspend)(struct s3c24xx_iis_ops *me);
- int (*resume)(struct s3c24xx_iis_ops *me);
-
- int (*open)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
- int (*close)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
- int (*prepare)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm, struct snd_pcm_runtime *rt);
-};
-
-struct s3c24xx_platdata_iis {
- const char *codec_clk;
- struct s3c24xx_iis_ops *ops;
- int (*match_dev)(struct device *dev);
-};
-
-#endif /* __ASM_ARCH_AUDIO_H */
Index: b/sound/soc/s3c24xx/s3c-i2s-v2.c
===================================================================
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c 2009-10-12 21:11:08.000000000 +0100
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c 2009-10-12 21:11:39.000000000 +0100
@@ -32,7 +32,6 @@
#include <plat/regs-s3c2412-iis.h>
-#include <plat/audio.h>
#include <mach/dma.h>
#include "s3c-i2s-v2.h"
Index: b/sound/soc/s3c24xx/s3c2412-i2s.c
===================================================================
--- a/sound/soc/s3c24xx/s3c2412-i2s.c 2009-10-12 21:11:08.000000000 +0100
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c 2009-10-12 21:11:39.000000000 +0100
@@ -34,7 +34,6 @@
#include <plat/regs-s3c2412-iis.h>
-#include <plat/audio.h>
#include <mach/regs-gpio.h>
#include <mach/dma.h>
Index: b/sound/soc/s3c24xx/s3c2443-ac97.c
===================================================================
--- a/sound/soc/s3c24xx/s3c2443-ac97.c 2009-10-12 21:11:08.000000000 +0100
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c 2009-10-12 21:11:39.000000000 +0100
@@ -32,7 +32,6 @@
#include <plat/regs-ac97.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
-#include <plat/audio.h>
#include <asm/dma.h>
#include <mach/dma.h>
Index: b/sound/soc/s3c24xx/s3c24xx-i2s.c
===================================================================
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c 2009-10-12 21:11:08.000000000 +0100
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c 2009-10-12 21:11:39.000000000 +0100
@@ -32,7 +32,7 @@
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
-#include <plat/audio.h>
+
#include <asm/dma.h>
#include <mach/dma.h>
Index: b/sound/soc/s3c24xx/s3c24xx-pcm.c
===================================================================
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c 2009-10-12 21:11:08.000000000 +0100
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c 2009-10-12 21:11:39.000000000 +0100
@@ -29,7 +29,6 @@
#include <asm/dma.h>
#include <mach/hardware.h>
#include <mach/dma.h>
-#include <plat/audio.h>
#include "s3c24xx-pcm.h"
Index: b/sound/soc/s3c24xx/neo1973_wm8753.c
===================================================================
--- a/sound/soc/s3c24xx/neo1973_wm8753.c 2009-10-12 21:13:18.000000000 +0100
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c 2009-10-12 21:13:29.000000000 +0100
@@ -29,7 +29,6 @@
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
-#include <plat/audio.h>
#include <linux/io.h>
#include <mach/spi-gpio.h>
Index: b/sound/soc/s3c24xx/s3c64xx-i2s.c
===================================================================
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c 2009-10-12 21:13:35.000000000 +0100
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c 2009-10-12 21:13:40.000000000 +0100
@@ -31,7 +31,6 @@
#include <plat/gpio-bank-d.h>
#include <plat/gpio-bank-e.h>
#include <plat/gpio-cfg.h>
-#include <plat/audio.h>
#include <mach/map.h>
#include <mach/dma.h>
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply
* gta02: fix includes
From: Ben Dooks @ 2009-10-12 20:17 UTC (permalink / raw)
To: broonie, alsa-devel; +Cc: Simtec Linux Team
[-- Attachment #1: fix-gta02-audio.patch --]
[-- Type: text/plain, Size: 1139 bytes --]
The gta02 build is missing <mach/regs-gpio.h> and is also using the
incorrect <asm/io.h> header (it should be <linux/io.h>). Fix these
two problems.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Simtec Linux Team <linux@simtec.co.uk>
---
sound/soc/s3c24xx/neo1973_gta02_wm8753.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Index: b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
===================================================================
--- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c 2009-10-10 22:55:53.000000000 +0100
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c 2009-10-10 22:58:31.000000000 +0100
@@ -19,6 +19,8 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <linux/io.h>
+
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -29,7 +31,7 @@
#include <plat/regs-iis.h>
#include <mach/regs-clock.h>
-#include <asm/io.h>
+#include <mach/regs-gpioj.h>
#include <mach/gta02.h>
#include "../codecs/wm8753.h"
#include "s3c24xx-pcm.h"
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply
* Re: [PATCH 1/3] extend get/setrlimit to support setting rlimits external to a process (v6)
From: Neil Horman @ 2009-10-12 20:20 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, marcin.slusarz, nhorman
In-Reply-To: <20091012201304.GG32088@hmsreliant.think-freely.org>
Augment /proc/<pid>/limits file to support limit setting
It was suggested to me recently that we support a mechanism by which we can set
various process limits from points external to the process. The reasoning being
that some processes are very long lived, and it would be beneficial to these
long lived processes if we could modify their various limits without needing to
kill them, adjust the limits for the user and restarting them. While individual
application can certainly export this control on their own, it would be nice if
such functionality were available to a sysadmin, without needing to have each
application re-invent the wheel.
As such, I've implemented the below patch, which makes /proc/pid/limits writable
for each process. By writing the following format:
<limit> <current value> <max value>
to the limits file, an administrator can now dynamically change the limits for
the respective process. Tested by myself with good results.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Documentation/filesystems/proc.txt | 26 +++++
fs/proc/base.c | 184 ++++++++++++++++++++++++++++++-------
include/linux/sched.h | 3
kernel/sys.c | 48 ++++++---
4 files changed, 209 insertions(+), 52 deletions(-)
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 2c48f94..62fd7f5 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -38,6 +38,7 @@ Table of Contents
3.3 /proc/<pid>/io - Display the IO accounting fields
3.4 /proc/<pid>/coredump_filter - Core dump filtering settings
3.5 /proc/<pid>/mountinfo - Information about mounts
+ 3.6 /proc/<pid>/limits - Information about process rlimit value
------------------------------------------------------------------------------
@@ -1408,3 +1409,28 @@ For more information on mount propagation see:
Documentation/filesystems/sharedsubtree.txt
+3.6 /proc/<pid>/limits - Information about rlimit values
+------------------------------------------------------------
+
+This file contains information regarding the processes rlimit settings.
+Normally this information is only available programatically via the
+getrlimit/setrlimit syscalls. This file exports it so that sysadmins may
+dyanmically see their values. This file contains lines of the form:
+
+Limit Set String Soft Limit Hard Limit Units
+
+Limit - A description of the limit
+Set String - A consise string defining the limit meaning
+Soft Limit - The rlim_cur value returned by getrlimit for the corresponding limit
+Hard Limit - The rlim_max value returned by getrlimit for the corresponding limit
+Units - The units that the given limit is measured in
+
+Limits for a given process can also be set by writing to this file by writing a
+string in the following format:
+<Set String> [value|"unlimited"] [value|"unlimited"] > proc/<pid>/limits
+
+For example to set the maximum core files size for process 2000 to a soft limit
+of 1024 bytes and a max limit of unlimited, we would do the following from a
+shell prompt:
+echo core 1024 unlimited > /proc/2000/limits
+
diff --git a/fs/proc/base.c b/fs/proc/base.c
index dd5bed0..69d2a55 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -49,6 +49,8 @@
#include <asm/uaccess.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
@@ -456,72 +458,186 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
struct limit_names {
char *name;
char *unit;
+ char *match;
};
static const struct limit_names lnames[RLIM_NLIMITS] = {
- [RLIMIT_CPU] = {"Max cpu time", "seconds"},
- [RLIMIT_FSIZE] = {"Max file size", "bytes"},
- [RLIMIT_DATA] = {"Max data size", "bytes"},
- [RLIMIT_STACK] = {"Max stack size", "bytes"},
- [RLIMIT_CORE] = {"Max core file size", "bytes"},
- [RLIMIT_RSS] = {"Max resident set", "bytes"},
- [RLIMIT_NPROC] = {"Max processes", "processes"},
- [RLIMIT_NOFILE] = {"Max open files", "files"},
- [RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"},
- [RLIMIT_AS] = {"Max address space", "bytes"},
- [RLIMIT_LOCKS] = {"Max file locks", "locks"},
- [RLIMIT_SIGPENDING] = {"Max pending signals", "signals"},
- [RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"},
- [RLIMIT_NICE] = {"Max nice priority", NULL},
- [RLIMIT_RTPRIO] = {"Max realtime priority", NULL},
- [RLIMIT_RTTIME] = {"Max realtime timeout", "us"},
+ [RLIMIT_CPU] = {"Max cpu time", "ms", "cpu"},
+ [RLIMIT_FSIZE] = {"Max file size", "bytes", "fsize"},
+ [RLIMIT_DATA] = {"Max data size", "bytes", "data"},
+ [RLIMIT_STACK] = {"Max stack size", "bytes", "stack"},
+ [RLIMIT_CORE] = {"Max core file size", "bytes", "core"},
+ [RLIMIT_RSS] = {"Max resident set", "bytes", "rss"},
+ [RLIMIT_NPROC] = {"Max processes", "processes", "nproc"},
+ [RLIMIT_NOFILE] = {"Max open files", "files", "nofile"},
+ [RLIMIT_MEMLOCK] = {"Max locked memory", "bytes", "memlock"},
+ [RLIMIT_AS] = {"Max address space", "bytes", "as"},
+ [RLIMIT_LOCKS] = {"Max file locks", "locks", "locks"},
+ [RLIMIT_SIGPENDING] = {"Max pending signals", "signals", "sigpending"},
+ [RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes", "msgqueue"},
+ [RLIMIT_NICE] = {"Max nice priority", NULL, "nice"},
+ [RLIMIT_RTPRIO] = {"Max realtime priority", NULL, "rtprio"},
+ [RLIMIT_RTTIME] = {"Max realtime timeout", "us", "rttime"},
};
/* Display limits for a process */
-static int proc_pid_limits(struct task_struct *task, char *buffer)
+static ssize_t proc_pid_limit_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned int i;
- int count = 0;
unsigned long flags;
- char *bufptr = buffer;
+ char *bufptr;
+ size_t bcount = 0;
+ size_t ccount = -ENOMEM;
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
struct rlimit rlim[RLIM_NLIMITS];
+ bufptr = kzalloc((RLIM_NLIMITS+1)*90, GFP_KERNEL);
+ if (!bufptr)
+ goto out;
+
+ ccount = -EBUSY;
+
if (!lock_task_sighand(task, &flags))
- return 0;
+ goto out_free;
+
memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
unlock_task_sighand(task, &flags);
/*
* print the file header
*/
- count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n",
- "Limit", "Soft Limit", "Hard Limit", "Units");
+ bcount += sprintf(&bufptr[bcount], "%-25s %-12s %-20s %-20s %-10s\n",
+ "Limit", "Set String", "Soft Limit", "Hard Limit", "Units");
for (i = 0; i < RLIM_NLIMITS; i++) {
if (rlim[i].rlim_cur == RLIM_INFINITY)
- count += sprintf(&bufptr[count], "%-25s %-20s ",
- lnames[i].name, "unlimited");
+ bcount += sprintf(&bufptr[bcount], "%-25s %-12s %-20s ",
+ lnames[i].name ,lnames[i].match,
+ "unlimited");
else
- count += sprintf(&bufptr[count], "%-25s %-20lu ",
- lnames[i].name, rlim[i].rlim_cur);
-
+ bcount += sprintf(&bufptr[bcount], "%-25s %-12s %-20lu ",
+ lnames[i].name, lnames[i].match,
+ rlim[i].rlim_cur);
if (rlim[i].rlim_max == RLIM_INFINITY)
- count += sprintf(&bufptr[count], "%-20s ", "unlimited");
+ bcount += sprintf(&bufptr[bcount], "%-20s ",
+ "unlimited");
else
- count += sprintf(&bufptr[count], "%-20lu ",
+ bcount += sprintf(&bufptr[bcount], "%-20lu ",
rlim[i].rlim_max);
-
if (lnames[i].unit)
- count += sprintf(&bufptr[count], "%-10s\n",
+ bcount += sprintf(&bufptr[bcount], "%-10s\n",
lnames[i].unit);
else
- count += sprintf(&bufptr[count], "\n");
+ bcount += sprintf(&bufptr[bcount], "\n");
+ }
+
+ ccount = -EMSGSIZE;
+
+ if (*ppos >= bcount)
+ goto out_task;
+
+ ccount = min(count, (size_t)(bcount-(*ppos)));
+ ccount = ccount - copy_to_user(buf, &bufptr[*ppos], ccount);
+ *ppos += ccount;
+out_task:
+ put_task_struct(task);
+out_free:
+ kfree(bufptr);
+out:
+ return ccount;
+}
+
+#define PROC_PID_BUF_SZ 128
+static ssize_t proc_pid_limit_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *buffer;
+ char *element, *vmc, *vmm;
+ struct rlimit new_rlim;
+ unsigned long flags;
+ int i;
+ int index = -1;
+ size_t wcount = -EMSGSIZE;
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+
+
+ if (*ppos != 0)
+ goto out;
+
+ if (count > PROC_PID_BUF_SZ)
+ goto out;
+
+ wcount = -ENOMEM;
+ buffer = kzalloc(PROC_PID_BUF_SZ, GFP_KERNEL);
+
+ if (!buffer)
+ goto out;
+
+ element = kzalloc(PROC_PID_BUF_SZ, GFP_KERNEL);
+ vmc = kzalloc(PROC_PID_BUF_SZ, GFP_KERNEL);
+ vmm = kzalloc(PROC_PID_BUF_SZ, GFP_KERNEL);
+
+ if (!element || !vmm || !vmc)
+ goto out_free;
+
+ wcount = -EFAULT;
+
+ if (copy_from_user(buffer, buf, count))
+ goto out_free;
+
+ i = sscanf(buffer, "%s %s %s", element, vmc, vmm);
+
+ if (i < 3)
+ goto out_free;
+
+ if (!strncmp(vmc, "unlimited", 9))
+ new_rlim.rlim_cur = RLIM_INFINITY;
+ else
+ new_rlim.rlim_cur = simple_strtoul(vmc, NULL, 10);
+
+ if (!strncmp(vmm, "unlimited", 9))
+ new_rlim.rlim_max = RLIM_INFINITY;
+ else
+ new_rlim.rlim_max = simple_strtoul(vmm, NULL, 10);
+
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ if (!strncmp(element, lnames[i].match,
+ strlen(lnames[i].match))) {
+ index = i;
+ break;
+ }
}
+ wcount = -EBUSY;
+
+ if (!lock_task_sighand(task, &flags))
+ goto out_free;
+
+ wcount = -ENOENT;
+
+ if ((index >= 0) && (index < RLIM_NLIMITS))
+ wcount = do_setrlimit(index, &new_rlim, task);
+
+ unlock_task_sighand(task, &flags);
+
+out_free:
+ kfree(element);
+ kfree(vmc);
+ kfree(vmm);
+ kfree(buffer);
+out:
+ *ppos += count;
+ put_task_struct(task);
return count;
}
+static const struct file_operations proc_limit_operations = {
+ .read = proc_pid_limit_read,
+ .write = proc_pid_limit_write,
+};
+
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
static int proc_pid_syscall(struct task_struct *task, char *buffer)
{
@@ -2501,7 +2617,7 @@ static const struct pid_entry tgid_base_stuff[] = {
INF("auxv", S_IRUSR, proc_pid_auxv),
ONE("status", S_IRUGO, proc_pid_status),
ONE("personality", S_IRUSR, proc_pid_personality),
- INF("limits", S_IRUSR, proc_pid_limits),
+ REG("limits", S_IRUSR|S_IWUSR, proc_limit_operations),
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
@@ -2836,7 +2952,7 @@ static const struct pid_entry tid_base_stuff[] = {
INF("auxv", S_IRUSR, proc_pid_auxv),
ONE("status", S_IRUGO, proc_pid_status),
ONE("personality", S_IRUSR, proc_pid_personality),
- INF("limits", S_IRUSR, proc_pid_limits),
+ REG("limits", S_IRUSR|S_IWUSR, proc_limit_operations),
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2be3760..be54f28 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -672,6 +672,9 @@ struct signal_struct {
int oom_adj; /* OOM kill score adjustment (bit shift) */
};
+extern int do_setrlimit(unsigned int resource, struct rlimit *new_rlim,
+ struct task_struct *tsk);
+
/* Context switch must be unlocked if interrupts are to be enabled */
#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
# define __ARCH_WANT_UNLOCKED_CTXSW
diff --git a/kernel/sys.c b/kernel/sys.c
index 1828f8d..0e210a4 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1238,41 +1238,41 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
#endif
-SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
+int do_setrlimit(unsigned int resource, struct rlimit *new_rlim,
+ struct task_struct *tsk)
{
- struct rlimit new_rlim, *old_rlim;
int retval;
+ struct rlimit *old_rlim;
- if (resource >= RLIM_NLIMITS)
- return -EINVAL;
- if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
- return -EFAULT;
- if (new_rlim.rlim_cur > new_rlim.rlim_max)
+
+ if (new_rlim->rlim_cur > new_rlim->rlim_max)
return -EINVAL;
- old_rlim = current->signal->rlim + resource;
- if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
+ old_rlim = tsk->signal->rlim + resource;
+
+ if ((new_rlim->rlim_max > old_rlim->rlim_max) &&
!capable(CAP_SYS_RESOURCE))
return -EPERM;
- if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
+
+ if (resource == RLIMIT_NOFILE && new_rlim->rlim_max > sysctl_nr_open)
return -EPERM;
- retval = security_task_setrlimit(resource, &new_rlim);
+ retval = security_task_setrlimit(resource, new_rlim);
if (retval)
return retval;
- if (resource == RLIMIT_CPU && new_rlim.rlim_cur == 0) {
+ if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
/*
* The caller is asking for an immediate RLIMIT_CPU
* expiry. But we use the zero value to mean "it was
* never set". So let's cheat and make it one second
* instead
*/
- new_rlim.rlim_cur = 1;
+ new_rlim->rlim_cur = 1;
}
- task_lock(current->group_leader);
- *old_rlim = new_rlim;
- task_unlock(current->group_leader);
+ task_lock(tsk->group_leader);
+ *old_rlim = *new_rlim;
+ task_unlock(tsk->group_leader);
if (resource != RLIMIT_CPU)
goto out;
@@ -1283,14 +1283,26 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
* very long-standing error, and fixing it now risks breakage of
* applications, so we live with it
*/
- if (new_rlim.rlim_cur == RLIM_INFINITY)
+ if (new_rlim->rlim_cur == RLIM_INFINITY)
goto out;
- update_rlimit_cpu(new_rlim.rlim_cur);
+ update_rlimit_cpu(new_rlim->rlim_cur);
out:
return 0;
}
+SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
+{
+ struct rlimit new_rlim;
+
+ if (resource >= RLIM_NLIMITS)
+ return -EINVAL;
+ if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
+ return -EFAULT;
+
+ return do_setrlimit(resource, &new_rlim, current);
+}
+
/*
* It would make sense to put struct rusage in the task_struct,
* except that would make the task_struct be *really big*. After
^ permalink raw reply related
* RE: [PATCH 15/15] Do not rely on the initial state of TC/VPEbindings when doing cross VPE writes
From: Gandham, Raghu @ 2009-10-12 20:20 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Kevin D. Kissell, linux-mips, Dearman, Chris
In-Reply-To: <20091012161751.GB21183@linux-mips.org>
> -----Original Message-----
> From: Ralf Baechle [mailto:ralf@linux-mips.org]
> Sent: Monday, October 12, 2009 9:18 AM
> To: Gandham, Raghu
> Cc: Kevin D. Kissell; linux-mips@linux-mips.org; Dearman, Chris
> Subject: Re: [PATCH 15/15] Do not rely on the initial state
> of TC/VPEbindings when doing cross VPE writes
>
> On Thu, Jul 02, 2009 at 02:46:33PM -0700, Gandham, Raghu wrote:
>
> > > From: Kevin D. Kissell [mailto:kevink@paralogos.com]
> > > Sent: Wednesday, July 01, 2009 9:02 PM
> > > To: Gandham, Raghu
> > > Cc: linux-mips@linux-mips.org; Dearman, Chris
> > > Subject: Re: [PATCH 15/15] Do not rely on the initial state of
> > > TC/VPE bindings when doing cross VPE writes
> > >
> > > Note that, regardless of the reset state, smtc_configure_tlb()
> > > should have at least temporarily bound TC 1 to VPE1, which may be
> > > why this never seemed to be a problem on the 34K. If one
> wants to
> > > support designs with more than 2 VPEs, then this is
> probably one of
> > > the things that needs to be fixed. That having been said, rather
> > > than adding a usually-redundant write_vpe_c0_vpeconf0() in that
> > > clause, wouldn't it
> > be
> > > cleaner to just move the MVP setting from the top of the
> loop to the
> > > point in the loop just after the TCs have been bound to
> the VPE in
> > > question, i.e.,
> > >
> > > 454 if (slop) {
> > > 455 if (tc != 0) {
> > > 456 smtc_tc_setup(vpe,tc, cpu);
> > > 457 cpu++;
> > > 458 }
> > > 459 printk(" %d", tc);
> > > 460 tc++;
> > > 461 slop--;
> > > 462 }
> > >
> > >
> write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0()
> > > | VPECONF0_MVP);
> > >
> > > 463 if (vpe != 0) {
> > > 464 /*
> > > 465 * Clear any stale software
> interrupts
> > from
> > > VPE's Cause
> > > 466 */
> > >
> > > This should definitely be OK for a 34K, because it's
> being executed
> > > by TC0 in VPE0 and the reset state of VPE0 has MVP set. If it
> > > weren't,
> > > smtc_configure_tlb() would have failed.
> > >
> > > Regards,
> > >
> > > Kevin K.
> >
> >
> > I will resend this patch with your suggestion.
>
> Ping? Don't think I ever received that, if you sent it.
I resent the patch and it got checked-in. It is not appended to this
mail thread though.
http://www.linux-mips.org/git?p=linux.git;a=commitdiff;h=d8e5f9fe5dab0e0
7985f2456cb6cc57788f53131
Thanks,
Raghu
>
> Ralf
>
^ permalink raw reply
* RE: [PATCH 15/15] Do not rely on the initial state of TC/VPEbindings when doing cross VPE writes
From: Gandham, Raghu @ 2009-10-12 20:20 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Kevin D. Kissell, linux-mips, Dearman, Chris
In-Reply-To: <20091012161751.GB21183@linux-mips.org>
> -----Original Message-----
> From: Ralf Baechle [mailto:ralf@linux-mips.org]
> Sent: Monday, October 12, 2009 9:18 AM
> To: Gandham, Raghu
> Cc: Kevin D. Kissell; linux-mips@linux-mips.org; Dearman, Chris
> Subject: Re: [PATCH 15/15] Do not rely on the initial state
> of TC/VPEbindings when doing cross VPE writes
>
> On Thu, Jul 02, 2009 at 02:46:33PM -0700, Gandham, Raghu wrote:
>
> > > From: Kevin D. Kissell [mailto:kevink@paralogos.com]
> > > Sent: Wednesday, July 01, 2009 9:02 PM
> > > To: Gandham, Raghu
> > > Cc: linux-mips@linux-mips.org; Dearman, Chris
> > > Subject: Re: [PATCH 15/15] Do not rely on the initial state of
> > > TC/VPE bindings when doing cross VPE writes
> > >
> > > Note that, regardless of the reset state, smtc_configure_tlb()
> > > should have at least temporarily bound TC 1 to VPE1, which may be
> > > why this never seemed to be a problem on the 34K. If one
> wants to
> > > support designs with more than 2 VPEs, then this is
> probably one of
> > > the things that needs to be fixed. That having been said, rather
> > > than adding a usually-redundant write_vpe_c0_vpeconf0() in that
> > > clause, wouldn't it
> > be
> > > cleaner to just move the MVP setting from the top of the
> loop to the
> > > point in the loop just after the TCs have been bound to
> the VPE in
> > > question, i.e.,
> > >
> > > 454 if (slop) {
> > > 455 if (tc != 0) {
> > > 456 smtc_tc_setup(vpe,tc, cpu);
> > > 457 cpu++;
> > > 458 }
> > > 459 printk(" %d", tc);
> > > 460 tc++;
> > > 461 slop--;
> > > 462 }
> > >
> > >
> write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0()
> > > | VPECONF0_MVP);
> > >
> > > 463 if (vpe != 0) {
> > > 464 /*
> > > 465 * Clear any stale software
> interrupts
> > from
> > > VPE's Cause
> > > 466 */
> > >
> > > This should definitely be OK for a 34K, because it's
> being executed
> > > by TC0 in VPE0 and the reset state of VPE0 has MVP set. If it
> > > weren't,
> > > smtc_configure_tlb() would have failed.
> > >
> > > Regards,
> > >
> > > Kevin K.
> >
> >
> > I will resend this patch with your suggestion.
>
> Ping? Don't think I ever received that, if you sent it.
I resent the patch and it got checked-in. It is not appended to this
mail thread though.
http://www.linux-mips.org/git?p=linux.git;a=commitdiff;h=d8e5f9fe5dab0e0
7985f2456cb6cc57788f53131
Thanks,
Raghu
>
> Ralf
>
^ permalink raw reply
* [LTP] [ ltp-Bugs-2877261 ] diotest failing with tmp dir creation errors
From: SourceForge.net @ 2009-10-12 20:20 UTC (permalink / raw)
To: noreply
Bugs item #2877261, was opened at 2009-10-12 14:19
Message generated for change (Comment added) made by mrwenzel
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=103382&aid=2877261&group_id=3382
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Testcases
Group: None
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: mrwenzel (mrwenzel)
Assigned to: Nobody/Anonymous (nobody)
Summary: diotest failing with tmp dir creation errors
Initial Comment:
If I start a default test run with runltp, all of the diotest runs except diotest1 will fail with an error that mkdtemp hit no such file or directory. It appears that the tmp directory is getting removed somehow after the first test and then all the subsequent tests fail. I can get around the problem by not specifying a tmp dir option to runltp and instead setting an environment variable for TDIRECTORY which according to tst_tmpdir code is not removed.
----------------------------------------------------------------------
>Comment By: mrwenzel (mrwenzel)
Date: 2009-10-12 14:20
Message:
Forgot to add; I'm using version ltp-full-20090831
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=103382&aid=2877261&group_id=3382
------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply
* Re: [ofa-general] Re: [GIT PULL] please pull ummunotify
From: Ingo Molnar @ 2009-10-12 20:20 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Pavel Machek, Roland Dreier, Peter Zijlstra, linux-rdma,
linux-kernel, Paul Mackerras, Anton Blanchard, general, akpm,
torvalds, Jeff Squyres
In-Reply-To: <20091012193048.GA20313@obsidianresearch.com>
* Jason Gunthorpe <jgunthorpe@obsidianresearch.com> wrote:
> On Mon, Oct 12, 2009 at 08:19:44PM +0200, Ingo Molnar wrote:
>
> > > After that point the scheme is perfectly lossless.
> >
> > Well if it can OOM it's not lossless, obviously. You just define
> > "event loss" to be equivalent to "Destruction of the universe." ;-)
>
> It can't OOM once the ummunotify registration is done - when an event
> occurs it doesn't allocate any memory and it doesn't loose events.
Well, it has built-in event loss via the UMMUNOTIFY_FLAG_HINT mechanism:
any double events on the same range will cause an imprecise event to be
recorded and cause the loss of information.
Is that loss of information more acceptable than the loss of information
via the loss of events?
It might be more acceptable because the flag-hint mechanism can at most
cause over-flushing - while with perf events we might miss to invalidate
a range altogether.
Ingo
^ permalink raw reply
* Re: [PATCH] MIPS: Alchemy: fix DB1550 PCI interrupt typo
From: Ralf Baechle @ 2009-10-12 20:18 UTC (permalink / raw)
To: Manuel Lauss; +Cc: Linux-MIPS, Manuel Lauss
In-Reply-To: <1255366626-10307-1-git-send-email-manuel.lauss@gmail.com>
On Mon, Oct 12, 2009 at 06:57:06PM +0200, Manuel Lauss wrote:
> Fix a copy-paste error in patch "Alchemy: Stop IRQ name sharing".
>
> Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
> ---
> Ralf, please fold this into the patch "Alchemy: Stop IRQ name sharing"
> in lmo-queue!
Done. Thanks!
Ralf
^ permalink raw reply
* Re: [dm-crypt] Naming key slots to permit luksKillSlot to be aimed...
From: David Greaves @ 2009-10-12 20:20 UTC (permalink / raw)
To: Christian Pernegger; +Cc: dm-crypt
In-Reply-To: <bb145bd20910121133k74cdf4f4v14a04aea61cc92d7@mail.gmail.com>
Christian Pernegger wrote:
>> How do I know which slot to luksKillSlot?
>
> Specify the slot number when adding keys and keep a list of 'slot
> number = user' entries somewhere.
OK, glad I didn't miss anything.
I guess "somewhere" could/should be the header :)
> After the fact ... kill both users and re-add the one that should remain.
So clearly there's a usability problem there.
Cheers
David
--
"Don't worry, you'll be fine; I saw it work in a cartoon once..."
^ permalink raw reply
* [linux-dvb] Status of v4l repositories / merging new one
From: Helmut Auer @ 2009-10-12 20:20 UTC (permalink / raw)
To: linux-dvb
Hello List
AFAIK there are different v4l repositories supporting differnet hardware, e.g v4l-dvb(missing
skystar HD), liplianin (missing knc1) etc.
To add another one, we have a repository supporting the pci-e dual dvb-s low pointer profile
mediapointer card :)
But for my distribution I'd like to have one repository, supporting all cards
Whats to do to get all these repositories merged ?
Are there any plans about doing that ?
--
Helmut Auer, helmut@helmutauer.de
_______________________________________________
linux-dvb users mailing list
For V4L/DVB development, please use instead linux-media@vger.kernel.org
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
^ permalink raw reply
* Re: [PATCH tracing/kprobes v3 4/7] tracing/kprobes: Avoid field name confliction
From: Masami Hiramatsu @ 2009-10-12 20:22 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Steven Rostedt, Ingo Molnar, lkml, systemtap, DLE,
Thomas Gleixner, Arnaldo Carvalho de Melo, Mike Galbraith,
Paul Mackerras, Peter Zijlstra, Christoph Hellwig,
Ananth N Mavinakayanahalli, Jim Keniston, Frank Ch. Eigler
In-Reply-To: <20091012194852.GB4748@nowhere>
Frederic Weisbecker wrote:
> On Mon, Oct 12, 2009 at 03:13:51PM -0400, Masami Hiramatsu wrote:
>> Frederic Weisbecker wrote:
>>> The conflict issue might not be obvious for a user desperately trying to set
>>> a kprobe. Even for other failcases, it might not be obvious (blacklisted
>>> symbols, syntax errors...)
>>>
>>> May be should you improve the error granularity and print a KERN_DEBUG
>>> message?
>>
>> Agreed, and kprobes error handling should be improved too (in the most cases,
>> it just returns -EINVAL).
>>
>> Thank you.
>>
>
>
> And btw, I'm enable to create a probe, neither through ftrace nor perf:
>
> $ sudo ./perf probe -P 'p:sys_close sys_close $retval'
> Adding new event: p:sys_close sys_close+0 $retval
>
> Error: Failed to create event: Invalid argument
>
>
> # echo 'p:sys_open sys_open $retval'> /debug/tracing/kprobe_events
> bash: echo: write error : Invalid argument
>
> I suspect I missed something very obvious with the syntax :)
Ah, only kretprobe events can use $retval :-)
So, you should specify 'r' instead of 'p'.
-P 'r:sys_close sys_close $retval'
> I've applied your patches in:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing.git
> tracing/kprobes
>
> Thanks.
Thank you!
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhiramat@redhat.com
^ permalink raw reply
* RE: [patch] Staging: hv: Fix vmbus load hang caused by wrong data packing
From: Hank Janssen @ 2009-10-12 20:10 UTC (permalink / raw)
To: Greg KH, Haiyang Zhang
Cc: linux-kernel@vger.kernel.org, Tom Hanrahan, Hashir Abdi
In-Reply-To: <20091012172953.GA10557@suse.de>
>Odd quoting style :(
We like to keep things lively :)
>> Based on our testing, the #pragma pack(push,1) can pack the data
>> correctly for the HyperV to use, but __attribute__((packed)) couldn't
>> do this right.
>
>Why? What does gcc generate differently? This should be identical.
It should, but in practice in this case it does not seem to behave the same
Way.
>> These data structures are moved by someone from the original file,
>> ChannelMessages.h, which contains structures used for messaging to
>> host.
>
>I moved them as they did not need to be in that file, right?
Moving them was not a problem.
>Ideally, we don't deal with packed structures at all, but with offsets
>in memory and pick out the proper fields and put them into new
>structures if you want to use them that way. How hard would that be to
>do here instead?
It is something that I want to look at in the future. Our primary focus
Is to get the bug fixed. We cannot do the offset way in the time we
Have before 2.6.32 closes and still be comfortable we have gone through
The extensive testing cycle we do on our side.
>I still want to figure out what the real difference here is. Especially
>as I removed a lot of the #pragma pack(push,1) lines from the hv code.
>If it really is different, all of those patches should be reverted,
>right?
Not sure yet if they need to be reverted, after we fixed this bug last week
We are getting another one, it was masked by the one we just fixed.
We are checking into that right now;
BUG: unable to handle kernel NULL pointer dereference at (null)
Thanks,
Hank.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.