--- /dev/null
+From ben@decadent.org.uk Wed Apr 21 12:11:57 2010
+From: Alexey Starikovskiy <astarikovskiy@suse.de>
+Date: Sat, 10 Apr 2010 02:18:35 +0100
+Subject: ACPI: EC: Allow multibyte access to EC
+To: stable@kernel.org
+Cc: Len Brown <len.brown@intel.com>, 563313@bugs.debian.org, Alexey Starikovskiy <astarikovskiy@suse.de>
+Message-ID: <1270862315.2176.69.camel@localhost>
+
+
+From: Alexey Starikovskiy <astarikovskiy@suse.de>
+
+commit dadf28a10c3eb29421837a2e413ab869ebd upstream
+
+http://bugzilla.kernel.org/show_bug.cgi?id=14667
+
+[bwh: Backport to 2.6.32; same applies to 2.6.33]
+
+Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/acpi/acpica/exprep.c | 12 ++++++++++++
+ drivers/acpi/ec.c | 35 +++++++++--------------------------
+ 2 files changed, 21 insertions(+), 26 deletions(-)
+
+--- a/drivers/acpi/acpica/exprep.c
++++ b/drivers/acpi/acpica/exprep.c
+@@ -468,6 +468,18 @@ acpi_status acpi_ex_prep_field_value(str
+
+ acpi_ut_add_reference(obj_desc->field.region_obj);
+
++ /* allow full data read from EC address space */
++ if (obj_desc->field.region_obj->region.space_id ==
++ ACPI_ADR_SPACE_EC) {
++ if (obj_desc->common_field.bit_length > 8)
++ obj_desc->common_field.access_bit_width =
++ ACPI_ROUND_UP(obj_desc->common_field.
++ bit_length, 8);
++ obj_desc->common_field.access_byte_width =
++ ACPI_DIV_8(obj_desc->common_field.
++ access_bit_width);
++ }
++
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
+ obj_desc->field.start_field_bit_offset,
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -589,12 +589,12 @@ static u32 acpi_ec_gpe_handler(void *dat
+
+ static acpi_status
+ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+- u32 bits, acpi_integer *value,
++ u32 bits, acpi_integer *value64,
+ void *handler_context, void *region_context)
+ {
+ struct acpi_ec *ec = handler_context;
+- int result = 0, i;
+- u8 temp = 0;
++ int result = 0, i, bytes = bits / 8;
++ u8 *value = (u8 *)value64;
+
+ if ((address > 0xFF) || !value || !handler_context)
+ return AE_BAD_PARAMETER;
+@@ -602,32 +602,15 @@ acpi_ec_space_handler(u32 function, acpi
+ if (function != ACPI_READ && function != ACPI_WRITE)
+ return AE_BAD_PARAMETER;
+
+- if (bits != 8 && acpi_strict)
+- return AE_BAD_PARAMETER;
+-
+- if (EC_FLAGS_MSI)
++ if (EC_FLAGS_MSI || bits > 8)
+ acpi_ec_burst_enable(ec);
+
+- if (function == ACPI_READ) {
+- result = acpi_ec_read(ec, address, &temp);
+- *value = temp;
+- } else {
+- temp = 0xff & (*value);
+- result = acpi_ec_write(ec, address, temp);
+- }
+-
+- for (i = 8; unlikely(bits - i > 0); i += 8) {
+- ++address;
+- if (function == ACPI_READ) {
+- result = acpi_ec_read(ec, address, &temp);
+- (*value) |= ((acpi_integer)temp) << i;
+- } else {
+- temp = 0xff & ((*value) >> i);
+- result = acpi_ec_write(ec, address, temp);
+- }
+- }
++ for (i = 0; i < bytes; ++i, ++address, ++value)
++ result = (function == ACPI_READ) ?
++ acpi_ec_read(ec, address, value) :
++ acpi_ec_write(ec, address, *value);
+
+- if (EC_FLAGS_MSI)
++ if (EC_FLAGS_MSI || bits > 8)
+ acpi_ec_burst_disable(ec);
+
+ switch (result) {
--- /dev/null
+From dac876193cd79ced36d0462749ea47c05844fb49 Mon Sep 17 00:00:00 2001
+From: Terry Loftin <terry.loftin@hp.com>
+Date: Fri, 9 Apr 2010 10:29:49 +0000
+Subject: e1000e: stop cleaning when we reach tx_ring->next_to_use
+
+From: Terry Loftin <terry.loftin@hp.com>
+
+commit dac876193cd79ced36d0462749ea47c05844fb49 upstream.
+
+Tx ring buffers after tx_ring->next_to_use are volatile and could
+change, possibly causing a crash. Stop cleaning when we hit
+tx_ring->next_to_use.
+
+Signed-off-by: Terry Loftin <terry.loftin@hp.com>
+Acked-by: Bruce Allan <bruce.w.allan@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: Matthew Burgess <matthew@linuxfromscratch.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000e/netdev.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -660,6 +660,8 @@ static bool e1000_clean_tx_irq(struct e1
+ i = 0;
+ }
+
++ if (i == tx_ring->next_to_use)
++ break;
+ eop = tx_ring->buffer_info[i].next_to_watch;
+ eop_desc = E1000_TX_DESC(*tx_ring, eop);
+ }
--- /dev/null
+From 3a60a1686f0d51c99bd0df8ac93050fb6dfce647 Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Date: Mon, 22 Mar 2010 00:41:35 -0500
+Subject: eCryptfs: Decrypt symlink target for stat size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+
+commit 3a60a1686f0d51c99bd0df8ac93050fb6dfce647 upstream.
+
+Create a getattr handler for eCryptfs symlinks that is capable of
+reading the lower target and decrypting its path. Prior to this patch,
+a stat's st_size field would represent the strlen of the encrypted path,
+while readlink() would return the strlen of the decrypted path. This
+could lead to confusion in some userspace applications, since the two
+values should be equal.
+
+https://bugs.launchpad.net/bugs/524919
+
+Reported-by: Loïc Minier <loic.minier@canonical.com>
+Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/inode.c | 100 +++++++++++++++++++++++++++-------------------------
+ 1 file changed, 52 insertions(+), 48 deletions(-)
+
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -647,38 +647,17 @@ out_lock:
+ return rc;
+ }
+
+-static int
+-ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
++static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
++ size_t *bufsiz)
+ {
++ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ char *lower_buf;
+- size_t lower_bufsiz;
+- struct dentry *lower_dentry;
+- struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+- char *plaintext_name;
+- size_t plaintext_name_size;
++ size_t lower_bufsiz = PATH_MAX;
+ mm_segment_t old_fs;
+ int rc;
+
+- lower_dentry = ecryptfs_dentry_to_lower(dentry);
+- if (!lower_dentry->d_inode->i_op->readlink) {
+- rc = -EINVAL;
+- goto out;
+- }
+- mount_crypt_stat = &ecryptfs_superblock_to_private(
+- dentry->d_sb)->mount_crypt_stat;
+- /*
+- * If the lower filename is encrypted, it will result in a significantly
+- * longer name. If needed, truncate the name after decode and decrypt.
+- */
+- if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
+- lower_bufsiz = PATH_MAX;
+- else
+- lower_bufsiz = bufsiz;
+- /* Released in this function */
+ lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
+- if (lower_buf == NULL) {
+- printk(KERN_ERR "%s: Out of memory whilst attempting to "
+- "kmalloc [%zd] bytes\n", __func__, lower_bufsiz);
++ if (!lower_buf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+@@ -688,29 +667,31 @@ ecryptfs_readlink(struct dentry *dentry,
+ (char __user *)lower_buf,
+ lower_bufsiz);
+ set_fs(old_fs);
+- if (rc >= 0) {
+- rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name,
+- &plaintext_name_size,
+- dentry, lower_buf,
+- rc);
+- if (rc) {
+- printk(KERN_ERR "%s: Error attempting to decode and "
+- "decrypt filename; rc = [%d]\n", __func__,
+- rc);
+- goto out_free_lower_buf;
+- }
+- /* Check for bufsiz <= 0 done in sys_readlinkat() */
+- rc = copy_to_user(buf, plaintext_name,
+- min((size_t) bufsiz, plaintext_name_size));
+- if (rc)
+- rc = -EFAULT;
+- else
+- rc = plaintext_name_size;
+- kfree(plaintext_name);
+- fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
+- }
+-out_free_lower_buf:
++ if (rc < 0)
++ goto out;
++ lower_bufsiz = rc;
++ rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
++ lower_buf, lower_bufsiz);
++out:
+ kfree(lower_buf);
++ return rc;
++}
++
++static int
++ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
++{
++ char *kbuf;
++ size_t kbufsiz, copied;
++ int rc;
++
++ rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz);
++ if (rc)
++ goto out;
++ copied = min_t(size_t, bufsiz, kbufsiz);
++ rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied;
++ kfree(kbuf);
++ fsstack_copy_attr_atime(dentry->d_inode,
++ ecryptfs_dentry_to_lower(dentry)->d_inode);
+ out:
+ return rc;
+ }
+@@ -1015,6 +996,28 @@ out:
+ return rc;
+ }
+
++int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
++ struct kstat *stat)
++{
++ struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
++ int rc = 0;
++
++ mount_crypt_stat = &ecryptfs_superblock_to_private(
++ dentry->d_sb)->mount_crypt_stat;
++ generic_fillattr(dentry->d_inode, stat);
++ if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
++ char *target;
++ size_t targetsiz;
++
++ rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz);
++ if (!rc) {
++ kfree(target);
++ stat->size = targetsiz;
++ }
++ }
++ return rc;
++}
++
+ int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+ {
+@@ -1132,6 +1135,7 @@ const struct inode_operations ecryptfs_s
+ .put_link = ecryptfs_put_link,
+ .permission = ecryptfs_permission,
+ .setattr = ecryptfs_setattr,
++ .getattr = ecryptfs_getattr_link,
+ .setxattr = ecryptfs_setxattr,
+ .getxattr = ecryptfs_getxattr,
+ .listxattr = ecryptfs_listxattr,
--- /dev/null
+From cfce08c6bdfb20ade979284e55001ca1f100ed51 Mon Sep 17 00:00:00 2001
+From: Christian Pulvermacher <pulvermacher@gmx.de>
+Date: Tue, 23 Mar 2010 11:51:38 -0500
+Subject: ecryptfs: fix error code for missing xattrs in lower fs
+
+From: Christian Pulvermacher <pulvermacher@gmx.de>
+
+commit cfce08c6bdfb20ade979284e55001ca1f100ed51 upstream.
+
+If the lower file system driver has extended attributes disabled,
+ecryptfs' own access functions return -ENOSYS instead of -EOPNOTSUPP.
+This breaks execution of programs in the ecryptfs mount, since the
+kernel expects the latter error when checking for security
+capabilities in xattrs.
+
+Signed-off-by: Christian Pulvermacher <pulvermacher@gmx.de>
+Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/inode.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -1042,7 +1042,7 @@ ecryptfs_setxattr(struct dentry *dentry,
+
+ lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ if (!lower_dentry->d_inode->i_op->setxattr) {
+- rc = -ENOSYS;
++ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
+@@ -1060,7 +1060,7 @@ ecryptfs_getxattr_lower(struct dentry *l
+ int rc = 0;
+
+ if (!lower_dentry->d_inode->i_op->getxattr) {
+- rc = -ENOSYS;
++ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
+@@ -1087,7 +1087,7 @@ ecryptfs_listxattr(struct dentry *dentry
+
+ lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ if (!lower_dentry->d_inode->i_op->listxattr) {
+- rc = -ENOSYS;
++ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
+@@ -1104,7 +1104,7 @@ static int ecryptfs_removexattr(struct d
+
+ lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ if (!lower_dentry->d_inode->i_op->removexattr) {
+- rc = -ENOSYS;
++ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
--- /dev/null
+From 133b8f9d632cc23715c6d72d1c5ac449e054a12a Mon Sep 17 00:00:00 2001
+From: Jeff Mahoney <jeffm@jeffreymahoney.com>
+Date: Fri, 19 Mar 2010 15:35:46 -0400
+Subject: ecryptfs: fix use with tmpfs by removing d_drop from ecryptfs_destroy_inode
+
+From: Jeff Mahoney <jeffm@jeffreymahoney.com>
+
+commit 133b8f9d632cc23715c6d72d1c5ac449e054a12a upstream.
+
+Since tmpfs has no persistent storage, it pins all its dentries in memory
+so they have d_count=1 when other file systems would have d_count=0.
+->lookup is only used to create new dentries. If the caller doesn't
+instantiate it, it's freed immediately at dput(). ->readdir reads
+directly from the dcache and depends on the dentries being hashed.
+
+When an ecryptfs mount is mounted, it associates the lower file and dentry
+with the ecryptfs files as they're accessed. When it's umounted and
+destroys all the in-memory ecryptfs inodes, it fput's the lower_files and
+d_drop's the lower_dentries. Commit 4981e081 added this and a d_delete in
+2008 and several months later commit caeeeecf removed the d_delete. I
+believe the d_drop() needs to be removed as well.
+
+The d_drop effectively hides any file that has been accessed via ecryptfs
+from the underlying tmpfs since it depends on it being hashed for it to
+be accessible. I've removed the d_drop on my development node and see no
+ill effects with basic testing on both tmpfs and persistent storage.
+
+As a side effect, after ecryptfs d_drops the dentries on tmpfs, tmpfs
+BUGs on umount. This is due to the dentries being unhashed.
+tmpfs->kill_sb is kill_litter_super which calls d_genocide to drop
+the reference pinning the dentry. It skips unhashed and negative dentries,
+but shrink_dcache_for_umount_subtree doesn't. Since those dentries
+still have an elevated d_count, we get a BUG().
+
+This patch removes the d_drop call and fixes both issues.
+
+This issue was reported at:
+https://bugzilla.novell.com/show_bug.cgi?id=567887
+
+Reported-by: Árpád Bíró <biroa@demasz.hu>
+Signed-off-by: Jeff Mahoney <jeffm@suse.com>
+Cc: Dustin Kirkland <kirkland@canonical.com>
+Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/super.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/fs/ecryptfs/super.c
++++ b/fs/ecryptfs/super.c
+@@ -85,7 +85,6 @@ static void ecryptfs_destroy_inode(struc
+ if (lower_dentry->d_inode) {
+ fput(inode_info->lower_file);
+ inode_info->lower_file = NULL;
+- d_drop(lower_dentry);
+ }
+ }
+ ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
--- /dev/null
+From dff010ac8e57e43669518a14c0e945dfeb80c2a7 Mon Sep 17 00:00:00 2001
+From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+Date: Tue, 2 Feb 2010 16:58:34 -0800
+Subject: iwlwifi: clear all tx queues when firmware ready
+
+From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+
+commit dff010ac8e57e43669518a14c0e945dfeb80c2a7 upstream.
+
+Reset and clear all the tx queues when finished downloading runtime
+uCode and ready to go into operation mode.
+
+Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/iwlwifi/iwl-4965.c | 2 ++
+ drivers/net/wireless/iwlwifi/iwl-5000.c | 2 ++
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
++++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
+@@ -581,6 +581,8 @@ static int iwl4965_alive_notify(struct i
+
+ iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+
++ /* reset to 0 to enable all the queue first */
++ priv->txq_ctx_active_msk = 0;
+ /* Map each Tx/cmd queue to its corresponding fifo */
+ for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
+ int ac = default_queue_to_tx_fifo[i];
+--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
+@@ -657,6 +657,8 @@ int iwl5000_alive_notify(struct iwl_priv
+
+ iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+
++ /* reset to 0 to enable all the queue first */
++ priv->txq_ctx_active_msk = 0;
+ /* map qos queues to fifos one-to-one */
+ for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
+ int ac = iwl5000_default_queue_to_tx_fifo[i];
--- /dev/null
+From bbcbb9ef9735c67da303d30bd6beb9e699f0f508 Mon Sep 17 00:00:00 2001
+From: Reinette Chatre <reinette.chatre@intel.com>
+Date: Tue, 2 Feb 2010 10:57:12 -0800
+Subject: iwlwifi: fix scan race
+
+From: Reinette Chatre <reinette.chatre@intel.com>
+
+commit bbcbb9ef9735c67da303d30bd6beb9e699f0f508 upstream.
+
+There is a problem if an "internal short scan" is in progress when a
+mac80211 requested scan arrives. If this new scan request arrives within
+the "next_scan_jiffies" period then driver will immediately return success
+and complete the scan. The problem here is that the scan has not been
+fully initialized at this time (is_internal_short_scan is still set to true
+because of the currently running scan), which results in the scan
+completion never to be sent to mac80211. At this time also, evan though the
+internal short scan is still running the state (is_internal_short_scan)
+will be set to false, so when the internal scan does complete then mac80211
+will receive a scan completion.
+
+Fix this by checking right away if a scan is in progress when a scan
+request arrives from mac80211.
+
+Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/iwlwifi/iwl-scan.c | 27 ++++++++++++---------------
+ 1 file changed, 12 insertions(+), 15 deletions(-)
+
+--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
++++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
+@@ -404,21 +404,6 @@ EXPORT_SYMBOL(iwl_init_scan_params);
+
+ static int iwl_scan_initiate(struct iwl_priv *priv)
+ {
+- if (!iwl_is_ready_rf(priv)) {
+- IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
+- return -EIO;
+- }
+-
+- if (test_bit(STATUS_SCANNING, &priv->status)) {
+- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+- return -EAGAIN;
+- }
+-
+- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+- IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
+- return -EAGAIN;
+- }
+-
+ IWL_DEBUG_INFO(priv, "Starting scan...\n");
+ set_bit(STATUS_SCANNING, &priv->status);
+ priv->scan_start = jiffies;
+@@ -449,6 +434,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw
+ goto out_unlock;
+ }
+
++ if (test_bit(STATUS_SCANNING, &priv->status)) {
++ IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
++ ret = -EAGAIN;
++ goto out_unlock;
++ }
++
++ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++ IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
++ ret = -EAGAIN;
++ goto out_unlock;
++ }
++
+ /* We don't schedule scan within next_scan_jiffies period.
+ * Avoid scanning during possible EAPOL exchange, return
+ * success immediately.
--- /dev/null
+From youquan.song@linux.intel.com Wed Apr 21 11:57:31 2010
+From: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Date: Fri, 16 Apr 2010 05:14:41 -0400
+Subject: perf_events, x86: Implement Intel Westmere/Nehalem-EX support
+To: Vince Weaver <vweaver1@eecs.utk.edu>, gregkh@novell.com
+Cc: youquan.song@intel.com, a.p.zijlstra@chello.nl, gregkh@novell.com, "Youquan, Song" <youquan.song@linux.intel.com>, trenn@novell.com, stable@kernel.org
+Message-ID: <20100416091441.GA14199@youquan-linux.bj.intel.com>
+Content-Disposition: inline
+
+From: Peter Zijlstra <a.p.zijlstra@chello.nl>
+
+original patch commit ids: 452a339a976e7f782c786eb3f73080401e2fa3a6 and
+134fbadf028a5977a1b06b0253d3ee33e6f0c642
+
+perf_events, x86: Implement Intel Westmere support
+
+The new Intel documentation includes Westmere arch specific
+event maps that are significantly different from the Nehalem
+ones. Add support for this generation.
+
+Found the CPUID model numbers on wikipedia.
+
+Also ammend some Nehalem constraints, spotted those when looking
+for the differences between Nehalem and Westmere.
+
+Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Cc: Arjan van de Ven <arjan@linux.intel.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Stephane Eranian <eranian@google.com>
+LKML-Reference: <20100127221122.151865645@chello.nl>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+perf, x86: Enable Nehalem-EX support
+
+According to Intel Software Devel Manual Volume 3B, the
+Nehalem-EX PMU is just like regular Nehalem (except for the
+uncore support, which is completely different).
+
+Signed-off-by: Vince Weaver <vweaver1@eecs.utk.edu>
+Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Arjan van de Ven <arjan@linux.intel.com>
+Cc: Lin Ming <ming.m.lin@intel.com>
+LKML-Reference: <alpine.DEB.2.00.1004060956580.1417@cl320.eecs.utk.edu>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Cc: Youquan Song <youquan.song@linux.intel.com>
+---
+
+
+---
+ arch/x86/kernel/cpu/perf_event.c | 104 ++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 103 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/cpu/perf_event.c
++++ b/arch/x86/kernel/cpu/perf_event.c
+@@ -245,6 +245,97 @@ static u64 __read_mostly hw_cache_event_
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX];
+
++static const u64 westmere_hw_cache_event_ids
++ [PERF_COUNT_HW_CACHE_MAX]
++ [PERF_COUNT_HW_CACHE_OP_MAX]
++ [PERF_COUNT_HW_CACHE_RESULT_MAX] =
++{
++ [ C(L1D) ] = {
++ [ C(OP_READ) ] = {
++ [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */
++ [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPL */
++ },
++ [ C(OP_WRITE) ] = {
++ [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */
++ [ C(RESULT_MISS) ] = 0x0251, /* L1D.M_REPL */
++ },
++ [ C(OP_PREFETCH) ] = {
++ [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */
++ [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */
++ },
++ },
++ [ C(L1I ) ] = {
++ [ C(OP_READ) ] = {
++ [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */
++ [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */
++ },
++ [ C(OP_WRITE) ] = {
++ [ C(RESULT_ACCESS) ] = -1,
++ [ C(RESULT_MISS) ] = -1,
++ },
++ [ C(OP_PREFETCH) ] = {
++ [ C(RESULT_ACCESS) ] = 0x0,
++ [ C(RESULT_MISS) ] = 0x0,
++ },
++ },
++ [ C(LL ) ] = {
++ [ C(OP_READ) ] = {
++ [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */
++ [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */
++ },
++ [ C(OP_WRITE) ] = {
++ [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */
++ [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */
++ },
++ [ C(OP_PREFETCH) ] = {
++ [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */
++ [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */
++ },
++ },
++ [ C(DTLB) ] = {
++ [ C(OP_READ) ] = {
++ [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */
++ [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */
++ },
++ [ C(OP_WRITE) ] = {
++ [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */
++ [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */
++ },
++ [ C(OP_PREFETCH) ] = {
++ [ C(RESULT_ACCESS) ] = 0x0,
++ [ C(RESULT_MISS) ] = 0x0,
++ },
++ },
++ [ C(ITLB) ] = {
++ [ C(OP_READ) ] = {
++ [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */
++ [ C(RESULT_MISS) ] = 0x0185, /* ITLB_MISSES.ANY */
++ },
++ [ C(OP_WRITE) ] = {
++ [ C(RESULT_ACCESS) ] = -1,
++ [ C(RESULT_MISS) ] = -1,
++ },
++ [ C(OP_PREFETCH) ] = {
++ [ C(RESULT_ACCESS) ] = -1,
++ [ C(RESULT_MISS) ] = -1,
++ },
++ },
++ [ C(BPU ) ] = {
++ [ C(OP_READ) ] = {
++ [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
++ [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */
++ },
++ [ C(OP_WRITE) ] = {
++ [ C(RESULT_ACCESS) ] = -1,
++ [ C(RESULT_MISS) ] = -1,
++ },
++ [ C(OP_PREFETCH) ] = {
++ [ C(RESULT_ACCESS) ] = -1,
++ [ C(RESULT_MISS) ] = -1,
++ },
++ },
++};
++
+ static __initconst u64 nehalem_hw_cache_event_ids
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+@@ -2118,6 +2209,7 @@ static __init int intel_pmu_init(void)
+ * Install the hw-cache-events table:
+ */
+ switch (boot_cpu_data.x86_model) {
++
+ case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
+ case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
+ case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
+@@ -2129,7 +2221,9 @@ static __init int intel_pmu_init(void)
+ event_constraints = intel_core_event_constraints;
+ break;
+ default:
+- case 26:
++ case 26: /* 45 nm nehalem, "Bloomfield" */
++ case 30: /* 45 nm nehalem, "Lynnfield" */
++ case 46: /* 45 nm nehalem-ex, "Beckton" */
+ memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
+ sizeof(hw_cache_event_ids));
+
+@@ -2142,6 +2236,14 @@ static __init int intel_pmu_init(void)
+
+ pr_cont("Atom events, ");
+ break;
++
++ case 37: /* 32 nm nehalem, "Clarkdale" */
++ case 44: /* 32 nm nehalem, "Gulftown" */
++ memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
++ sizeof(hw_cache_event_ids));
++
++ pr_cont("Westmere events, ");
++ break;
+ }
+ return 0;
+ }
b43-allow-pio-mode-to-be-selected-at-module-load.patch
b43-fall-back-gracefully-to-pio-mode-after-fatal-dma-errors.patch
alsa-hda-add-position_fix-quirk-for-biostar-mobo.patch
+ecryptfs-fix-use-with-tmpfs-by-removing-d_drop-from-ecryptfs_destroy_inode.patch
+ecryptfs-decrypt-symlink-target-for-stat-size.patch
+ecryptfs-fix-error-code-for-missing-xattrs-in-lower-fs.patch
+usb-cdc-acm-update-to-new-autopm-api.patch
+usb-cdc-acm-fix-stupid-null-pointer-in-resume.patch
+iwlwifi-clear-all-tx-queues-when-firmware-ready.patch
+iwlwifi-fix-scan-race.patch
+e1000e-stop-cleaning-when-we-reach-tx_ring-next_to_use.patch
+perf_events-x86-implement-intel-westmere-nehalem-ex-support.patch
+xfs-non-blocking-inode-locking-in-io-completion.patch
+xfs-fix-locking-for-inode-cache-radix-tree-tag-updates.patch
+xfs-check-for-more-work-before-sleeping-in-xfssyncd.patch
+acpi-ec-allow-multibyte-access-to-ec.patch
--- /dev/null
+From f0730924e9e32bb8935c60040a26d94179355088 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oliver@neukum.org>
+Date: Wed, 3 Mar 2010 00:37:56 +0100
+Subject: USB: cdc-acm: Fix stupid NULL pointer in resume()
+
+From: Oliver Neukum <oliver@neukum.org>
+
+commit f0730924e9e32bb8935c60040a26d94179355088 upstream.
+
+Stupid logic bug passing a just nulled pointer
+
+Signed-off-by: Oliver Neukum <neukum@b1-systems.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interfa
+ wb = acm->delayed_wb;
+ acm->delayed_wb = NULL;
+ spin_unlock_irq(&acm->write_lock);
+- acm_start_wb(acm, acm->delayed_wb);
++ acm_start_wb(acm, wb);
+ } else {
+ spin_unlock_irq(&acm->write_lock);
+ }
--- /dev/null
+From 97d35f95552c9a0ee4777a7f04431a9fd1260478 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oliver@neukum.org>
+Date: Wed, 16 Dec 2009 17:05:57 +0100
+Subject: USB: cdc-acm: Update to new autopm API
+
+From: Oliver Neukum <oliver@neukum.org>
+
+commit 97d35f95552c9a0ee4777a7f04431a9fd1260478 upstream.
+
+Update cdc-acm to the async methods eliminating the workqueue
+
+[This fixes a reported lockup for the cdc-acm driver - gregkh]
+
+Signed-off-by: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 43 ++++++++++++++++++++++---------------------
+ drivers/usb/class/cdc-acm.h | 1 -
+ 2 files changed, 22 insertions(+), 22 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -170,6 +170,7 @@ static void acm_write_done(struct acm *a
+ {
+ wb->use = 0;
+ acm->transmitting--;
++ usb_autopm_put_interface_async(acm->control);
+ }
+
+ /*
+@@ -211,9 +212,12 @@ static int acm_write_start(struct acm *a
+ }
+
+ dbg("%s susp_count: %d", __func__, acm->susp_count);
++ usb_autopm_get_interface_async(acm->control);
+ if (acm->susp_count) {
+- acm->delayed_wb = wb;
+- schedule_work(&acm->waker);
++ if (!acm->delayed_wb)
++ acm->delayed_wb = wb;
++ else
++ usb_autopm_put_interface_async(acm->control);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ return 0; /* A white lie */
+ }
+@@ -534,23 +538,6 @@ static void acm_softint(struct work_stru
+ tty_kref_put(tty);
+ }
+
+-static void acm_waker(struct work_struct *waker)
+-{
+- struct acm *acm = container_of(waker, struct acm, waker);
+- int rv;
+-
+- rv = usb_autopm_get_interface(acm->control);
+- if (rv < 0) {
+- dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
+- return;
+- }
+- if (acm->delayed_wb) {
+- acm_start_wb(acm, acm->delayed_wb);
+- acm->delayed_wb = NULL;
+- }
+- usb_autopm_put_interface(acm->control);
+-}
+-
+ /*
+ * TTY handlers
+ */
+@@ -1178,7 +1165,6 @@ made_compressed_probe:
+ acm->urb_task.func = acm_rx_tasklet;
+ acm->urb_task.data = (unsigned long) acm;
+ INIT_WORK(&acm->work, acm_softint);
+- INIT_WORK(&acm->waker, acm_waker);
+ init_waitqueue_head(&acm->drain_wait);
+ spin_lock_init(&acm->throttle_lock);
+ spin_lock_init(&acm->write_lock);
+@@ -1343,7 +1329,6 @@ static void stop_data_traffic(struct acm
+ tasklet_enable(&acm->urb_task);
+
+ cancel_work_sync(&acm->work);
+- cancel_work_sync(&acm->waker);
+ }
+
+ static void acm_disconnect(struct usb_interface *intf)
+@@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interf
+ static int acm_resume(struct usb_interface *intf)
+ {
+ struct acm *acm = usb_get_intfdata(intf);
++ struct acm_wb *wb;
+ int rv = 0;
+ int cnt;
+
+@@ -1449,6 +1435,21 @@ static int acm_resume(struct usb_interfa
+ mutex_lock(&acm->mutex);
+ if (acm->port.count) {
+ rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
++
++ spin_lock_irq(&acm->write_lock);
++ if (acm->delayed_wb) {
++ wb = acm->delayed_wb;
++ acm->delayed_wb = NULL;
++ spin_unlock_irq(&acm->write_lock);
++ acm_start_wb(acm, acm->delayed_wb);
++ } else {
++ spin_unlock_irq(&acm->write_lock);
++ }
++
++ /*
++ * delayed error checking because we must
++ * do the write path at all cost
++ */
+ if (rv < 0)
+ goto err_out;
+
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -112,7 +112,6 @@ struct acm {
+ struct mutex mutex;
+ struct usb_cdc_line_coding line; /* bits, stop, parity */
+ struct work_struct work; /* work queue entry for line discipline waking up */
+- struct work_struct waker;
+ wait_queue_head_t drain_wait; /* close processing */
+ struct tasklet_struct urb_task; /* rx processing */
+ spinlock_t throttle_lock; /* synchronize throtteling and read callback */
--- /dev/null
+From 20f6b2c785cf187445f126321638ab8ba7aa7494 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <david@fromorbit.com>
+Date: Thu, 4 Mar 2010 01:46:23 +0000
+Subject: xfs: check for more work before sleeping in xfssyncd
+
+From: Dave Chinner <david@fromorbit.com>
+
+commit 20f6b2c785cf187445f126321638ab8ba7aa7494 upstream.
+
+xfssyncd processes a queue of work by detaching the queue and
+then iterating over all the work items. It then sleeps for a
+time period or until new work comes in. If new work is queued
+while xfssyncd is actively processing the detached work queue,
+it will not process that new work until after a sleep timeout
+or the next work event queued wakes it.
+
+Fix this by checking the work queue again before going to sleep.
+
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Alex Elder <aelder@sgi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/xfs/linux-2.6/xfs_sync.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/xfs/linux-2.6/xfs_sync.c
++++ b/fs/xfs/linux-2.6/xfs_sync.c
+@@ -613,7 +613,8 @@ xfssyncd(
+ set_freezable();
+ timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
+ for (;;) {
+- timeleft = schedule_timeout_interruptible(timeleft);
++ if (list_empty(&mp->m_sync_list))
++ timeleft = schedule_timeout_interruptible(timeleft);
+ /* swsusp */
+ try_to_freeze();
+ if (kthread_should_stop() && list_empty(&mp->m_sync_list))
+@@ -633,8 +634,7 @@ xfssyncd(
+ list_add_tail(&mp->m_sync_work.w_list,
+ &mp->m_sync_list);
+ }
+- list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
+- list_move(&work->w_list, &tmp);
++ list_splice_init(&mp->m_sync_list, &tmp);
+ spin_unlock(&mp->m_sync_lock);
+
+ list_for_each_entry_safe(work, n, &tmp, w_list) {
--- /dev/null
+From f1f724e4b523d444c5a598d74505aefa3d6844d2 Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@infradead.org>
+Date: Mon, 1 Mar 2010 11:30:31 +0000
+Subject: xfs: fix locking for inode cache radix tree tag updates
+
+From: Christoph Hellwig <hch@infradead.org>
+
+commit f1f724e4b523d444c5a598d74505aefa3d6844d2 upstream.
+
+The radix-tree code requires it's users to serialize tag updates
+against other updates to the tree. While XFS protects tag updates
+against each other it does not serialize them against updates of the
+tree contents, which can lead to tag corruption. Fix the inode
+cache to always take pag_ici_lock in exclusive mode when updating
+radix tree tags.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reported-by: Patrick Schreurs <patrick@news-service.com>
+Tested-by: Patrick Schreurs <patrick@news-service.com>
+Signed-off-by: Alex Elder <aelder@sgi.com>
+Cc: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/xfs/linux-2.6/xfs_sync.c | 4 ++--
+ fs/xfs/xfs_iget.c | 19 +++++++++++++------
+ 2 files changed, 15 insertions(+), 8 deletions(-)
+
+--- a/fs/xfs/linux-2.6/xfs_sync.c
++++ b/fs/xfs/linux-2.6/xfs_sync.c
+@@ -693,12 +693,12 @@ xfs_inode_set_reclaim_tag(
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino);
+
+- read_lock(&pag->pag_ici_lock);
++ write_lock(&pag->pag_ici_lock);
+ spin_lock(&ip->i_flags_lock);
+ __xfs_inode_set_reclaim_tag(pag, ip);
+ __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
+ spin_unlock(&ip->i_flags_lock);
+- read_unlock(&pag->pag_ici_lock);
++ write_unlock(&pag->pag_ici_lock);
+ xfs_put_perag(mp, pag);
+ }
+
+--- a/fs/xfs/xfs_iget.c
++++ b/fs/xfs/xfs_iget.c
+@@ -190,13 +190,12 @@ xfs_iget_cache_hit(
+ trace_xfs_iget_reclaim(ip);
+
+ /*
+- * We need to set XFS_INEW atomically with clearing the
+- * reclaimable tag so that we do have an indicator of the
+- * inode still being initialized.
++ * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
++ * from stomping over us while we recycle the inode. We can't
++ * clear the radix tree reclaimable tag yet as it requires
++ * pag_ici_lock to be held exclusive.
+ */
+- ip->i_flags |= XFS_INEW;
+- ip->i_flags &= ~XFS_IRECLAIMABLE;
+- __xfs_inode_clear_reclaim_tag(mp, pag, ip);
++ ip->i_flags |= XFS_IRECLAIM;
+
+ spin_unlock(&ip->i_flags_lock);
+ read_unlock(&pag->pag_ici_lock);
+@@ -216,7 +215,15 @@ xfs_iget_cache_hit(
+ trace_xfs_iget_reclaim(ip);
+ goto out_error;
+ }
++
++ write_lock(&pag->pag_ici_lock);
++ spin_lock(&ip->i_flags_lock);
++ ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
++ ip->i_flags |= XFS_INEW;
++ __xfs_inode_clear_reclaim_tag(mp, pag, ip);
+ inode->i_state = I_NEW;
++ spin_unlock(&ip->i_flags_lock);
++ write_unlock(&pag->pag_ici_lock);
+ } else {
+ /* If the VFS inode is being torn down, pause and try again. */
+ if (!igrab(inode)) {
--- /dev/null
+From 77d7a0c2eeb285c9069e15396703d0cb9690ac50 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <david@fromorbit.com>
+Date: Wed, 17 Feb 2010 05:36:29 +0000
+Subject: xfs: Non-blocking inode locking in IO completion
+
+From: Dave Chinner <david@fromorbit.com>
+
+commit 77d7a0c2eeb285c9069e15396703d0cb9690ac50 upstream.
+
+The introduction of barriers to loop devices has created a new IO
+order completion dependency that XFS does not handle. The loop
+device implements barriers using fsync and so turns a log IO in the
+XFS filesystem on the loop device into a data IO in the backing
+filesystem. That is, the completion of log IOs in the loop
+filesystem are now dependent on completion of data IO in the backing
+filesystem.
+
+This can cause deadlocks when a flush daemon issues a log force with
+an inode locked because the IO completion of IO on the inode is
+blocked by the inode lock. This in turn prevents further data IO
+completion from occuring on all XFS filesystems on that CPU (due to
+the shared nature of the completion queues). This then prevents the
+log IO from completing because the log is waiting for data IO
+completion as well.
+
+The fix for this new completion order dependency issue is to make
+the IO completion inode locking non-blocking. If the inode lock
+can't be grabbed, simply requeue the IO completion back to the work
+queue so that it can be processed later. This prevents the
+completion queue from being blocked and allows data IO completion on
+other inodes to proceed, hence avoiding completion order dependent
+deadlocks.
+
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Alex Elder <aelder@sgi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/xfs/linux-2.6/xfs_aops.c | 93 ++++++++++++++++++++++++++------------------
+ 1 file changed, 56 insertions(+), 37 deletions(-)
+
+--- a/fs/xfs/linux-2.6/xfs_aops.c
++++ b/fs/xfs/linux-2.6/xfs_aops.c
+@@ -163,14 +163,17 @@ xfs_ioend_new_eof(
+ }
+
+ /*
+- * Update on-disk file size now that data has been written to disk.
+- * The current in-memory file size is i_size. If a write is beyond
+- * eof i_new_size will be the intended file size until i_size is
+- * updated. If this write does not extend all the way to the valid
+- * file size then restrict this update to the end of the write.
++ * Update on-disk file size now that data has been written to disk. The
++ * current in-memory file size is i_size. If a write is beyond eof i_new_size
++ * will be the intended file size until i_size is updated. If this write does
++ * not extend all the way to the valid file size then restrict this update to
++ * the end of the write.
++ *
++ * This function does not block as blocking on the inode lock in IO completion
++ * can lead to IO completion order dependency deadlocks.. If it can't get the
++ * inode ilock it will return EAGAIN. Callers must handle this.
+ */
+-
+-STATIC void
++STATIC int
+ xfs_setfilesize(
+ xfs_ioend_t *ioend)
+ {
+@@ -181,9 +184,11 @@ xfs_setfilesize(
+ ASSERT(ioend->io_type != IOMAP_READ);
+
+ if (unlikely(ioend->io_error))
+- return;
++ return 0;
++
++ if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
++ return EAGAIN;
+
+- xfs_ilock(ip, XFS_ILOCK_EXCL);
+ isize = xfs_ioend_new_eof(ioend);
+ if (isize) {
+ ip->i_d.di_size = isize;
+@@ -191,6 +196,28 @@ xfs_setfilesize(
+ }
+
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++ return 0;
++}
++
++/*
++ * Schedule IO completion handling on a xfsdatad if this was
++ * the final hold on this ioend. If we are asked to wait,
++ * flush the workqueue.
++ */
++STATIC void
++xfs_finish_ioend(
++ xfs_ioend_t *ioend,
++ int wait)
++{
++ if (atomic_dec_and_test(&ioend->io_remaining)) {
++ struct workqueue_struct *wq;
++
++ wq = (ioend->io_type == IOMAP_UNWRITTEN) ?
++ xfsconvertd_workqueue : xfsdatad_workqueue;
++ queue_work(wq, &ioend->io_work);
++ if (wait)
++ flush_workqueue(wq);
++ }
+ }
+
+ /*
+@@ -198,11 +225,11 @@ xfs_setfilesize(
+ */
+ STATIC void
+ xfs_end_io(
+- struct work_struct *work)
++ struct work_struct *work)
+ {
+- xfs_ioend_t *ioend =
+- container_of(work, xfs_ioend_t, io_work);
+- struct xfs_inode *ip = XFS_I(ioend->io_inode);
++ xfs_ioend_t *ioend = container_of(work, xfs_ioend_t, io_work);
++ struct xfs_inode *ip = XFS_I(ioend->io_inode);
++ int error;
+
+ /*
+ * For unwritten extents we need to issue transactions to convert a
+@@ -210,7 +237,6 @@ xfs_end_io(
+ */
+ if (ioend->io_type == IOMAP_UNWRITTEN &&
+ likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) {
+- int error;
+
+ error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
+ ioend->io_size);
+@@ -222,30 +248,23 @@ xfs_end_io(
+ * We might have to update the on-disk file size after extending
+ * writes.
+ */
+- if (ioend->io_type != IOMAP_READ)
+- xfs_setfilesize(ioend);
+- xfs_destroy_ioend(ioend);
+-}
+-
+-/*
+- * Schedule IO completion handling on a xfsdatad if this was
+- * the final hold on this ioend. If we are asked to wait,
+- * flush the workqueue.
+- */
+-STATIC void
+-xfs_finish_ioend(
+- xfs_ioend_t *ioend,
+- int wait)
+-{
+- if (atomic_dec_and_test(&ioend->io_remaining)) {
+- struct workqueue_struct *wq;
+-
+- wq = (ioend->io_type == IOMAP_UNWRITTEN) ?
+- xfsconvertd_workqueue : xfsdatad_workqueue;
+- queue_work(wq, &ioend->io_work);
+- if (wait)
+- flush_workqueue(wq);
++ if (ioend->io_type != IOMAP_READ) {
++ error = xfs_setfilesize(ioend);
++ ASSERT(!error || error == EAGAIN);
+ }
++
++ /*
++ * If we didn't complete processing of the ioend, requeue it to the
++ * tail of the workqueue for another attempt later. Otherwise destroy
++ * it.
++ */
++ if (error == EAGAIN) {
++ atomic_inc(&ioend->io_remaining);
++ xfs_finish_ioend(ioend, 0);
++ /* ensure we don't spin on blocked ioends */
++ delay(1);
++ } else
++ xfs_destroy_ioend(ioend);
+ }
+
+ /*