--- /dev/null
+From 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 Mon Sep 17 00:00:00 2001
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+Date: Mon, 28 Dec 2009 13:15:20 +0800
+Subject: drm/i915: disable TV hotplug status check
+
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+
+commit 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 upstream.
+
+As we removed TV hotplug, don't check its status ever.
+
+Reviewed-by: Adam Jackson <ajax@redhat.com>
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_tv.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_tv.c
++++ b/drivers/gpu/drm/i915/intel_tv.c
+@@ -1801,8 +1801,6 @@ intel_tv_init(struct drm_device *dev)
+ drm_connector_attach_property(connector,
+ dev->mode_config.tv_bottom_margin_property,
+ tv_priv->margin[TV_MARGIN_BOTTOM]);
+-
+- dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS;
+ out:
+ drm_sysfs_connector_add(connector);
+ }
--- /dev/null
+From 43bcd61fae05fc6062b4f117c5adb1a72c9f8c57 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Tue, 3 Nov 2009 09:03:34 +0000
+Subject: drm/i915: fix get_core_clock_speed for G33 class desktop chips
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 43bcd61fae05fc6062b4f117c5adb1a72c9f8c57 upstream.
+
+Somehow the case for G33 got dropped while porting from ums code.
+This made a 400MHz chip into a 133MHz one which resulted in the
+unnecessary enabling of double wide pipe mode which in turn
+screwed up the overlay code.
+
+Nothing else (than the overlay code) seems to be affected.
+
+This fixes fdo.org bug #24835
+
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_display.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -4322,7 +4322,7 @@ static void intel_init_display(struct dr
+ }
+
+ /* Returns the core display clock speed */
+- if (IS_I945G(dev))
++ if (IS_I945G(dev) || (IS_G33(dev) && ! IS_IGDGM(dev)))
+ dev_priv->display.get_display_clock_speed =
+ i945_get_display_clock_speed;
+ else if (IS_I915G(dev))
--- /dev/null
+From c0d7a0212becebe11ffe6979ee3d6f1c4104568d Mon Sep 17 00:00:00 2001
+From: Jarek Poplawski <jarkao2@gmail.com>
+Date: Wed, 23 Dec 2009 21:54:29 -0800
+Subject: net/via-rhine: Fix scheduling while atomic bugs
+
+From: Jarek Poplawski <jarkao2@gmail.com>
+
+commit c0d7a0212becebe11ffe6979ee3d6f1c4104568d upstream.
+
+There are BUGs "scheduling while atomic" triggered by the timer
+rhine_tx_timeout(). They are caused by calling napi_disable() (with
+msleep()). This patch fixes it by moving most of the timer content to
+the workqueue function (similarly to other drivers, like tg3), with
+spin_lock() changed to BH version.
+
+Additionally, there is spin_lock_irq() moved in rhine_close() to
+exclude napi_disable() etc., also tg3's way.
+
+Reported-by: Andrey Rahmatullin <wrar@altlinux.org>
+Tested-by: Andrey Rahmatullin <wrar@altlinux.org>
+Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/via-rhine.c | 41 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 28 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/via-rhine.c
++++ b/drivers/net/via-rhine.c
+@@ -102,6 +102,7 @@ static const int multicast_filter_limit
+ #include <linux/ethtool.h>
+ #include <linux/crc32.h>
+ #include <linux/bitops.h>
++#include <linux/workqueue.h>
+ #include <asm/processor.h> /* Processor type for cache alignment. */
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -389,6 +390,7 @@ struct rhine_private {
+ struct net_device *dev;
+ struct napi_struct napi;
+ spinlock_t lock;
++ struct work_struct reset_task;
+
+ /* Frequently used values: keep some adjacent for cache effect. */
+ u32 quirks;
+@@ -407,6 +409,7 @@ struct rhine_private {
+ static int mdio_read(struct net_device *dev, int phy_id, int location);
+ static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+ static int rhine_open(struct net_device *dev);
++static void rhine_reset_task(struct work_struct *work);
+ static void rhine_tx_timeout(struct net_device *dev);
+ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
+ struct net_device *dev);
+@@ -775,6 +778,8 @@ static int __devinit rhine_init_one(stru
+ dev->irq = pdev->irq;
+
+ spin_lock_init(&rp->lock);
++ INIT_WORK(&rp->reset_task, rhine_reset_task);
++
+ rp->mii_if.dev = dev;
+ rp->mii_if.mdio_read = mdio_read;
+ rp->mii_if.mdio_write = mdio_write;
+@@ -1179,22 +1184,18 @@ static int rhine_open(struct net_device
+ return 0;
+ }
+
+-static void rhine_tx_timeout(struct net_device *dev)
++static void rhine_reset_task(struct work_struct *work)
+ {
+- struct rhine_private *rp = netdev_priv(dev);
+- void __iomem *ioaddr = rp->base;
+-
+- printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
+- "%4.4x, resetting...\n",
+- dev->name, ioread16(ioaddr + IntrStatus),
+- mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
++ struct rhine_private *rp = container_of(work, struct rhine_private,
++ reset_task);
++ struct net_device *dev = rp->dev;
+
+ /* protect against concurrent rx interrupts */
+ disable_irq(rp->pdev->irq);
+
+ napi_disable(&rp->napi);
+
+- spin_lock(&rp->lock);
++ spin_lock_bh(&rp->lock);
+
+ /* clear all descriptors */
+ free_tbufs(dev);
+@@ -1206,7 +1207,7 @@ static void rhine_tx_timeout(struct net_
+ rhine_chip_reset(dev);
+ init_registers(dev);
+
+- spin_unlock(&rp->lock);
++ spin_unlock_bh(&rp->lock);
+ enable_irq(rp->pdev->irq);
+
+ dev->trans_start = jiffies;
+@@ -1214,6 +1215,19 @@ static void rhine_tx_timeout(struct net_
+ netif_wake_queue(dev);
+ }
+
++static void rhine_tx_timeout(struct net_device *dev)
++{
++ struct rhine_private *rp = netdev_priv(dev);
++ void __iomem *ioaddr = rp->base;
++
++ printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
++ "%4.4x, resetting...\n",
++ dev->name, ioread16(ioaddr + IntrStatus),
++ mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
++
++ schedule_work(&rp->reset_task);
++}
++
+ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+@@ -1830,10 +1844,11 @@ static int rhine_close(struct net_device
+ struct rhine_private *rp = netdev_priv(dev);
+ void __iomem *ioaddr = rp->base;
+
+- spin_lock_irq(&rp->lock);
+-
+- netif_stop_queue(dev);
+ napi_disable(&rp->napi);
++ cancel_work_sync(&rp->reset_task);
++ netif_stop_queue(dev);
++
++ spin_lock_irq(&rp->lock);
+
+ if (debug > 1)
+ printk(KERN_DEBUG "%s: Shutting down ethercard, "
--- /dev/null
+From ceae8cbe94f3127253110e2d01b9334069e93177 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@ppcg5.localdomain>
+Date: Sun, 6 Dec 2009 20:01:26 +0000
+Subject: offb: Add support for framebuffer handoff to offb.
+
+From: Dave Airlie <airlied@ppcg5.localdomain>
+
+commit ceae8cbe94f3127253110e2d01b9334069e93177 upstream.
+
+This allows offb to be used for initial framebuffer,
+and a kms driver to take over later in the boot sequence.
+
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/offb.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/offb.c
++++ b/drivers/video/offb.c
+@@ -282,8 +282,17 @@ static int offb_set_par(struct fb_info *
+ return 0;
+ }
+
++static void offb_destroy(struct fb_info *info)
++{
++ if (info->screen_base)
++ iounmap(info->screen_base);
++ release_mem_region(info->aperture_base, info->aperture_size);
++ framebuffer_release(info);
++}
++
+ static struct fb_ops offb_ops = {
+ .owner = THIS_MODULE,
++ .fb_destroy = offb_destroy,
+ .fb_setcolreg = offb_setcolreg,
+ .fb_set_par = offb_set_par,
+ .fb_blank = offb_blank,
+@@ -482,10 +491,14 @@ static void __init offb_init_fb(const ch
+ var->sync = 0;
+ var->vmode = FB_VMODE_NONINTERLACED;
+
++ /* set offb aperture size for generic probing */
++ info->aperture_base = address;
++ info->aperture_size = fix->smem_len;
++
+ info->fbops = &offb_ops;
+ info->screen_base = ioremap(address, fix->smem_len);
+ info->pseudo_palette = (void *) (info + 1);
+- info->flags = FBINFO_DEFAULT | foreign_endian;
++ info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
+
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
--- /dev/null
+From 77593ae28c4c134eaf28ef34ecac3cd4464ecd6e Mon Sep 17 00:00:00 2001
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Date: Sun, 22 Nov 2009 20:16:47 +0200
+Subject: rndis_wlan: disable stall workaround
+
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+
+commit 77593ae28c4c134eaf28ef34ecac3cd4464ecd6e upstream.
+
+Stall workaround doesn't work with bcm4320a devices like with bcm4320b.
+This workaround actually causes more stalls/device freeze on bcm4320a.
+Therefore disable stall workaround by default.
+
+Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/rndis_wlan.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/rndis_wlan.c
++++ b/drivers/net/wireless/rndis_wlan.c
+@@ -83,11 +83,11 @@ MODULE_PARM_DESC(roamdelta,
+ "set roaming tendency: 0=aggressive, 1=moderate, "
+ "2=conservative (default: moderate)");
+
+-static int modparam_workaround_interval = 500;
++static int modparam_workaround_interval;
+ module_param_named(workaround_interval, modparam_workaround_interval,
+ int, 0444);
+ MODULE_PARM_DESC(workaround_interval,
+- "set stall workaround interval in msecs (default: 500)");
++ "set stall workaround interval in msecs (0=disabled) (default: 0)");
+
+
+ /* various RNDIS OID defs */
+@@ -2550,7 +2550,7 @@ static void rndis_device_poller(struct w
+ /* Workaround transfer stalls on poor quality links.
+ * TODO: find right way to fix these stalls (as stalls do not happen
+ * with ndiswrapper/windows driver). */
+- if (priv->last_qual <= 25) {
++ if (priv->param_workaround_interval > 0 && priv->last_qual <= 25) {
+ /* Decrease stats worker interval to catch stalls.
+ * faster. Faster than 400-500ms causes packet loss,
+ * Slower doesn't catch stalls fast enough.
--- /dev/null
+From c1f8ca1d837148bf061d6ffa2038366e3cf0e4d7 Mon Sep 17 00:00:00 2001
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Date: Sun, 22 Nov 2009 20:16:42 +0200
+Subject: rndis_wlan: fix buffer overflow in rndis_query_oid
+
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+
+commit c1f8ca1d837148bf061d6ffa2038366e3cf0e4d7 upstream.
+
+rndis_query_oid overwrites *len which stores buffer size to return full size
+of received command and then uses *len with memcpy to fill buffer with
+command.
+
+Ofcourse memcpy should be done before replacing buffer size.
+
+Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/rndis_wlan.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/rndis_wlan.c
++++ b/drivers/net/wireless/rndis_wlan.c
+@@ -733,12 +733,13 @@ static int rndis_query_oid(struct usbnet
+ le32_to_cpu(u.get_c->status));
+
+ if (ret == 0) {
++ memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
++
+ ret = le32_to_cpu(u.get_c->len);
+ if (ret > *len)
+ *len = ret;
+- memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
+- ret = rndis_error_status(u.get_c->status);
+
++ ret = rndis_error_status(u.get_c->status);
+ if (ret < 0)
+ devdbg(dev, "rndis_query_oid(%s): device returned "
+ "error, 0x%08x (%d)", oid_to_string(oid),
--- /dev/null
+From 634a555ce3ee5ea1fdcaee8b4ac9ce7b54f301ac Mon Sep 17 00:00:00 2001
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Date: Mon, 16 Nov 2009 12:49:43 +0200
+Subject: rndis_wlan: handle NL80211_AUTHTYPE_AUTOMATIC
+
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+
+commit 634a555ce3ee5ea1fdcaee8b4ac9ce7b54f301ac upstream.
+
+rndis_wlan didn't know about NL80211_AUTHTYPE_AUTOMATIC and simple
+setup with 'iwconfig wlan essid no-encrypt' would fail (ENOSUPP).
+
+v2: use NDIS_80211_AUTH_AUTO_SWITCH instead of _OPEN.
+ This will make device try shared key auth first, then open.
+
+Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/rndis_wlan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/rndis_wlan.c
++++ b/drivers/net/wireless/rndis_wlan.c
+@@ -1072,6 +1072,8 @@ static int set_auth_mode(struct usbnet *
+ auth_mode = NDIS_80211_AUTH_SHARED;
+ else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
+ auth_mode = NDIS_80211_AUTH_OPEN;
++ else if (auth_type == NL80211_AUTHTYPE_AUTOMATIC)
++ auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
+ else
+ return -ENOTSUPP;
+
--- /dev/null
+From 2a7a06a0cdd86d572e91657603180da5992be6d3 Mon Sep 17 00:00:00 2001
+From: Aaro Koskinen <aaro.koskinen@nokia.com>
+Date: Fri, 5 Mar 2010 13:44:24 -0800
+Subject: rtc-core: fix memory leak
+
+From: Aaro Koskinen <aaro.koskinen@nokia.com>
+
+commit 2a7a06a0cdd86d572e91657603180da5992be6d3 upstream.
+
+The idr should be destroyed when the module is unloaded. Found with
+kmemleak.
+
+Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
+Cc: Alessandro Zummo <a.zummo@towertech.it>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/rtc/class.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/rtc/class.c
++++ b/drivers/rtc/class.c
+@@ -226,6 +226,7 @@ static void __exit rtc_exit(void)
+ {
+ rtc_dev_exit();
+ class_destroy(rtc_class);
++ idr_destroy(&rtc_idr);
+ }
+
+ subsys_initcall(rtc_init);
--- /dev/null
+From a67093d46e3caed1a42d694a7de452b61db30562 Mon Sep 17 00:00:00 2001
+From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
+Date: Thu, 4 Feb 2010 14:17:59 -0800
+Subject: SCSI: qla2xxx: Obtain proper host structure during response-queue processing.
+
+From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
+
+commit a67093d46e3caed1a42d694a7de452b61db30562 upstream.
+
+Original code incorrectly assumed only status-type-0
+IOCBs would be queued to the response-queue, and thus all
+entries would safely reference a VHA from the IOCB
+'handle.'
+
+Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/scsi/qla2xxx/qla_gbl.h | 1 -
+ drivers/scsi/qla2xxx/qla_isr.c | 29 +----------------------------
+ drivers/scsi/qla2xxx/qla_mid.c | 6 +++++-
+ 3 files changed, 6 insertions(+), 30 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -453,6 +453,5 @@ extern void qla24xx_wrt_req_reg(struct q
+ extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
+ extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
+ extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
+-extern struct scsi_qla_host * qla25xx_get_host(struct rsp_que *);
+
+ #endif /* _QLA_GBL_H */
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -2018,7 +2018,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id
+
+ spin_lock_irq(&ha->hardware_lock);
+
+- vha = qla25xx_get_host(rsp);
++ vha = pci_get_drvdata(ha->pdev);
+ qla24xx_process_response_queue(vha, rsp);
+ if (!ha->mqenable) {
+ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
+@@ -2357,30 +2357,3 @@ int qla25xx_request_irq(struct rsp_que *
+ msix->rsp = rsp;
+ return ret;
+ }
+-
+-struct scsi_qla_host *
+-qla25xx_get_host(struct rsp_que *rsp)
+-{
+- srb_t *sp;
+- struct qla_hw_data *ha = rsp->hw;
+- struct scsi_qla_host *vha = NULL;
+- struct sts_entry_24xx *pkt;
+- struct req_que *req;
+- uint16_t que;
+- uint32_t handle;
+-
+- pkt = (struct sts_entry_24xx *) rsp->ring_ptr;
+- que = MSW(pkt->handle);
+- handle = (uint32_t) LSW(pkt->handle);
+- req = ha->req_q_map[que];
+- if (handle < MAX_OUTSTANDING_COMMANDS) {
+- sp = req->outstanding_cmds[handle];
+- if (sp)
+- return sp->fcport->vha;
+- else
+- goto base_que;
+- }
+-base_que:
+- vha = pci_get_drvdata(ha->pdev);
+- return vha;
+-}
+--- a/drivers/scsi/qla2xxx/qla_mid.c
++++ b/drivers/scsi/qla2xxx/qla_mid.c
+@@ -638,11 +638,15 @@ failed:
+
+ static void qla_do_work(struct work_struct *work)
+ {
++ unsigned long flags;
+ struct rsp_que *rsp = container_of(work, struct rsp_que, q_work);
+ struct scsi_qla_host *vha;
++ struct qla_hw_data *ha = rsp->hw;
+
+- vha = qla25xx_get_host(rsp);
++ spin_lock_irqsave(&rsp->hw->hardware_lock, flags);
++ vha = pci_get_drvdata(ha->pdev);
+ qla24xx_process_response_queue(vha, rsp);
++ spin_unlock_irqrestore(&rsp->hw->hardware_lock, flags);
+ }
+
+ /* create response queue */
drm-radeon-kms-forbid-creation-of-framebuffer-with-no-valid-gem-object.patch
drm-radeon-kms-r600-r700-don-t-test-ib-if-ib-initialization-fails.patch
drm-radeon-r6xx-r7xx-possible-security-issue-system-ram-access.patch
+scsi-qla2xxx-obtain-proper-host-structure-during-response-queue-processing.patch
+rtc-core-fix-memory-leak.patch
+drm-i915-fix-get_core_clock_speed-for-g33-class-desktop-chips.patch
+drm-i915-disable-tv-hotplug-status-check.patch
+offb-add-support-for-framebuffer-handoff-to-offb.patch
+tpm_tis-tpm_sts_data_expect-workaround.patch
+rndis_wlan-handle-nl80211_authtype_automatic.patch
+rndis_wlan-fix-buffer-overflow-in-rndis_query_oid.patch
+rndis_wlan-disable-stall-workaround.patch
+net-via-rhine-fix-scheduling-while-atomic-bugs.patch
--- /dev/null
+From 3507d612366a4e81226295f646410130a1f62a5c Mon Sep 17 00:00:00 2001
+From: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
+Date: Thu, 10 Sep 2009 17:09:35 -0300
+Subject: tpm_tis: TPM_STS_DATA_EXPECT workaround
+
+From: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
+
+commit 3507d612366a4e81226295f646410130a1f62a5c upstream.
+
+Some newer Lenovo models are shipped with a TPM that doesn't seem to set the TPM_STS_DATA_EXPECT status bit
+when sending it a burst of data, so the code understands it as a failure and doesn't proceed sending the chip
+the intended data. In this patch we bypass this bit check in case the itpm module parameter was set.
+
+This patch is based on Andy Isaacson's one:
+
+http://marc.info/?l=linux-kernel&m=124650185023495&w=2
+
+It was heavily discussed how should we deal with identifying the chip in kernel space, but the required
+patch to do so was NACK'd:
+
+http://marc.info/?l=linux-kernel&m=124650186423711&w=2
+
+This way we let the user choose using this workaround or not based on his
+observations on this code behavior when trying to use the TPM.
+
+Fixed a checkpatch issue present on the previous patch, thanks to Daniel Walker.
+
+Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
+Acked-by: Eric Paris <eparis@redhat.com>
+Tested-by: Seiji Munetoh <seiji.munetoh@gmail.com>
+Signed-off-by: James Morris <jmorris@namei.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/tpm/tpm_tis.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -257,6 +257,10 @@ out:
+ return size;
+ }
+
++static int itpm;
++module_param(itpm, bool, 0444);
++MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
++
+ /*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+@@ -293,7 +297,7 @@ static int tpm_tis_send(struct tpm_chip
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+- if ((status & TPM_STS_DATA_EXPECT) == 0) {
++ if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+@@ -467,6 +471,10 @@ static int tpm_tis_init(struct device *d
+ "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
+
++ if (itpm)
++ dev_info(dev, "Intel iTPM workaround enabled\n");
++
++
+ /* Figure out the capabilities */
+ intfcaps =
+ ioread32(chip->vendor.iobase +