From 769514dd9989ba2d968bc7514740013e24a82bb8 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 29 Nov 2010 09:19:24 -0500 Subject: [PATCH] tty fixes from git and tpm fix from f14 --- kernel.spec | 17 ++++ tpm-autodetect-itpm-devices.patch | 65 ++++++++++++++ ...-allow-reopen-when-ldisc-is-changing.patch | 84 +++++++++++++++++++ tty-ldisc-fix-open-flag-handling.patch | 54 ++++++++++++ tty-open-hangup-race-fixup.patch | 76 +++++++++++++++++ 5 files changed, 296 insertions(+) create mode 100644 tpm-autodetect-itpm-devices.patch create mode 100644 tty-dont-allow-reopen-when-ldisc-is-changing.patch create mode 100644 tty-ldisc-fix-open-flag-handling.patch create mode 100644 tty-open-hangup-race-fixup.patch diff --git a/kernel.spec b/kernel.spec index 72152fb9f..f1357e774 100644 --- a/kernel.spec +++ b/kernel.spec @@ -746,6 +746,12 @@ Patch12407: hda_realtek-handle-unset-external-amp-bits.patch Patch12410: tty-make-tiocgicount-a-handler.patch Patch12411: tty-icount-changeover-for-other-main-devices.patch +Patch12413: tpm-autodetect-itpm-devices.patch + +Patch12415: tty-dont-allow-reopen-when-ldisc-is-changing.patch +Patch12416: tty-ldisc-fix-open-flag-handling.patch +Patch12417: tty-open-hangup-race-fixup.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1393,6 +1399,12 @@ ApplyPatch hda_realtek-handle-unset-external-amp-bits.patch ApplyPatch tty-make-tiocgicount-a-handler.patch ApplyPatch tty-icount-changeover-for-other-main-devices.patch +ApplyPatch tpm-autodetect-itpm-devices.patch + +ApplyPatch tty-dont-allow-reopen-when-ldisc-is-changing.patch +ApplyPatch tty-ldisc-fix-open-flag-handling.patch +ApplyPatch tty-open-hangup-race-fixup.patch + # END OF PATCH APPLICATIONS %endif @@ -2006,6 +2018,11 @@ fi # || || %changelog +* Mon Nov 29 2010 Kyle McMartin +- tpm-autodetect-itpm-devices.patch: Auto-fix TPM issues on various + laptops which prevented suspend/resume. (#647132) +- tty fixes from kernel-git (#630464) + * Fri Nov 26 2010 Kyle McMartin - Quiet a build warning the previous INET_DIAG fix caused. diff --git a/tpm-autodetect-itpm-devices.patch b/tpm-autodetect-itpm-devices.patch new file mode 100644 index 000000000..57b5d07ed --- /dev/null +++ b/tpm-autodetect-itpm-devices.patch @@ -0,0 +1,65 @@ +commit 8cf5102c84dba60b2ea29b7e89f1a65100e20bb9 +Author: Matthew Garrett +Date: Thu Oct 21 17:31:56 2010 -0400 + + tpm: Autodetect itpm devices + + Some Lenovos have TPMs that require a quirk to function correctly. This can + be autodetected by checking whether the device has a _HID of INTC0102. This + is an invalid PNPid, and as such is discarded by the pnp layer - however + it's still present in the ACPI code, so we can pull it out that way. This + means that the quirk won't be automatically applied on non-ACPI systems, + but without ACPI we don't have any way to identify the chip anyway so I + don't think that's a great concern. + + Signed-off-by: Matthew Garrett + +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index 1030f84..c17a305 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include "tpm.h" + + #define TPM_HEADER_SIZE 10 +@@ -78,6 +79,26 @@ enum tis_defaults { + static LIST_HEAD(tis_chips); + static DEFINE_SPINLOCK(tis_lock); + ++#ifdef CONFIG_ACPI ++static int is_itpm(struct pnp_dev *dev) ++{ ++ struct acpi_device *acpi = pnp_acpi_device(dev); ++ struct acpi_hardware_id *id; ++ ++ list_for_each_entry(id, &acpi->pnp.ids, list) { ++ if (!strcmp("INTC0102", id->id)) ++ return 1; ++ } ++ ++ return 0; ++} ++#else ++static int is_itpm(struct pnp_dev *dev) ++{ ++ return 0; ++} ++#endif ++ + static int check_locality(struct tpm_chip *chip, int l) + { + if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & +@@ -472,6 +493,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + "1.2 TPM (device-id 0x%X, rev-id %d)\n", + vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); + ++ if (is_itpm(to_pnp_dev(dev))) ++ itpm = 1; ++ + if (itpm) + dev_info(dev, "Intel iTPM workaround enabled\n"); + diff --git a/tty-dont-allow-reopen-when-ldisc-is-changing.patch b/tty-dont-allow-reopen-when-ldisc-is-changing.patch new file mode 100644 index 000000000..4b822d5f9 --- /dev/null +++ b/tty-dont-allow-reopen-when-ldisc-is-changing.patch @@ -0,0 +1,84 @@ +From jirislaby@gmail.com Thu Nov 25 12:16:42 2010 +From: Jiri Slaby +Subject: [PATCH 1/1] TTY: don't allow reopen when ldisc is changing +Date: Thu, 25 Nov 2010 18:16:23 +0100 + +There are many WARNINGs like the following reported nowadays: +WARNING: at drivers/tty/tty_io.c:1331 tty_open+0x2a2/0x49a() +Hardware name: Latitude E6500 +Modules linked in: +Pid: 1207, comm: plymouthd Not tainted 2.6.37-rc3-mmotm1123 #3 +Call Trace: + [] warn_slowpath_common+0x80/0x98 + [] warn_slowpath_null+0x15/0x17 + [] tty_open+0x2a2/0x49a + [] chrdev_open+0x11d/0x146 +... + +This means tty_reopen is called without TTY_LDISC set. For further +considerations, note tty_lock is held in tty_open. TTY_LDISC is cleared in: +1) __tty_hangup from tty_ldisc_hangup to tty_ldisc_enable. During this +section tty_lock is held. + +2) tty_release via tty_ldisc_release till the end of tty existence. If +tty->count <= 1, tty_lock is taken, TTY_CLOSING bit set and then +tty_ldisc_release called. tty_reopen checks TTY_CLOSING before checking +TTY_LDISC. + +3) tty_set_ldisc from tty_ldisc_halt to tty_ldisc_enable. We: + * take tty_lock, set TTY_LDISC_CHANGING, put tty_lock + * call tty_ldisc_halt (clear TTY_LDISC), tty_lock is _not_ held + * do some other work + * take tty_lock, call tty_ldisc_enable (set TTY_LDISC), put + tty_lock + +So the only option I see is 3). The solution is to check +TTY_LDISC_CHANGING along with TTY_CLOSING in tty_reopen. + +Nicely reproducible with two processes: +while (1) { + fd = open("/dev/ttyS1", O_RDWR); + if (fd < 0) { + warn("open"); + continue; + } + close(fd); +} +-------- +while (1) { + fd = open("/dev/ttyS1", O_RDWR); + ld1 = 0; ld2 = 2; + while (1) { + ioctl(fd, TIOCSETD, &ld1); + ioctl(fd, TIOCSETD, &ld2); + } + close(fd); +} + +Signed-off-by: Jiri Slaby +Reported-by: +Cc: Kyle McMartin +Cc: Alan Cox +--- + drivers/tty/tty_io.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index c05c5af..878f6d6 100644 +--- a/drivers/char/tty_io.c ++++ b/drivers/char/tty_io.c +@@ -1310,7 +1310,8 @@ static int tty_reopen(struct tty_struct *tty) + { + struct tty_driver *driver = tty->driver; + +- if (test_bit(TTY_CLOSING, &tty->flags)) ++ if (test_bit(TTY_CLOSING, &tty->flags) || ++ test_bit(TTY_LDISC_CHANGING, &tty->flags)) + return -EIO; + + if (driver->type == TTY_DRIVER_TYPE_PTY && +-- +1.7.3.1 + + + diff --git a/tty-ldisc-fix-open-flag-handling.patch b/tty-ldisc-fix-open-flag-handling.patch new file mode 100644 index 000000000..72c67a976 --- /dev/null +++ b/tty-ldisc-fix-open-flag-handling.patch @@ -0,0 +1,54 @@ +From linux-kernel-owner@vger.kernel.org Wed Nov 24 18:28:11 2010 +From: Jiri Slaby +Subject: [PATCH 1/2] TTY: ldisc, fix open flag handling +Date: Thu, 25 Nov 2010 00:27:54 +0100 + +When a concrete ldisc open fails in tty_ldisc_open, we forget to clear +TTY_LDISC_OPEN. This causes a false warning on the next ldisc open: +WARNING: at drivers/char/tty_ldisc.c:445 tty_ldisc_open+0x26/0x38() +Hardware name: System Product Name +Modules linked in: ... +Pid: 5251, comm: a.out Tainted: G W 2.6.32-5-686 #1 +Call Trace: + [] ? warn_slowpath_common+0x5e/0x8a + [] ? warn_slowpath_null+0xa/0xc + [] ? tty_ldisc_open+0x26/0x38 + [] ? tty_set_ldisc+0x218/0x304 +... + +So clear the bit when failing... + +Introduced in c65c9bc3efa (tty: rewrite the ldisc locking) back in +2.6.31-rc1. + +Signed-off-by: Jiri Slaby +Cc: Alan Cox +Reported-by: Sergey Lapin +Tested-by: Sergey Lapin +--- + drivers/tty/tty_ldisc.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c +index d8e96b0..4214d58 100644 +--- a/drivers/char/tty_ldisc.c ++++ b/drivers/char/tty_ldisc.c +@@ -454,6 +454,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) + /* BTM here locks versus a hangup event */ + WARN_ON(!tty_locked()); + ret = ld->ops->open(tty); ++ if (ret) ++ clear_bit(TTY_LDISC_OPEN, &tty->flags); + return ret; + } + return 0; +-- +1.7.3.1 + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ + diff --git a/tty-open-hangup-race-fixup.patch b/tty-open-hangup-race-fixup.patch new file mode 100644 index 000000000..bfd29ecf7 --- /dev/null +++ b/tty-open-hangup-race-fixup.patch @@ -0,0 +1,76 @@ +From 9e88e8b9915b5e067507a087437d80e6a133d612 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Sat, 27 Nov 2010 16:06:46 +0100 +Subject: [PATCH 1/1] TTY: open/hangup race fixup + + +Signed-off-by: Jiri Slaby +--- + drivers/tty/tty_io.c | 10 +++++++++- + include/linux/tty.h | 1 + + 2 files changed, 10 insertions(+), 1 deletions(-) + +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 878f6d6..35480dd 100644 +--- a/drivers/char/tty_io.c ++++ b/drivers/char/tty_io.c +@@ -559,6 +559,9 @@ void __tty_hangup(struct tty_struct *tty) + + tty_lock(); + ++ /* some functions below drop BTM, so we need this bit */ ++ set_bit(TTY_HUPPING, &tty->flags); ++ + /* inuse_filps is protected by the single tty lock, + this really needs to change if we want to flush the + workqueue with the lock held */ +@@ -578,6 +581,10 @@ void __tty_hangup(struct tty_struct *tty) + } + spin_unlock(&tty_files_lock); + ++ /* ++ * it drops BTM and thus races with reopen ++ * we protect the race by TTY_HUPPING ++ */ + tty_ldisc_hangup(tty); + + read_lock(&tasklist_lock); +@@ -615,7 +622,6 @@ void __tty_hangup(struct tty_struct *tty) + tty->session = NULL; + tty->pgrp = NULL; + tty->ctrl_status = 0; +- set_bit(TTY_HUPPED, &tty->flags); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); + + /* Account for the p->signal references we killed */ +@@ -641,6 +647,7 @@ void __tty_hangup(struct tty_struct *tty) + * can't yet guarantee all that. + */ + set_bit(TTY_HUPPED, &tty->flags); ++ clear_bit(TTY_HUPPING, &tty->flags); + tty_ldisc_enable(tty); + + tty_unlock(); +@@ -1311,6 +1318,7 @@ static int tty_reopen(struct tty_struct *tty) + struct tty_driver *driver = tty->driver; + + if (test_bit(TTY_CLOSING, &tty->flags) || ++ test_bit(TTY_HUPPING, &tty->flags) || + test_bit(TTY_LDISC_CHANGING, &tty->flags)) + return -EIO; + +diff --git a/include/linux/tty.h b/include/linux/tty.h +index 032d79f..54e4eaa 100644 +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -366,6 +366,7 @@ struct tty_file_private { + #define TTY_HUPPED 18 /* Post driver->hangup() */ + #define TTY_FLUSHING 19 /* Flushing to ldisc in progress */ + #define TTY_FLUSHPENDING 20 /* Queued buffer flush pending */ ++#define TTY_HUPPING 21 /* ->hangup() in progress */ + + #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) + +-- +1.7.3.1 +