* RE: [RFC v3][PATCH 0/4] OMAP: DSS2: Overlay Manager LCD2 support in DISPC
From: Taneja, Archit @ 2010-10-20 3:56 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: linux-omap@vger.kernel.org
In-Reply-To: <1287493790.2216.26.camel@tubuntu>
Hi,
Tomi Valkeinen wrote:
> Hi,
>
> On Tue, 2010-10-05 at 13:55 +0200, ext Archit Taneja wrote:
>> This patch series which incorporates changes in DSS2 to enable
>> omap_dss_device instances to use the new Overlay Manager LCD2 in DISPC.
>>
>> On OMAP4, we have a new DISPC channel for Overlay Manager LCD2. This
>> channel's video port is a source port for RFBI, DSI2 and DPI. The
>> Primary channel's video port is connected to RFBI and DSI1.
>>
>> There is a set of regsiters for LCD2 channel similar to the existing
>> LCD channel, like DISPC_CONTROL2, DISPC_DIVISOR2, DISPC_CONFIG2 and so on.
>>
>> In order to decide which LCD Overlay Manager to configure(LCD/LCD2),
>> there is a need for the omap_dss_device instances to tell the
>> interface drivers(DSI, DPI, RFBI etc) which LCD channel they want to
>> connect to, so that the corresponding registers get configured.
>> Therefore, a new enum omap_channel member is introduced to omap_dss_device.
>>
>> This design was made keeping in mind the possible addition of more
>> Overlay Managers in future OMAPs, this code is also backward
>> compatible with OMAP3 as omap_dss_device instances in OMAP3 will stick
>> only with OMAP_DSS_CHANNEL_LCD.
>>
>> This will apply over the set of dss_feature framework patches:
>> http://www.mail-archive.com/linux-omap@vger.kernel.org/msg34768.html
>
> The patchset makes dispc API changes in patch 2, but doesn't
> change any of the code that uses that API. This means that
> the kernel doesn't compile after applying patch 2.
>
> The kernel has to be compilable and working after each patch, so that is not
> acceptable.
>
> Fixing that in easy way would mean squashing the later
> patches together with patch 2, but that would result in a
> huge patch, and patch 2 is already very big. Thus I'd suggest
> doing the changes in smaller bits.
>
> You could first add the register definitions, and make the
> changes in dispc.c to keep everything working. After that you
> could change the dispc functions, one by one or in small
> groups (depending on the amount of changes), and add the
> channel argument and adjusting the code using those functions in the same
> time.
>
> This would solve the problem of keeping the kernel working,
> and would make the patches much more readable.
Thanks, will take care of this.
Archit
^ permalink raw reply
* [PATCH v3] i2c/mux: Driver for PCA9541 I2C Master Selector
From: Guenter Roeck @ 2010-10-20 3:55 UTC (permalink / raw)
To: Jean Delvare
Cc: Ben Dooks, Rodolfo Giometti, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Guenter Roeck
This patch adds support for PCA9541, an I2C Bus Master Selector.
The driver is modeled as single channel I2C Multiplexer to be able to utilize
the I2C multiplexer framework.
Signed-off-by: Guenter Roeck <guenter.roeck-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org>
Reviewed-by: Tom Grennan <tom.grennan-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org>
---
v3 changes:
- Clarified and cleaned up comments.
- No longer pass "struct i2c_adapter *" as parameter.
Get it from client->adapter if needed.
- No longer pass "struct pca9541 *" as parameter.
Pass "struct i2c_client *" instead and get "struct pca9541 *" from it
if needed.
- Removed "struct i2c_client *client" from struct pca9541 since it is
no longer needed.
- Moved "pca9541_release_bus(client);" ahead of i2c_add_mux_adapter()
to avoid a possible race condition. Also protect the call with
i2c_lock_adapter() / i2c_unlock_adapter().
- Removed __devinit from pca9541_probe() and __devexit from pca9541_remove().
v2 changes:
- Added more detailed description and reasoning why the driver was implemented
as single-channel multiplexer.
- Modified arbitration algorithm, since access to i2c masters from interrupt
level is not a good idea. Instead of using hrtimers and handling arbitration
in interrupt, handle it from select_chan and either delay for short retry
periods or sleep for long (millisecond) periods.
drivers/i2c/muxes/Kconfig | 10 +
drivers/i2c/muxes/Makefile | 1 +
drivers/i2c/muxes/pca9541.c | 411 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 422 insertions(+), 0 deletions(-)
create mode 100644 drivers/i2c/muxes/pca9541.c
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 4c9a99c..4d91d80 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -5,6 +5,16 @@
menu "Multiplexer I2C Chip support"
depends on I2C_MUX
+config I2C_MUX_PCA9541
+ tristate "NXP PCA9541 I2C Master Selector"
+ depends on EXPERIMENTAL
+ help
+ If you say yes here you get support for the NXP PCA9541
+ I2C Master Selector.
+
+ This driver can also be built as a module. If so, the module
+ will be called pca9541.
+
config I2C_MUX_PCA954x
tristate "Philips PCA954x I2C Mux/switches"
depends on EXPERIMENTAL
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index bd83b52..4e27d0d 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -1,6 +1,7 @@
#
# Makefile for multiplexer I2C chip drivers.
+obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o
obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c
new file mode 100644
index 0000000..ed699c5
--- /dev/null
+++ b/drivers/i2c/muxes/pca9541.c
@@ -0,0 +1,411 @@
+/*
+ * I2C multiplexer driver for PCA9541 bus master selector
+ *
+ * Copyright (c) 2010 Ericsson AB.
+ *
+ * Author: Guenter Roeck <guenter.roeck-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org>
+ *
+ * Derived from:
+ * pca954x.c
+ *
+ * Copyright (c) 2008-2009 Rodolfo Giometti <giometti-k2GhghHVRtY@public.gmane.org>
+ * Copyright (c) 2008-2009 Eurotech S.p.A. <info-ymFC7zkAqBI1GQ1Ptb7lUw@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+
+#include <linux/i2c/pca954x.h>
+
+/*
+ * The PCA9541 is a bus master selector. It supports two I2C masters connected
+ * to a single slave bus.
+ *
+ * Before each bus transaction, a master has to acquire bus ownership. After the
+ * transaction is complete, bus ownership has to be released. This fits well
+ * into the I2C multiplexer framework, which provides select and release
+ * functions for this purpose. For this reason, this driver is modeled as
+ * single-channel I2C bus multiplexer.
+ *
+ * This driver assumes that the two bus masters are controlled by two different
+ * hosts. If a single host controls both masters, platform code has to ensure
+ * that only one of the masters is instantiated at any given time.
+ */
+
+#define PCA9541_CONTROL 0x01
+#define PCA9541_ISTAT 0x02
+
+#define PCA9541_CTL_MYBUS (1 << 0)
+#define PCA9541_CTL_NMYBUS (1 << 1)
+#define PCA9541_CTL_BUSON (1 << 2)
+#define PCA9541_CTL_NBUSON (1 << 3)
+#define PCA9541_CTL_BUSINIT (1 << 4)
+#define PCA9541_CTL_TESTON (1 << 6)
+#define PCA9541_CTL_NTESTON (1 << 7)
+
+#define PCA9541_ISTAT_INTIN (1 << 0)
+#define PCA9541_ISTAT_BUSINIT (1 << 1)
+#define PCA9541_ISTAT_BUSOK (1 << 2)
+#define PCA9541_ISTAT_BUSLOST (1 << 3)
+#define PCA9541_ISTAT_MYTEST (1 << 6)
+#define PCA9541_ISTAT_NMYTEST (1 << 7)
+
+#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON)
+#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS)
+#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
+#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON)
+
+/* arbitration timeouts, in jiffies */
+#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */
+#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */
+
+/* arbitration retry delays, in us */
+#define SELECT_DELAY_SHORT 50
+#define SELECT_DELAY_LONG 1000
+
+struct pca9541 {
+ struct i2c_adapter *mux_adap;
+ unsigned long select_timeout;
+ unsigned long arb_timeout;
+};
+
+static const struct i2c_device_id pca9541_id[] = {
+ {"pca9541", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pca9541_id);
+
+/*
+ * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock the adapter a second time.
+ */
+static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int ret;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg;
+ char buf[2];
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ buf[0] = command;
+ buf[1] = val;
+ msg.buf = buf;
+ ret = adap->algo->master_xfer(adap, &msg, 1);
+ } else {
+ union i2c_smbus_data data;
+
+ data.byte = val;
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_WRITE,
+ command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ }
+
+ return ret;
+}
+
+/*
+ * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock adapter a second time.
+ */
+static int pca9541_reg_read(struct i2c_client *client, u8 command)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int ret;
+ u8 val;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &command
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &val
+ }
+ };
+ ret = adap->algo->master_xfer(adap, msg, 2);
+ if (ret == 2)
+ ret = val;
+ else if (ret >= 0)
+ ret = -EIO;
+ } else {
+ union i2c_smbus_data data;
+
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_READ,
+ command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (!ret)
+ ret = data.byte;
+ }
+ return ret;
+}
+
+/*
+ * Arbitration management functions
+ */
+
+/* Release bus. Also reset NTESTON and BUSINIT if it was set. */
+static void pca9541_release_bus(struct i2c_client *client)
+{
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9541_CONTROL);
+ if (reg >= 0 && !busoff(reg) && mybus(reg))
+ pca9541_reg_write(client, PCA9541_CONTROL,
+ (reg & PCA9541_CTL_NBUSON) >> 1);
+}
+
+/*
+ * Arbitration is defined as a two-step process. A bus master can only activate
+ * the slave bus if it owns it; otherwise it has to request ownership first.
+ * This multi-step process ensures that access contention is resolved
+ * gracefully.
+ *
+ * Bus Ownership Other master Action
+ * state requested access
+ * ----------------------------------------------------
+ * off - yes wait for arbitration timeout or
+ * for other master to drop request
+ * off no no take ownership
+ * off yes no turn on bus
+ * on yes - done
+ * on no - wait for arbitration timeout or
+ * for other master to release bus
+ *
+ * The main contention point occurs if the slave bus is off and both masters
+ * request ownership at the same time. In this case, one master will turn on
+ * the slave bus, believing that it owns it. The other master will request
+ * bus ownership. Result is that the bus is turned on, and master which did
+ * _not_ own the slave bus before ends up owning it.
+ */
+
+/* Control commands per PCA9541 datasheet */
+static const u8 pca9541_control[16] = {
+ 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1
+};
+
+/*
+ * Channel arbitration
+ *
+ * Return values:
+ * <0: error
+ * 0 : bus not acquired
+ * 1 : bus acquired
+ */
+static int pca9541_arbitrate(struct i2c_client *client)
+{
+ struct pca9541 *data = i2c_get_clientdata(client);
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9541_CONTROL);
+ if (reg < 0)
+ return reg;
+
+ if (busoff(reg)) {
+ int istat;
+ /*
+ * Bus is off. Request ownership or turn it on unless
+ * other master requested ownership.
+ */
+ istat = pca9541_reg_read(client, PCA9541_ISTAT);
+ if (!(istat & PCA9541_ISTAT_NMYTEST)
+ || time_is_before_eq_jiffies(data->arb_timeout)) {
+ /*
+ * Other master did not request ownership,
+ * or arbitration timeout expired. Take the bus.
+ */
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ pca9541_control[reg & 0x0f]
+ | PCA9541_CTL_NTESTON);
+ data->select_timeout = SELECT_DELAY_SHORT;
+ } else {
+ /*
+ * Other master requested ownership.
+ * Set extra long timeout to give it time to acquire it.
+ */
+ data->select_timeout = SELECT_DELAY_LONG * 2;
+ }
+ } else if (mybus(reg)) {
+ /*
+ * Bus is on, and we own it. We are done with acquisition.
+ * Reset NTESTON and BUSINIT, then return success.
+ */
+ if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT))
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ reg & ~(PCA9541_CTL_NTESTON
+ | PCA9541_CTL_BUSINIT));
+ return 1;
+ } else {
+ /*
+ * Other master owns the bus.
+ * If arbitration timeout has expired, force ownership.
+ * Otherwise request it.
+ */
+ data->select_timeout = SELECT_DELAY_LONG;
+ if (time_is_before_eq_jiffies(data->arb_timeout)) {
+ /* Time is up, take the bus and reset it. */
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ pca9541_control[reg & 0x0f]
+ | PCA9541_CTL_BUSINIT
+ | PCA9541_CTL_NTESTON);
+ } else {
+ /* Request bus ownership if needed */
+ if (!(reg & PCA9541_CTL_NTESTON))
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ reg | PCA9541_CTL_NTESTON);
+ }
+ }
+ return 0;
+}
+
+static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
+{
+ struct pca9541 *data = i2c_get_clientdata(client);
+ int ret;
+ unsigned long timeout = jiffies + ARB2_TIMEOUT;
+ /* give up after this time */
+
+ data->arb_timeout = jiffies + ARB_TIMEOUT;
+ /* force bus ownership after this time */
+
+ do {
+ ret = pca9541_arbitrate(client);
+ if (ret)
+ return ret < 0 ? ret : 0;
+
+ if (data->select_timeout == SELECT_DELAY_SHORT)
+ udelay(data->select_timeout);
+ else
+ msleep(data->select_timeout / 1000);
+ } while (time_is_after_eq_jiffies(timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int pca9541_release_chan(struct i2c_adapter *adap,
+ void *client, u32 chan)
+{
+ pca9541_release_bus(client);
+ return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int pca9541_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = client->adapter;
+ struct pca954x_platform_data *pdata = client->dev.platform_data;
+ struct pca9541 *data;
+ int force;
+ int ret = -ENODEV;
+
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto err;
+
+ data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ i2c_set_clientdata(client, data);
+
+ /*
+ * I2C accesses are unprotected here.
+ * We have to lock the adapter before releasing the bus.
+ */
+ i2c_lock_adapter(adap);
+ pca9541_release_bus(client);
+ i2c_unlock_adapter(adap);
+
+ /* Create mux adapter */
+
+ force = 0;
+ if (pdata)
+ force = pdata->modes[0].adap_id;
+ data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0,
+ pca9541_select_chan,
+ pca9541_release_chan);
+
+ if (data->mux_adap == NULL) {
+ dev_err(&client->dev, "failed to register master selector\n");
+ goto exit_free;
+ }
+
+ dev_info(&client->dev, "registered master selector for I2C %s\n",
+ client->name);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+err:
+ return ret;
+}
+
+static int pca9541_remove(struct i2c_client *client)
+{
+ struct pca9541 *data = i2c_get_clientdata(client);
+
+ i2c_del_mux_adapter(data->mux_adap);
+
+ kfree(data);
+ return 0;
+}
+
+static struct i2c_driver pca9541_driver = {
+ .driver = {
+ .name = "pca9541",
+ .owner = THIS_MODULE,
+ },
+ .probe = pca9541_probe,
+ .remove = pca9541_remove,
+ .id_table = pca9541_id,
+};
+
+static int __init pca9541_init(void)
+{
+ return i2c_add_driver(&pca9541_driver);
+}
+
+static void __exit pca9541_exit(void)
+{
+ i2c_del_driver(&pca9541_driver);
+}
+
+module_init(pca9541_init);
+module_exit(pca9541_exit);
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org>");
+MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
+MODULE_LICENSE("GPL v2");
--
1.7.3.1
^ permalink raw reply related
* Re: [PATCH] drivers/hwmon: Use pr_fmt and pr_<level>
From: Guenter Roeck @ 2010-10-20 3:53 UTC (permalink / raw)
To: Joe Perches
Cc: Jean Delvare, Hans de Goede, Alistair John Strachan,
Henrik Rydberg, Mark M. Hoffman, Luca Tettamanti, Fenghua Yu,
Juerg Haefliger, Eric Piel, Jim Cromie, Roger Lucas,
lm-sensors@lm-sensors.org, LKML
In-Reply-To: <1287545658.10409.606.camel@Joe-Laptop>
On Tue, Oct 19, 2010 at 11:34:18PM -0400, Joe Perches wrote:
> On Tue, 2010-10-19 at 20:29 -0700, Guenter Roeck wrote:
> > On Tue, Oct 19, 2010 at 07:13:40PM -0400, Joe Perches wrote:
> > > Convert printks to pr_<level>
> > > Coalesce long formats
> > > Removed prefixes from formats
> > > Added #define pr_fmt KBUILD_MODNAME ": " fmt
> > > Standardized abitguru messages for reporting and finding MAINTAINER
> > > Compiled x86 allyesconfig only.
> > > I inspected "strings drivers/hwmon/built-in.o",
> > > but it's otherwise untested.
> > > Signed-off-by: Joe Perches <joe@perches.com>
> > There are several lines longer than 80 characters.
> > Does this rule no longer apply ?
>
> 80 columns isn't checked for printk format strings.
>
Interesting.
> A kernel general preference may be to keep formats as
> a single string without line breaks so that grep works
> better.
>
> > Oddly enough, there are only four checkpatch warnings about long lines,
> > even though there are many more.
>
> The version I use doesn't show any warnings.
>
checkpatch.pl from both v2.6.36-rc7 and v2.6.36-rc6 do report warnings.
Looks like those versions flag long lines for pr_warn. Is your version
older or newer ?
Anyway, would it be possible to split the patch into one patch per file ?
I don't know how Jean thinks about it, but in my opinion it would be cleaner,
permit revert on a single patch/file instead of having to revert the entire series,
it would simplify review, and it would make it much easier to cherry-pick
pieces into other releases if needed.
Thanks,
Guenter
^ permalink raw reply
* Re: [lm-sensors] [PATCH] drivers/hwmon: Use pr_fmt and pr_<level>
From: Guenter Roeck @ 2010-10-20 3:53 UTC (permalink / raw)
To: Joe Perches
Cc: Jean Delvare, Hans de Goede, Alistair John Strachan,
Henrik Rydberg, Mark M. Hoffman, Luca Tettamanti, Fenghua Yu,
Juerg Haefliger, Eric Piel, Jim Cromie, Roger Lucas,
lm-sensors@lm-sensors.org, LKML
In-Reply-To: <1287545658.10409.606.camel@Joe-Laptop>
On Tue, Oct 19, 2010 at 11:34:18PM -0400, Joe Perches wrote:
> On Tue, 2010-10-19 at 20:29 -0700, Guenter Roeck wrote:
> > On Tue, Oct 19, 2010 at 07:13:40PM -0400, Joe Perches wrote:
> > > Convert printks to pr_<level>
> > > Coalesce long formats
> > > Removed prefixes from formats
> > > Added #define pr_fmt KBUILD_MODNAME ": " fmt
> > > Standardized abitguru messages for reporting and finding MAINTAINER
> > > Compiled x86 allyesconfig only.
> > > I inspected "strings drivers/hwmon/built-in.o",
> > > but it's otherwise untested.
> > > Signed-off-by: Joe Perches <joe@perches.com>
> > There are several lines longer than 80 characters.
> > Does this rule no longer apply ?
>
> 80 columns isn't checked for printk format strings.
>
Interesting.
> A kernel general preference may be to keep formats as
> a single string without line breaks so that grep works
> better.
>
> > Oddly enough, there are only four checkpatch warnings about long lines,
> > even though there are many more.
>
> The version I use doesn't show any warnings.
>
checkpatch.pl from both v2.6.36-rc7 and v2.6.36-rc6 do report warnings.
Looks like those versions flag long lines for pr_warn. Is your version
older or newer ?
Anyway, would it be possible to split the patch into one patch per file ?
I don't know how Jean thinks about it, but in my opinion it would be cleaner,
permit revert on a single patch/file instead of having to revert the entire series,
it would simplify review, and it would make it much easier to cherry-pick
pieces into other releases if needed.
Thanks,
Guenter
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply
* Re: [PATCH 4/6] IMA: only allocate iint when needed
From: Al Viro @ 2010-10-20 3:53 UTC (permalink / raw)
To: Eric Paris
Cc: linux-kernel, linux-security-module, linux-fsdevel, hch, zohar,
warthog9, david, jmorris, kyle, hpa, akpm, torvalds, mingo
In-Reply-To: <20101019225833.12396.56721.stgit@paris.rdu.redhat.com>
On Tue, Oct 19, 2010 at 06:58:33PM -0400, Eric Paris wrote:
> IMA always allocates an integrity structure to hold information about every
> inode, but only needed this structure to tract the number of readers and
> writers currently accessing a given inode. Since that information was moved
> into struct inode instead of the integrity struct this patch stops allocating
> the integrity stucture until it is needed. Thurs greatly reducing memory
> usage.
OK, I'm really confused. Could you explain what's going on with refcounts
now? AFAICS, you allocate them in process_measurement() now and they live
until the inode is torn down. Fine by me. However
* why bother with bumping refcount in ima_file_free()? It's not going
to die until we free the inode, for fsck sake...
* i_mutex is a damn strange choice for protecting your write counter
* for that matter, why bother with refcount at all? What could
hold a reference to that sucker without holding a reference to struct inode?
I don't see anything of that sort, other that delayed freeing that'll hold
the only remaining pointer to iint until the callback where it'll promptly
drop it.
And while we are at it, you are forcing a hash lookup on _every_ _damn_
close(2) of a regular file. How about marking the inode as ima-infested
so that it wouldn't bother? For that matter, this "final writer" logics
needs explanation as well...
^ permalink raw reply
* Re: [PATCH v3 08/11] memcg: CPU hotplug lockdep warning fix
From: Daisuke Nishimura @ 2010-10-20 3:47 UTC (permalink / raw)
To: Greg Thelen
Cc: Andrew Morton, linux-kernel, linux-mm, containers, Andrea Righi,
Balbir Singh, KAMEZAWA Hiroyuki, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <1287448784-25684-9-git-send-email-gthelen@google.com>
On Mon, 18 Oct 2010 17:39:41 -0700
Greg Thelen <gthelen@google.com> wrote:
> From: Balbir Singh <balbir@linux.vnet.ibm.com>
>
> memcg has lockdep warnings (sleep inside rcu lock)
>
> From: Balbir Singh <balbir@linux.vnet.ibm.com>
>
> Recent move to get_online_cpus() ends up calling get_online_cpus() from
> mem_cgroup_read_stat(). However mem_cgroup_read_stat() is called under rcu
> lock. get_online_cpus() can sleep. The dirty limit patches expose
> this BUG more readily due to their usage of mem_cgroup_page_stat()
>
> This patch address this issue as identified by lockdep and moves the
> hotplug protection to a higher layer. This might increase the time
> required to hotplug, but not by much.
>
> Warning messages
>
> BUG: sleeping function called from invalid context at kernel/cpu.c:62
> in_atomic(): 0, irqs_disabled(): 0, pid: 6325, name: pagetest
> 2 locks held by pagetest/6325:
> do_page_fault+0x27d/0x4a0
> mem_cgroup_page_stat+0x0/0x23f
> Pid: 6325, comm: pagetest Not tainted 2.6.36-rc5-mm1+ #201
> Call Trace:
> [<ffffffff81041224>] __might_sleep+0x12d/0x131
> [<ffffffff8104f4af>] get_online_cpus+0x1c/0x51
> [<ffffffff8110eedb>] mem_cgroup_read_stat+0x27/0xa3
> [<ffffffff811125d2>] mem_cgroup_page_stat+0x131/0x23f
> [<ffffffff811124a1>] ? mem_cgroup_page_stat+0x0/0x23f
> [<ffffffff810d57c3>] global_dirty_limits+0x42/0xf8
> [<ffffffff810d58b3>] throttle_vm_writeout+0x3a/0xb4
> [<ffffffff810dc2f8>] shrink_zone+0x3e6/0x3f8
> [<ffffffff81074a35>] ? ktime_get_ts+0xb2/0xbf
> [<ffffffff810dd1aa>] do_try_to_free_pages+0x106/0x478
> [<ffffffff810dd601>] try_to_free_mem_cgroup_pages+0xe5/0x14c
> [<ffffffff8110f947>] mem_cgroup_hierarchical_reclaim+0x314/0x3a2
> [<ffffffff81111b31>] __mem_cgroup_try_charge+0x29b/0x593
> [<ffffffff8111194a>] ? __mem_cgroup_try_charge+0xb4/0x593
> [<ffffffff81071258>] ? local_clock+0x40/0x59
> [<ffffffff81009015>] ? sched_clock+0x9/0xd
> [<ffffffff810710d5>] ? sched_clock_local+0x1c/0x82
> [<ffffffff8111398a>] mem_cgroup_charge_common+0x4b/0x76
> [<ffffffff81141469>] ? bio_add_page+0x36/0x38
> [<ffffffff81113ba9>] mem_cgroup_cache_charge+0x1f4/0x214
> [<ffffffff810cd195>] add_to_page_cache_locked+0x4a/0x148
> ....
>
> Acked-by: Greg Thelen <gthelen@google.com>
> Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
^ permalink raw reply
* Re: [PATCH v3 10/11] writeback: make determine_dirtyable_memory() static.
From: Daisuke Nishimura @ 2010-10-20 3:47 UTC (permalink / raw)
To: Greg Thelen
Cc: Daisuke Nishimura, Andrew Morton, linux-kernel, linux-mm,
containers, Andrea Righi, Balbir Singh, KAMEZAWA Hiroyuki,
Minchan Kim, Ciju Rajan K, David Rientjes
In-Reply-To: <1287448784-25684-11-git-send-email-gthelen@google.com>
On Mon, 18 Oct 2010 17:39:43 -0700
Greg Thelen <gthelen@google.com> wrote:
> The determine_dirtyable_memory() function is not used outside of
> page writeback. Make the routine static. No functional change.
> Just a cleanup in preparation for a change that adds memcg dirty
> limits consideration into global_dirty_limits().
>
> Signed-off-by: Andrea Righi <arighi@develer.com>
> Signed-off-by: Greg Thelen <gthelen@google.com>
Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
^ permalink raw reply
* Re: [PATCH v3 09/11] memcg: add cgroupfs interface to memcg dirty limits
From: KAMEZAWA Hiroyuki @ 2010-10-20 3:44 UTC (permalink / raw)
To: Daisuke Nishimura
Cc: Greg Thelen, Andrew Morton, linux-kernel, linux-mm, containers,
Andrea Righi, Balbir Singh, Minchan Kim, Ciju Rajan K,
David Rientjes
In-Reply-To: <20101020123110.fd269ab4.nishimura@mxp.nes.nec.co.jp>
On Wed, 20 Oct 2010 12:31:10 +0900
Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> wrote:
> On Mon, 18 Oct 2010 17:39:42 -0700
> Greg Thelen <gthelen@google.com> wrote:
>
> > Add cgroupfs interface to memcg dirty page limits:
> > Direct write-out is controlled with:
> > - memory.dirty_ratio
> > - memory.dirty_limit_in_bytes
> >
> > Background write-out is controlled with:
> > - memory.dirty_background_ratio
> > - memory.dirty_background_limit_bytes
> >
> > Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g'
> > and 'G' suffixes for byte counts. This patch provides the
> > same functionality for memory.dirty_limit_in_bytes and
> > memory.dirty_background_limit_bytes.
> >
> > Signed-off-by: Andrea Righi <arighi@develer.com>
> > Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
> > Signed-off-by: Greg Thelen <gthelen@google.com>
>
> Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
>
> One question: shouldn't we return -EINVAL when writing to dirty(_background)_limit_bytes
> a bigger value than that of global one(if any)
This should be checked. I'm now writing one add-on.
> ? Or do you intentionally
> set the input value without comparing it with the global value ?
please see my patch sent(memcg+dirtylimit] Fix overwriting global vm dirty limit setting by memcg)
IMHO, check at setting value is not helpful because global value can be changed
after we set this. My patch checks it at calculating dirtyable bytes.
> But, hmm..., IMHO we should check it in __mem_cgroup_dirty_param() or something
> not to allow dirty pages more than global limit.
>
yes.
Thanks,
-Kame
^ permalink raw reply
* [Qemu-devel] Re: Git server hung
From: Michael Crawford @ 2010-10-20 3:50 UTC (permalink / raw)
To: qemu-devel
In-Reply-To: <AANLkTi=Z-YEJ_567jaD1cYA7a+pyv1ZTJM_wMqgrpBmb@mail.gmail.com>
> git clone http://git.qemu.org/qemu.git
>
> This initializes a repository in qemu/.git and starts downloading from
> the git server.
>
> After 60 or 70 mb - as seen via "du -s" it stops downloading. The
> "git clone" never completes.
After a long time I got the following. Perhaps someone had a commit
in progress?
error: Recv failure: Connection timed out (curl_result = 56, http_code
= 0, sha1 = 61ca9c42095a78cd81f28a2b18da4993b12be128)
error: Unable to find ac82067acb19f88ccf451b0fd37bfb9d4b7d03e9 under
http://git.qemu.org/qemu.git
Cannot obtain needed blob ac82067acb19f88ccf451b0fd37bfb9d4b7d03e9
while processing commit fc29df759e7499446220349809a920ed2dfbc466.
error: Fetch failed.
Mike
--
Michael David Crawford
mdcrawford at gmail dot com
GoingWare's Bag of Programming Tricks
http://www.goingware.com/tips/
^ permalink raw reply
* Re: [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
From: viresh kumar @ 2010-10-20 3:49 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Pratyush ANAND,
Shiraz HASHIM, Vipin KUMAR, Deepak SIKRI, Armando VISCONTI,
Vipul Kumar SAMAR, Rajeev KUMAR, Bhupesh SHARMA, Amit VIRDI
In-Reply-To: <20101019144803.96d59689.akpm@linux-foundation.org>
On 10/20/2010 03:18 AM, Andrew Morton wrote:
>> > Andrew,
>> >
>> > Any review comments on this patch??
>> >
> I looked.
>
> I'd suggest cc'ing the PCI list and maintainer on future versions.
Will do that.
Thanks
viresh
^ permalink raw reply
* Re: [PATCH v3 02/11] memcg: document cgroup dirty memory interfaces
From: Daisuke Nishimura @ 2010-10-20 3:47 UTC (permalink / raw)
To: KAMEZAWA Hiroyuki
Cc: Greg Thelen, Andrew Morton, linux-kernel, linux-mm, containers,
Andrea Righi, Balbir Singh, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <20101020112431.b76b861d.kamezawa.hiroyu@jp.fujitsu.com>
On Wed, 20 Oct 2010 11:24:31 +0900
KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
> On Wed, 20 Oct 2010 10:14:21 +0900
> KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
>
> > On Wed, 20 Oct 2010 09:48:21 +0900
> > Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> wrote:
> >
> > > On Wed, 20 Oct 2010 09:11:09 +0900
> > > KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
> > >
> > > > On Tue, 19 Oct 2010 14:00:58 -0700
> > > > Greg Thelen <gthelen@google.com> wrote:
> > > >
> > > (snip)
> > > > > +When use_hierarchy=0, each cgroup has independent dirty memory usage and limits.
> > > > > +
> > > > > +When use_hierarchy=1, a parent cgroup increasing its dirty memory usage will
> > > > > +compare its total_dirty memory (which includes sum of all child cgroup dirty
> > > > > +memory) to its dirty limits. This keeps a parent from explicitly exceeding its
> > > > > +dirty limits. However, a child cgroup can increase its dirty usage without
> > > > > +considering the parent's dirty limits. Thus the parent's total_dirty can exceed
> > > > > +the parent's dirty limits as a child dirties pages.
> > > >
> > > > Hmm. in short, dirty_ratio in use_hierarchy=1 doesn't work as an user expects.
> > > > Is this a spec. or a current implementation ?
> > > >
> > > > I think as following.
> > > > - add a limitation as "At setting chidlren's dirty_ratio, it must be below parent's.
> > > > If it exceeds parent's dirty_ratio, EINVAL is returned."
> > > >
> > > > Could you modify setting memory.dirty_ratio code ?
> > > > Then, parent's dirty_ratio will never exceeds its own. (If I understand correctly.)
> > > >
> > > > "memory.dirty_limit_in_bytes" will be a bit more complecated, but I think you can.
> > > >
> > > I agree.
> > >
> > > At the first impression, this limitation seems a bit overkill for me, because
> > > we allow memory.limit_in_bytes of a child bigger than that of parent now.
> > > But considering more, the situation is different, because usage_in_bytes never
> > > exceeds limit_in_bytes.
> > >
> >
> > I'd like to consider a patch.
> > Please mention that "use_hierarchy=1 case depends on implemenation." for now.
> >
>
> BTW, how about supporing dirty_limit_in_bytes when use_hierarchy=0 or leave it as
> broken when use_hierarchy=1 ?
> It seems we can only support dirty_ratio when hierarchy is used.
>
It's all right for me.
This feature would be useful even w/o hierarchy support.
Thanks,
Daisuke Nishimura.
^ permalink raw reply
* [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
From: viresh kumar @ 2010-10-20 3:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20101019144803.96d59689.akpm@linux-foundation.org>
On 10/20/2010 03:18 AM, Andrew Morton wrote:
>> > Andrew,
>> >
>> > Any review comments on this patch??
>> >
> I looked.
>
> I'd suggest cc'ing the PCI list and maintainer on future versions.
Will do that.
Thanks
viresh
^ permalink raw reply
* Re: [PATCH v3 09/11] memcg: add cgroupfs interface to memcg dirty limits
From: Daisuke Nishimura @ 2010-10-20 3:46 UTC (permalink / raw)
To: Greg Thelen
Cc: Andrew Morton, linux-kernel, linux-mm, containers, Andrea Righi,
Balbir Singh, KAMEZAWA Hiroyuki, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <20101020123110.fd269ab4.nishimura@mxp.nes.nec.co.jp>
On Wed, 20 Oct 2010 12:31:10 +0900
Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> wrote:
> On Mon, 18 Oct 2010 17:39:42 -0700
> Greg Thelen <gthelen@google.com> wrote:
>
> > Add cgroupfs interface to memcg dirty page limits:
> > Direct write-out is controlled with:
> > - memory.dirty_ratio
> > - memory.dirty_limit_in_bytes
> >
> > Background write-out is controlled with:
> > - memory.dirty_background_ratio
> > - memory.dirty_background_limit_bytes
> >
> > Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g'
> > and 'G' suffixes for byte counts. This patch provides the
> > same functionality for memory.dirty_limit_in_bytes and
> > memory.dirty_background_limit_bytes.
> >
> > Signed-off-by: Andrea Righi <arighi@develer.com>
> > Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
> > Signed-off-by: Greg Thelen <gthelen@google.com>
>
> Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
>
> One question: shouldn't we return -EINVAL when writing to dirty(_background)_limit_bytes
> a bigger value than that of global one(if any) ? Or do you intentionally
> set the input value without comparing it with the global value ?
> But, hmm..., IMHO we should check it in __mem_cgroup_dirty_param() or something
> not to allow dirty pages more than global limit.
>
Oh, Kamazawa-san has just send a fix for this problem :)
Please ignore this comment.
Thanks,
Daisuke Nishimura.
^ permalink raw reply
* Re: [PATCH 2/2] rcu,cleanup: simplify the code when cpu is dying
From: Lai Jiangshan @ 2010-10-20 3:52 UTC (permalink / raw)
To: paulmck; +Cc: Ingo Molnar, LKML
In-Reply-To: <20101019183216.GC2362@linux.vnet.ibm.com>
On 10/20/2010 02:32 AM, Paul E. McKenney wrote:
> rsp->n_force_qs, rsp->n_force_qs_ngp,
> rsp->n_force_qs - rsp->n_force_qs_ngp,
> - rsp->n_force_qs_lh);
> + rsp->n_force_qs_lh, rsp->orphan_qlen);
> for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
> if (rnp->level != level) {
> seq_puts(m, "\n");
>
>
rsp->orphan_qlen is still removed in new patch, is it a big problem for
users who trace rcu by these files?
^ permalink raw reply
* Re: oom_killer crash linux system
From: Figo.zhang @ 2010-10-20 3:43 UTC (permalink / raw)
To: KOSAKI Motohiro, Wu Fengguang
Cc: KAMEZAWA Hiroyuki, Minchan Kim, linux-kernel@vger.kernel.org,
rientjes@google.com, figo1802, linux-mm@kvack.org
In-Reply-To: <20101020122137.1824.A69D9226@jp.fujitsu.com>
> > active_anon:398375 inactive_anon:82967 isolated_anon:0
> > active_file:81 inactive_file:429 isolated_file:32
> > unevictable:13 dirty:2 writeback:14 unstable:0
> > free:11942 slab_reclaimable:2391 slab_unreclaimable:3303
> > mapped:5617 shmem:33909 pagetables:2280 bounce:0
>
> active_anon + inactive_anon + isolated_anon = 481342 pages ~= 1.8GB
> Um, this oom doesn't makes accounting lost.
>
> > here is the page-types log:
> > flags page-count MB symbolic-flags long-symbolic-flags
> >
> > 0x0000000000005828 83024 324 ___U_l_____Ma_b___________________ uptodate,lru,mmap,anonymous,swapbacked
> > 0x0000000000005868 358737 1401 ___U_lA____Ma_b___________________ uptodate,lru,active,mmap,anonymous,swapbacked
> > total 515071 2011
>
> page-types show similar result.
>
>
> The big difference is, previous and current are showing some different processes.
> only previous has VirtualBox, only current has vmware-usbarbit, etc..
>
> Can you use same test environment?
yes, it is the same desktop, and i open some pdf files and applications
by random.
but when my desktop eat up to 1.8GB RAM (active_anon + inactive_anon +
isolated_anon = 481342 pages >= 1.8GB), the system became extraordinary
slow. when i move the mouse, the mouse cant move a little on screen. i
deem it have "crashed", but i ping it's ip by other desktop, it is ok.
so what is apect affect the system seem to "crashed", page-writeback?
page-reclaimed? and the oom-killer seem to be very conservative? in
that condition , oom_killer must kill some process to release memory for
new process.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: oom_killer crash linux system
From: Figo.zhang @ 2010-10-20 3:43 UTC (permalink / raw)
To: KOSAKI Motohiro, Wu Fengguang
Cc: KAMEZAWA Hiroyuki, Minchan Kim, linux-kernel@vger.kernel.org,
rientjes@google.com, figo1802, linux-mm@kvack.org
In-Reply-To: <20101020122137.1824.A69D9226@jp.fujitsu.com>
> > active_anon:398375 inactive_anon:82967 isolated_anon:0
> > active_file:81 inactive_file:429 isolated_file:32
> > unevictable:13 dirty:2 writeback:14 unstable:0
> > free:11942 slab_reclaimable:2391 slab_unreclaimable:3303
> > mapped:5617 shmem:33909 pagetables:2280 bounce:0
>
> active_anon + inactive_anon + isolated_anon = 481342 pages ~= 1.8GB
> Um, this oom doesn't makes accounting lost.
>
> > here is the page-types log:
> > flags page-count MB symbolic-flags long-symbolic-flags
> >
> > 0x0000000000005828 83024 324 ___U_l_____Ma_b___________________ uptodate,lru,mmap,anonymous,swapbacked
> > 0x0000000000005868 358737 1401 ___U_lA____Ma_b___________________ uptodate,lru,active,mmap,anonymous,swapbacked
> > total 515071 2011
>
> page-types show similar result.
>
>
> The big difference is, previous and current are showing some different processes.
> only previous has VirtualBox, only current has vmware-usbarbit, etc..
>
> Can you use same test environment?
yes, it is the same desktop, and i open some pdf files and applications
by random.
but when my desktop eat up to 1.8GB RAM (active_anon + inactive_anon +
isolated_anon = 481342 pages >= 1.8GB), the system became extraordinary
slow. when i move the mouse, the mouse cant move a little on screen. i
deem it have "crashed", but i ping it's ip by other desktop, it is ok.
so what is apect affect the system seem to "crashed", page-writeback?
page-reclaimed? and the oom-killer seem to be very conservative? in
that condition , oom_killer must kill some process to release memory for
new process.
^ permalink raw reply
* Re: [PATCH v3 08/11] memcg: CPU hotplug lockdep warning fix
From: Daisuke Nishimura @ 2010-10-20 3:47 UTC (permalink / raw)
To: Greg Thelen
Cc: Andrew Morton, linux-kernel, linux-mm, containers, Andrea Righi,
Balbir Singh, KAMEZAWA Hiroyuki, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <1287448784-25684-9-git-send-email-gthelen@google.com>
On Mon, 18 Oct 2010 17:39:41 -0700
Greg Thelen <gthelen@google.com> wrote:
> From: Balbir Singh <balbir@linux.vnet.ibm.com>
>
> memcg has lockdep warnings (sleep inside rcu lock)
>
> From: Balbir Singh <balbir@linux.vnet.ibm.com>
>
> Recent move to get_online_cpus() ends up calling get_online_cpus() from
> mem_cgroup_read_stat(). However mem_cgroup_read_stat() is called under rcu
> lock. get_online_cpus() can sleep. The dirty limit patches expose
> this BUG more readily due to their usage of mem_cgroup_page_stat()
>
> This patch address this issue as identified by lockdep and moves the
> hotplug protection to a higher layer. This might increase the time
> required to hotplug, but not by much.
>
> Warning messages
>
> BUG: sleeping function called from invalid context at kernel/cpu.c:62
> in_atomic(): 0, irqs_disabled(): 0, pid: 6325, name: pagetest
> 2 locks held by pagetest/6325:
> do_page_fault+0x27d/0x4a0
> mem_cgroup_page_stat+0x0/0x23f
> Pid: 6325, comm: pagetest Not tainted 2.6.36-rc5-mm1+ #201
> Call Trace:
> [<ffffffff81041224>] __might_sleep+0x12d/0x131
> [<ffffffff8104f4af>] get_online_cpus+0x1c/0x51
> [<ffffffff8110eedb>] mem_cgroup_read_stat+0x27/0xa3
> [<ffffffff811125d2>] mem_cgroup_page_stat+0x131/0x23f
> [<ffffffff811124a1>] ? mem_cgroup_page_stat+0x0/0x23f
> [<ffffffff810d57c3>] global_dirty_limits+0x42/0xf8
> [<ffffffff810d58b3>] throttle_vm_writeout+0x3a/0xb4
> [<ffffffff810dc2f8>] shrink_zone+0x3e6/0x3f8
> [<ffffffff81074a35>] ? ktime_get_ts+0xb2/0xbf
> [<ffffffff810dd1aa>] do_try_to_free_pages+0x106/0x478
> [<ffffffff810dd601>] try_to_free_mem_cgroup_pages+0xe5/0x14c
> [<ffffffff8110f947>] mem_cgroup_hierarchical_reclaim+0x314/0x3a2
> [<ffffffff81111b31>] __mem_cgroup_try_charge+0x29b/0x593
> [<ffffffff8111194a>] ? __mem_cgroup_try_charge+0xb4/0x593
> [<ffffffff81071258>] ? local_clock+0x40/0x59
> [<ffffffff81009015>] ? sched_clock+0x9/0xd
> [<ffffffff810710d5>] ? sched_clock_local+0x1c/0x82
> [<ffffffff8111398a>] mem_cgroup_charge_common+0x4b/0x76
> [<ffffffff81141469>] ? bio_add_page+0x36/0x38
> [<ffffffff81113ba9>] mem_cgroup_cache_charge+0x1f4/0x214
> [<ffffffff810cd195>] add_to_page_cache_locked+0x4a/0x148
> ....
>
> Acked-by: Greg Thelen <gthelen@google.com>
> Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH v3 10/11] writeback: make determine_dirtyable_memory() static.
From: Daisuke Nishimura @ 2010-10-20 3:47 UTC (permalink / raw)
To: Greg Thelen
Cc: Daisuke Nishimura, Andrew Morton, linux-kernel, linux-mm,
containers, Andrea Righi, Balbir Singh, KAMEZAWA Hiroyuki,
Minchan Kim, Ciju Rajan K, David Rientjes
In-Reply-To: <1287448784-25684-11-git-send-email-gthelen@google.com>
On Mon, 18 Oct 2010 17:39:43 -0700
Greg Thelen <gthelen@google.com> wrote:
> The determine_dirtyable_memory() function is not used outside of
> page writeback. Make the routine static. No functional change.
> Just a cleanup in preparation for a change that adds memcg dirty
> limits consideration into global_dirty_limits().
>
> Signed-off-by: Andrea Righi <arighi@develer.com>
> Signed-off-by: Greg Thelen <gthelen@google.com>
Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH v3 02/11] memcg: document cgroup dirty memory interfaces
From: Daisuke Nishimura @ 2010-10-20 3:47 UTC (permalink / raw)
To: KAMEZAWA Hiroyuki
Cc: Greg Thelen, Andrew Morton, linux-kernel, linux-mm, containers,
Andrea Righi, Balbir Singh, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <20101020112431.b76b861d.kamezawa.hiroyu@jp.fujitsu.com>
On Wed, 20 Oct 2010 11:24:31 +0900
KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
> On Wed, 20 Oct 2010 10:14:21 +0900
> KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
>
> > On Wed, 20 Oct 2010 09:48:21 +0900
> > Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> wrote:
> >
> > > On Wed, 20 Oct 2010 09:11:09 +0900
> > > KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
> > >
> > > > On Tue, 19 Oct 2010 14:00:58 -0700
> > > > Greg Thelen <gthelen@google.com> wrote:
> > > >
> > > (snip)
> > > > > +When use_hierarchy=0, each cgroup has independent dirty memory usage and limits.
> > > > > +
> > > > > +When use_hierarchy=1, a parent cgroup increasing its dirty memory usage will
> > > > > +compare its total_dirty memory (which includes sum of all child cgroup dirty
> > > > > +memory) to its dirty limits. This keeps a parent from explicitly exceeding its
> > > > > +dirty limits. However, a child cgroup can increase its dirty usage without
> > > > > +considering the parent's dirty limits. Thus the parent's total_dirty can exceed
> > > > > +the parent's dirty limits as a child dirties pages.
> > > >
> > > > Hmm. in short, dirty_ratio in use_hierarchy=1 doesn't work as an user expects.
> > > > Is this a spec. or a current implementation ?
> > > >
> > > > I think as following.
> > > > - add a limitation as "At setting chidlren's dirty_ratio, it must be below parent's.
> > > > If it exceeds parent's dirty_ratio, EINVAL is returned."
> > > >
> > > > Could you modify setting memory.dirty_ratio code ?
> > > > Then, parent's dirty_ratio will never exceeds its own. (If I understand correctly.)
> > > >
> > > > "memory.dirty_limit_in_bytes" will be a bit more complecated, but I think you can.
> > > >
> > > I agree.
> > >
> > > At the first impression, this limitation seems a bit overkill for me, because
> > > we allow memory.limit_in_bytes of a child bigger than that of parent now.
> > > But considering more, the situation is different, because usage_in_bytes never
> > > exceeds limit_in_bytes.
> > >
> >
> > I'd like to consider a patch.
> > Please mention that "use_hierarchy=1 case depends on implemenation." for now.
> >
>
> BTW, how about supporing dirty_limit_in_bytes when use_hierarchy=0 or leave it as
> broken when use_hierarchy=1 ?
> It seems we can only support dirty_ratio when hierarchy is used.
>
It's all right for me.
This feature would be useful even w/o hierarchy support.
Thanks,
Daisuke Nishimura.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH v3 09/11] memcg: add cgroupfs interface to memcg dirty limits
From: Daisuke Nishimura @ 2010-10-20 3:46 UTC (permalink / raw)
To: Greg Thelen
Cc: Andrew Morton, linux-kernel, linux-mm, containers, Andrea Righi,
Balbir Singh, KAMEZAWA Hiroyuki, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <20101020123110.fd269ab4.nishimura@mxp.nes.nec.co.jp>
On Wed, 20 Oct 2010 12:31:10 +0900
Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> wrote:
> On Mon, 18 Oct 2010 17:39:42 -0700
> Greg Thelen <gthelen@google.com> wrote:
>
> > Add cgroupfs interface to memcg dirty page limits:
> > Direct write-out is controlled with:
> > - memory.dirty_ratio
> > - memory.dirty_limit_in_bytes
> >
> > Background write-out is controlled with:
> > - memory.dirty_background_ratio
> > - memory.dirty_background_limit_bytes
> >
> > Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g'
> > and 'G' suffixes for byte counts. This patch provides the
> > same functionality for memory.dirty_limit_in_bytes and
> > memory.dirty_background_limit_bytes.
> >
> > Signed-off-by: Andrea Righi <arighi@develer.com>
> > Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
> > Signed-off-by: Greg Thelen <gthelen@google.com>
>
> Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
>
> One question: shouldn't we return -EINVAL when writing to dirty(_background)_limit_bytes
> a bigger value than that of global one(if any) ? Or do you intentionally
> set the input value without comparing it with the global value ?
> But, hmm..., IMHO we should check it in __mem_cgroup_dirty_param() or something
> not to allow dirty pages more than global limit.
>
Oh, Kamazawa-san has just send a fix for this problem :)
Please ignore this comment.
Thanks,
Daisuke Nishimura.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH 1/3] Introduce threadlets
From: Venkateswararao Jujjuri (JV) @ 2010-10-20 3:46 UTC (permalink / raw)
To: balbir; +Cc: Arun R Bharadwaj, qemu-devel
In-Reply-To: <20101020022217.GL15844@balbir.in.ibm.com>
On 10/19/2010 7:22 PM, Balbir Singh wrote:
> * Anthony Liguori <anthony@codemonkey.ws> [2010-10-19 16:36:31]:
>
>> On 10/19/2010 01:36 PM, Balbir Singh wrote:
>>>> + qemu_mutex_lock(&(queue->lock));
>>>> + while (1) {
>>>> + ThreadletWork *work;
>>>> + int ret = 0;
>>>> +
>>>> + while (QTAILQ_EMPTY(&(queue->request_list))&&
>>>> + (ret != ETIMEDOUT)) {
>>>> + ret = qemu_cond_timedwait(&(queue->cond),
>>>> + &(queue->lock), 10*100000);
>>> Ewww... what is 10*100000, can we use something more meaningful
>>> please?
>>
>> A define is fine but honestly, it's pretty darn obvious what it means...
>>
>>>> + }
>>>> +
>>>> + assert(queue->idle_threads != 0);
>>> This assertion holds because we believe one of the idle_threads
>>> actually did the dequeuing, right?
>>
>> An idle thread is a thread is one that is not doing work. At this
>> point in the code, we are not doing any work (yet) so if
>> idle_threads count is zero, something is horribly wrong. We're also
>> going to unconditionally decrement in the future code path which
>> means that if idle_threads is 0, it's going to become -1.
>>
>> The use of idle_thread is to detect whether it's necessary to spawn
>> an additional thread.
>>
>
> We can hit this assert if pthread_cond_signal() is called outside of
> the mutex, let me try and explain below
>
>>>> + if (QTAILQ_EMPTY(&(queue->request_list))) {
>>>> + if (queue->cur_threads> queue->min_threads) {
>>>> + /* We retain the minimum number of threads */
>>>> + break;
>>>> + }
>>>> + } else {
>>>> + work = QTAILQ_FIRST(&(queue->request_list));
>>>> + QTAILQ_REMOVE(&(queue->request_list), work, node);
>>>> +
>>>> + queue->idle_threads--;
>>>> + qemu_mutex_unlock(&(queue->lock));
>>>> +
>>>> + /* execute the work function */
>>>> + work->func(work);
>>>> +
>>>> + qemu_mutex_lock(&(queue->lock));
>>>> + queue->idle_threads++;
>>>> + }
>>>> + }
>>>> +
>>>> + queue->idle_threads--;
>>>> + queue->cur_threads--;
>>>> + qemu_mutex_unlock(&(queue->lock));
>>>> +
>>>> + return NULL;
>>> Does anybody do a join on the exiting thread from the pool?
>>
>> No. The thread is created in a detached state.
>>
>
> That makes sense, thanks for clarifying
>
>>>> +}
>>>> +
>>>> +static void spawn_threadlet(ThreadletQueue *queue)
>>>> +{
>>>> + QemuThread thread;
>>>> +
>>>> + queue->cur_threads++;
>>>> + queue->idle_threads++;
>>>> +
>>>> + qemu_thread_create(&thread, threadlet_worker, queue);
>>>> +}
>>>> +
>>>> +/**
>>>> + * submit_threadletwork_to_queue: Submit a new task to a private queue to be
>>>> + * executed asynchronously.
>>>> + * @queue: Per-subsystem private queue to which the new task needs
>>>> + * to be submitted.
>>>> + * @work: Contains information about the task that needs to be submitted.
>>>> + */
>>>> +void submit_threadletwork_to_queue(ThreadletQueue *queue, ThreadletWork *work)
>>>> +{
>>>> + qemu_mutex_lock(&(queue->lock));
>>>> + if (queue->idle_threads == 0&& queue->cur_threads< queue->max_threads) {
>>>> + spawn_threadlet(queue);
>>> So we hold queue->lock, spawn the thread, the spawned thread tries to
>>> acquire queue->lock
>>
>> Yup.
>>
>>>> + }
>>>> + QTAILQ_INSERT_TAIL(&(queue->request_list), work, node);
>>>> + qemu_mutex_unlock(&(queue->lock));
>>>> + qemu_cond_signal(&(queue->cond));
>>> In the case that we just spawned the threadlet, the cond_signal is
>>> spurious. If we need predictable scheduling behaviour,
>>> qemu_cond_signal needs to happen with queue->lock held.
>>
>> It doesn't really affect predictability..
>>
>>> I'd rewrite the function as
>>>
>>> /**
>>> * submit_threadletwork_to_queue: Submit a new task to a private queue to be
>>> * executed asynchronously.
>>> * @queue: Per-subsystem private queue to which the new task needs
>>> * to be submitted.
>>> * @work: Contains information about the task that needs to be submitted.
>>> */
>>> void submit_threadletwork_to_queue(ThreadletQueue *queue, ThreadletWork *work)
>>> {
>>> qemu_mutex_lock(&(queue->lock));
>>> if (queue->idle_threads == 0&& (queue->cur_threads< queue->max_threads)) {
>>> spawn_threadlet(queue);
>>> } else {
>>> qemu_cond_signal(&(queue->cond));
>>> }
>>> QTAILQ_INSERT_TAIL(&(queue->request_list), work, node);
>>> qemu_mutex_unlock(&(queue->lock));
>>> }
>>
>> I think this is a lot more fragile. You're relying on the fact that
>> signal will not cause the signalled thread to actually awaken until
>> we release the lock and doing work after signalling that the
>> signalled thread needs to be completed before it wakes up.
>>
>> I think you're a lot more robust in the long term if you treat
>> condition signalling as a hand off point because it makes the code a
>> lot more explicit about what's happening.
>>
>
> OK, here is a situation that can happen
>
> T1 T2
> --- ---
> threadlet submit_threadletwork_to_queue
> (sees condition as no work) mutex_lock
> qemu_cond_timedwait add_work
> ... mutex_unlock
>
> T3
> --
> cancel_threadlet_work_on_queue
> mutex_lock (grabs it) before T1 can
> cancels the work
>
>
> qemu_cond_signal
>
> T1
> --
> Grabs mutex_lock (from within cond_timedwait)
> Now there is no work to do, the condition
> has changed before the thread wakes up
So what? It won't find any work and goes back to sleep or exits.
idle_threads is decremented only in threadlet_worker(). Given that
we have a threadlet that is not doing anywork the assert should never hit unless
something horribly wrong .
- JV
>
>
> The man page also states
>
> "however, if predictable scheduling behavior is required, then that
> mutex shall be locked by the thread calling pthread_cond_broadcast()
> or pthread_cond_signal()"
>
>>>> +/**
>>>> + * submit_threadletwork: Submit to the global queue a new task to be executed
>>>> + * asynchronously.
>>>> + * @work: Contains information about the task that needs to be submitted.
>>>> + */
>>>> +void submit_threadletwork(ThreadletWork *work)
>>>> +{
>>>> + if (unlikely(!globalqueue_init)) {
>>>> + threadlet_queue_init(&globalqueue, MAX_GLOBAL_THREADS,
>>>> + MIN_GLOBAL_THREADS);
>>>> + globalqueue_init = 1;
>>>> + }
>>> What protects globalqueue_init?
>>
>> qemu_mutex, and that unlikely is almost certainly a premature optimization.
>>
>> Regards,
>>
>> Anthony Liguori
>>
>
^ permalink raw reply
* Re: [PATCH v3 09/11] memcg: add cgroupfs interface to memcg dirty limits
From: KAMEZAWA Hiroyuki @ 2010-10-20 3:44 UTC (permalink / raw)
To: Daisuke Nishimura
Cc: Greg Thelen, Andrew Morton, linux-kernel, linux-mm, containers,
Andrea Righi, Balbir Singh, Minchan Kim, Ciju Rajan K,
David Rientjes
In-Reply-To: <20101020123110.fd269ab4.nishimura@mxp.nes.nec.co.jp>
On Wed, 20 Oct 2010 12:31:10 +0900
Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> wrote:
> On Mon, 18 Oct 2010 17:39:42 -0700
> Greg Thelen <gthelen@google.com> wrote:
>
> > Add cgroupfs interface to memcg dirty page limits:
> > Direct write-out is controlled with:
> > - memory.dirty_ratio
> > - memory.dirty_limit_in_bytes
> >
> > Background write-out is controlled with:
> > - memory.dirty_background_ratio
> > - memory.dirty_background_limit_bytes
> >
> > Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g'
> > and 'G' suffixes for byte counts. This patch provides the
> > same functionality for memory.dirty_limit_in_bytes and
> > memory.dirty_background_limit_bytes.
> >
> > Signed-off-by: Andrea Righi <arighi@develer.com>
> > Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
> > Signed-off-by: Greg Thelen <gthelen@google.com>
>
> Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
>
> One question: shouldn't we return -EINVAL when writing to dirty(_background)_limit_bytes
> a bigger value than that of global one(if any)
This should be checked. I'm now writing one add-on.
> ? Or do you intentionally
> set the input value without comparing it with the global value ?
please see my patch sent(memcg+dirtylimit] Fix overwriting global vm dirty limit setting by memcg)
IMHO, check at setting value is not helpful because global value can be changed
after we set this. My patch checks it at calculating dirtyable bytes.
> But, hmm..., IMHO we should check it in __mem_cgroup_dirty_param() or something
> not to allow dirty pages more than global limit.
>
yes.
Thanks,
-Kame
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH v3] i2c/mux: Driver for PCA9541 I2C Master Selector
From: Guenter Roeck @ 2010-10-20 3:55 UTC (permalink / raw)
To: Jean Delvare
Cc: Ben Dooks, Rodolfo Giometti, linux-i2c, linux-kernel,
Guenter Roeck
This patch adds support for PCA9541, an I2C Bus Master Selector.
The driver is modeled as single channel I2C Multiplexer to be able to utilize
the I2C multiplexer framework.
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Reviewed-by: Tom Grennan <tom.grennan@ericsson.com>
---
v3 changes:
- Clarified and cleaned up comments.
- No longer pass "struct i2c_adapter *" as parameter.
Get it from client->adapter if needed.
- No longer pass "struct pca9541 *" as parameter.
Pass "struct i2c_client *" instead and get "struct pca9541 *" from it
if needed.
- Removed "struct i2c_client *client" from struct pca9541 since it is
no longer needed.
- Moved "pca9541_release_bus(client);" ahead of i2c_add_mux_adapter()
to avoid a possible race condition. Also protect the call with
i2c_lock_adapter() / i2c_unlock_adapter().
- Removed __devinit from pca9541_probe() and __devexit from pca9541_remove().
v2 changes:
- Added more detailed description and reasoning why the driver was implemented
as single-channel multiplexer.
- Modified arbitration algorithm, since access to i2c masters from interrupt
level is not a good idea. Instead of using hrtimers and handling arbitration
in interrupt, handle it from select_chan and either delay for short retry
periods or sleep for long (millisecond) periods.
drivers/i2c/muxes/Kconfig | 10 +
drivers/i2c/muxes/Makefile | 1 +
drivers/i2c/muxes/pca9541.c | 411 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 422 insertions(+), 0 deletions(-)
create mode 100644 drivers/i2c/muxes/pca9541.c
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 4c9a99c..4d91d80 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -5,6 +5,16 @@
menu "Multiplexer I2C Chip support"
depends on I2C_MUX
+config I2C_MUX_PCA9541
+ tristate "NXP PCA9541 I2C Master Selector"
+ depends on EXPERIMENTAL
+ help
+ If you say yes here you get support for the NXP PCA9541
+ I2C Master Selector.
+
+ This driver can also be built as a module. If so, the module
+ will be called pca9541.
+
config I2C_MUX_PCA954x
tristate "Philips PCA954x I2C Mux/switches"
depends on EXPERIMENTAL
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index bd83b52..4e27d0d 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -1,6 +1,7 @@
#
# Makefile for multiplexer I2C chip drivers.
+obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o
obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c
new file mode 100644
index 0000000..ed699c5
--- /dev/null
+++ b/drivers/i2c/muxes/pca9541.c
@@ -0,0 +1,411 @@
+/*
+ * I2C multiplexer driver for PCA9541 bus master selector
+ *
+ * Copyright (c) 2010 Ericsson AB.
+ *
+ * Author: Guenter Roeck <guenter.roeck@ericsson.com>
+ *
+ * Derived from:
+ * pca954x.c
+ *
+ * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+
+#include <linux/i2c/pca954x.h>
+
+/*
+ * The PCA9541 is a bus master selector. It supports two I2C masters connected
+ * to a single slave bus.
+ *
+ * Before each bus transaction, a master has to acquire bus ownership. After the
+ * transaction is complete, bus ownership has to be released. This fits well
+ * into the I2C multiplexer framework, which provides select and release
+ * functions for this purpose. For this reason, this driver is modeled as
+ * single-channel I2C bus multiplexer.
+ *
+ * This driver assumes that the two bus masters are controlled by two different
+ * hosts. If a single host controls both masters, platform code has to ensure
+ * that only one of the masters is instantiated at any given time.
+ */
+
+#define PCA9541_CONTROL 0x01
+#define PCA9541_ISTAT 0x02
+
+#define PCA9541_CTL_MYBUS (1 << 0)
+#define PCA9541_CTL_NMYBUS (1 << 1)
+#define PCA9541_CTL_BUSON (1 << 2)
+#define PCA9541_CTL_NBUSON (1 << 3)
+#define PCA9541_CTL_BUSINIT (1 << 4)
+#define PCA9541_CTL_TESTON (1 << 6)
+#define PCA9541_CTL_NTESTON (1 << 7)
+
+#define PCA9541_ISTAT_INTIN (1 << 0)
+#define PCA9541_ISTAT_BUSINIT (1 << 1)
+#define PCA9541_ISTAT_BUSOK (1 << 2)
+#define PCA9541_ISTAT_BUSLOST (1 << 3)
+#define PCA9541_ISTAT_MYTEST (1 << 6)
+#define PCA9541_ISTAT_NMYTEST (1 << 7)
+
+#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON)
+#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS)
+#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
+#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON)
+
+/* arbitration timeouts, in jiffies */
+#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */
+#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */
+
+/* arbitration retry delays, in us */
+#define SELECT_DELAY_SHORT 50
+#define SELECT_DELAY_LONG 1000
+
+struct pca9541 {
+ struct i2c_adapter *mux_adap;
+ unsigned long select_timeout;
+ unsigned long arb_timeout;
+};
+
+static const struct i2c_device_id pca9541_id[] = {
+ {"pca9541", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pca9541_id);
+
+/*
+ * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock the adapter a second time.
+ */
+static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int ret;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg;
+ char buf[2];
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ buf[0] = command;
+ buf[1] = val;
+ msg.buf = buf;
+ ret = adap->algo->master_xfer(adap, &msg, 1);
+ } else {
+ union i2c_smbus_data data;
+
+ data.byte = val;
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_WRITE,
+ command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ }
+
+ return ret;
+}
+
+/*
+ * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock adapter a second time.
+ */
+static int pca9541_reg_read(struct i2c_client *client, u8 command)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int ret;
+ u8 val;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &command
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &val
+ }
+ };
+ ret = adap->algo->master_xfer(adap, msg, 2);
+ if (ret == 2)
+ ret = val;
+ else if (ret >= 0)
+ ret = -EIO;
+ } else {
+ union i2c_smbus_data data;
+
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_READ,
+ command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (!ret)
+ ret = data.byte;
+ }
+ return ret;
+}
+
+/*
+ * Arbitration management functions
+ */
+
+/* Release bus. Also reset NTESTON and BUSINIT if it was set. */
+static void pca9541_release_bus(struct i2c_client *client)
+{
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9541_CONTROL);
+ if (reg >= 0 && !busoff(reg) && mybus(reg))
+ pca9541_reg_write(client, PCA9541_CONTROL,
+ (reg & PCA9541_CTL_NBUSON) >> 1);
+}
+
+/*
+ * Arbitration is defined as a two-step process. A bus master can only activate
+ * the slave bus if it owns it; otherwise it has to request ownership first.
+ * This multi-step process ensures that access contention is resolved
+ * gracefully.
+ *
+ * Bus Ownership Other master Action
+ * state requested access
+ * ----------------------------------------------------
+ * off - yes wait for arbitration timeout or
+ * for other master to drop request
+ * off no no take ownership
+ * off yes no turn on bus
+ * on yes - done
+ * on no - wait for arbitration timeout or
+ * for other master to release bus
+ *
+ * The main contention point occurs if the slave bus is off and both masters
+ * request ownership at the same time. In this case, one master will turn on
+ * the slave bus, believing that it owns it. The other master will request
+ * bus ownership. Result is that the bus is turned on, and master which did
+ * _not_ own the slave bus before ends up owning it.
+ */
+
+/* Control commands per PCA9541 datasheet */
+static const u8 pca9541_control[16] = {
+ 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1
+};
+
+/*
+ * Channel arbitration
+ *
+ * Return values:
+ * <0: error
+ * 0 : bus not acquired
+ * 1 : bus acquired
+ */
+static int pca9541_arbitrate(struct i2c_client *client)
+{
+ struct pca9541 *data = i2c_get_clientdata(client);
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9541_CONTROL);
+ if (reg < 0)
+ return reg;
+
+ if (busoff(reg)) {
+ int istat;
+ /*
+ * Bus is off. Request ownership or turn it on unless
+ * other master requested ownership.
+ */
+ istat = pca9541_reg_read(client, PCA9541_ISTAT);
+ if (!(istat & PCA9541_ISTAT_NMYTEST)
+ || time_is_before_eq_jiffies(data->arb_timeout)) {
+ /*
+ * Other master did not request ownership,
+ * or arbitration timeout expired. Take the bus.
+ */
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ pca9541_control[reg & 0x0f]
+ | PCA9541_CTL_NTESTON);
+ data->select_timeout = SELECT_DELAY_SHORT;
+ } else {
+ /*
+ * Other master requested ownership.
+ * Set extra long timeout to give it time to acquire it.
+ */
+ data->select_timeout = SELECT_DELAY_LONG * 2;
+ }
+ } else if (mybus(reg)) {
+ /*
+ * Bus is on, and we own it. We are done with acquisition.
+ * Reset NTESTON and BUSINIT, then return success.
+ */
+ if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT))
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ reg & ~(PCA9541_CTL_NTESTON
+ | PCA9541_CTL_BUSINIT));
+ return 1;
+ } else {
+ /*
+ * Other master owns the bus.
+ * If arbitration timeout has expired, force ownership.
+ * Otherwise request it.
+ */
+ data->select_timeout = SELECT_DELAY_LONG;
+ if (time_is_before_eq_jiffies(data->arb_timeout)) {
+ /* Time is up, take the bus and reset it. */
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ pca9541_control[reg & 0x0f]
+ | PCA9541_CTL_BUSINIT
+ | PCA9541_CTL_NTESTON);
+ } else {
+ /* Request bus ownership if needed */
+ if (!(reg & PCA9541_CTL_NTESTON))
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ reg | PCA9541_CTL_NTESTON);
+ }
+ }
+ return 0;
+}
+
+static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
+{
+ struct pca9541 *data = i2c_get_clientdata(client);
+ int ret;
+ unsigned long timeout = jiffies + ARB2_TIMEOUT;
+ /* give up after this time */
+
+ data->arb_timeout = jiffies + ARB_TIMEOUT;
+ /* force bus ownership after this time */
+
+ do {
+ ret = pca9541_arbitrate(client);
+ if (ret)
+ return ret < 0 ? ret : 0;
+
+ if (data->select_timeout == SELECT_DELAY_SHORT)
+ udelay(data->select_timeout);
+ else
+ msleep(data->select_timeout / 1000);
+ } while (time_is_after_eq_jiffies(timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int pca9541_release_chan(struct i2c_adapter *adap,
+ void *client, u32 chan)
+{
+ pca9541_release_bus(client);
+ return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int pca9541_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = client->adapter;
+ struct pca954x_platform_data *pdata = client->dev.platform_data;
+ struct pca9541 *data;
+ int force;
+ int ret = -ENODEV;
+
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto err;
+
+ data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ i2c_set_clientdata(client, data);
+
+ /*
+ * I2C accesses are unprotected here.
+ * We have to lock the adapter before releasing the bus.
+ */
+ i2c_lock_adapter(adap);
+ pca9541_release_bus(client);
+ i2c_unlock_adapter(adap);
+
+ /* Create mux adapter */
+
+ force = 0;
+ if (pdata)
+ force = pdata->modes[0].adap_id;
+ data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0,
+ pca9541_select_chan,
+ pca9541_release_chan);
+
+ if (data->mux_adap == NULL) {
+ dev_err(&client->dev, "failed to register master selector\n");
+ goto exit_free;
+ }
+
+ dev_info(&client->dev, "registered master selector for I2C %s\n",
+ client->name);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+err:
+ return ret;
+}
+
+static int pca9541_remove(struct i2c_client *client)
+{
+ struct pca9541 *data = i2c_get_clientdata(client);
+
+ i2c_del_mux_adapter(data->mux_adap);
+
+ kfree(data);
+ return 0;
+}
+
+static struct i2c_driver pca9541_driver = {
+ .driver = {
+ .name = "pca9541",
+ .owner = THIS_MODULE,
+ },
+ .probe = pca9541_probe,
+ .remove = pca9541_remove,
+ .id_table = pca9541_id,
+};
+
+static int __init pca9541_init(void)
+{
+ return i2c_add_driver(&pca9541_driver);
+}
+
+static void __exit pca9541_exit(void)
+{
+ i2c_del_driver(&pca9541_driver);
+}
+
+module_init(pca9541_init);
+module_exit(pca9541_exit);
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
+MODULE_LICENSE("GPL v2");
--
1.7.3.1
^ permalink raw reply related
* [Qemu-devel] Git server hung
From: Michael Crawford @ 2010-10-20 3:38 UTC (permalink / raw)
To: qemu-devel
git clone http://git.qemu.org/qemu.git
This initializes a repository in qemu/.git and starts downloading from
the git server.
After 60 or 70 mb - as seen via "du -s" it stops downloading. The
"git clone" never completes.
How many mb should be in my .git directory?
Thanks,
Mike
--
Michael David Crawford
mdcrawford at gmail dot com
GoingWare's Bag of Programming Tricks
http://www.goingware.com/tips/
^ permalink raw reply
* Re: [PATCH v3 09/11] memcg: add cgroupfs interface to memcg dirty limits
From: Daisuke Nishimura @ 2010-10-20 3:31 UTC (permalink / raw)
To: Greg Thelen
Cc: Andrew Morton, linux-kernel, linux-mm, containers, Andrea Righi,
Balbir Singh, KAMEZAWA Hiroyuki, Minchan Kim, Ciju Rajan K,
David Rientjes, Daisuke Nishimura
In-Reply-To: <1287448784-25684-10-git-send-email-gthelen@google.com>
On Mon, 18 Oct 2010 17:39:42 -0700
Greg Thelen <gthelen@google.com> wrote:
> Add cgroupfs interface to memcg dirty page limits:
> Direct write-out is controlled with:
> - memory.dirty_ratio
> - memory.dirty_limit_in_bytes
>
> Background write-out is controlled with:
> - memory.dirty_background_ratio
> - memory.dirty_background_limit_bytes
>
> Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g'
> and 'G' suffixes for byte counts. This patch provides the
> same functionality for memory.dirty_limit_in_bytes and
> memory.dirty_background_limit_bytes.
>
> Signed-off-by: Andrea Righi <arighi@develer.com>
> Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
> Signed-off-by: Greg Thelen <gthelen@google.com>
Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
One question: shouldn't we return -EINVAL when writing to dirty(_background)_limit_bytes
a bigger value than that of global one(if any) ? Or do you intentionally
set the input value without comparing it with the global value ?
But, hmm..., IMHO we should check it in __mem_cgroup_dirty_param() or something
not to allow dirty pages more than global limit.
Thanks,
Daisuke Nishimura.
^ 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.