On devices with an AXP288, we need to wakeup from suspend when a charger
is plugged in, so that we can do charger-type detection and so that the
axp288-charger driver, which listens for our extcon events, can configure
the input-current-limit accordingly.
Cc: stable(a)vger.kernel.org
Signed-off-by: Hans de Goede <hdegoede(a)redhat.com>
---
drivers/extcon/extcon-axp288.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c
index a7f216191493..710a3bb66e95 100644
--- a/drivers/extcon/extcon-axp288.c
+++ b/drivers/extcon/extcon-axp288.c
@@ -443,9 +443,40 @@ static int axp288_extcon_probe(struct platform_device *pdev)
/* Start charger cable type detection */
axp288_extcon_enable(info);
+ device_init_wakeup(dev, true);
+ platform_set_drvdata(pdev, info);
+
+ return 0;
+}
+
+static int __maybe_unused axp288_extcon_suspend(struct device *dev)
+{
+ struct axp288_extcon_info *info = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(info->irq[VBUS_RISING_IRQ]);
+
return 0;
}
+static int __maybe_unused axp288_extcon_resume(struct device *dev)
+{
+ struct axp288_extcon_info *info = dev_get_drvdata(dev);
+
+ /*
+ * Wakeup when a charger is connected to do charger-type
+ * connection and generate an extcon event which makes the
+ * axp288 charger driver set the input current limit.
+ */
+ if (device_may_wakeup(dev))
+ disable_irq_wake(info->irq[VBUS_RISING_IRQ]);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(axp288_extcon_pm_ops, axp288_extcon_suspend,
+ axp288_extcon_resume);
+
static const struct platform_device_id axp288_extcon_table[] = {
{ .name = "axp288_extcon" },
{},
@@ -457,6 +488,7 @@ static struct platform_driver axp288_extcon_driver = {
.id_table = axp288_extcon_table,
.driver = {
.name = "axp288_extcon",
+ .pm = &axp288_extcon_pm_ops,
},
};
--
2.26.0.rc2
It was brought to my attention that this bug from 2018 was
still unresolved: 32 bit emulators like QEMU were given
64 bit hashes when running 32 bit emulation on 64 bit systems.
The personality(2) system call supports to let processes
indicate that they are 32 bit Linux to the kernel. This
was suggested by Teo in the original thread, so I just wired
it up and it solves the problem.
Programs that need the 32 bit hash only need to issue the
personality(PER_LINUX32) call and things start working.
I made a test program like this:
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/personality.h>
int main(int argc, char** argv) {
DIR* dir;
personality(PER_LINUX32);
dir = opendir("/boot");
printf("dir=%p\n", dir);
printf("readdir(dir)=%p\n", readdir(dir));
printf("errno=%d: %s\n", errno, strerror(errno));
return 0;
}
This was compiled with an ARM32 toolchain from Bootlin using
glibc 2.28 and thus suffering from the bug.
Before the patch:
$ ./readdir-bug
dir=0x86000
readdir(dir)=(nil)
errno=75: Value too large for defined data type
After the patch:
$ ./readdir-bug
dir=0x86000
readdir(dir)=0x86020
errno=0: Success
Problem solved.
Cc: Florian Weimer <fw(a)deneb.enyo.de>
Cc: Peter Maydell <peter.maydell(a)linaro.org>
Cc: Andy Lutomirski <luto(a)kernel.org>
Cc: stable(a)vger.kernel.org
Suggested-by: Theodore Ts'o <tytso(a)mit.edu>
Link: https://bugs.launchpad.net/qemu/+bug/1805913
Link: https://lore.kernel.org/lkml/87bm56vqg4.fsf@mid.deneb.enyo.de/
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=205957
Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org>
---
fs/ext4/dir.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 9aa1f75409b0..3faf9edf3e92 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/iversion.h>
#include <linux/unicode.h>
+#include <linux/personality.h>
#include "ext4.h"
#include "xattr.h"
@@ -618,6 +619,14 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
static int ext4_dir_open(struct inode * inode, struct file * filp)
{
+ /*
+ * If we are currently running e.g. a 32 bit emulator on
+ * a 64 bit machine, the emulator will indicate that it needs
+ * a 32 bit personality and thus 32 bit hashes from the file
+ * system.
+ */
+ if (personality(current->personality) == PER_LINUX32)
+ filp->f_mode |= FMODE_32BITHASH;
if (IS_ENCRYPTED(inode))
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
return 0;
--
2.24.1