]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.8-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:39:29 +0000 (14:39 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:39:29 +0000 (14:39 -0700)
added patches:
mwifiex-cancel-cmd-timer-and-free-curr_cmd-in-shutdown-process.patch
mwifiex-fix-race-when-queuing-commands.patch
mwifiex-skip-pending-commands-after-function-shutdown.patch
nest-rename_lock-inside-vfsmount_lock.patch
net-irda-add-missing-error-path-release_sock-call.patch
nfsv4.1-always-clear-the-nfs_ino_layoutcommit-in-layoutreturn.patch
nfsv4.1-fix-a-race-in-pnfs-layoutcommit.patch
nfsv4-fix-the-string-length-returned-by-the-idmapper.patch
pnfs-block-removing-dm-device-maybe-cause-oops-when-call-dev_remove.patch
tty-atmel_serial_probe-index-of-atmel_ports-fix.patch
usb-ehci-fix-bug-in-itd-sitd-dma-pool-allocation.patch
usb-ftdi_sio-add-support-for-mitsubishi-fx-usb-aw-bd.patch
usb-xhci-fix-trb-transfer-length-macro-used-for-event-trb.patch
vt-synchronize_rcu-under-spinlock-is-not-nice.patch
xen-blkback-correctly-respond-to-unknown-non-native-requests.patch
xen-blkback-fix-dispatch_rw_block_io-error-path.patch
xen-blkfront-switch-from-llist-to-list.patch
xen-pciback-notify-hypervisor-about-devices-intended-to-be-assigned-to-guests.patch

19 files changed:
queue-3.8/mwifiex-cancel-cmd-timer-and-free-curr_cmd-in-shutdown-process.patch [new file with mode: 0644]
queue-3.8/mwifiex-fix-race-when-queuing-commands.patch [new file with mode: 0644]
queue-3.8/mwifiex-skip-pending-commands-after-function-shutdown.patch [new file with mode: 0644]
queue-3.8/nest-rename_lock-inside-vfsmount_lock.patch [new file with mode: 0644]
queue-3.8/net-irda-add-missing-error-path-release_sock-call.patch [new file with mode: 0644]
queue-3.8/nfsv4-fix-the-string-length-returned-by-the-idmapper.patch [new file with mode: 0644]
queue-3.8/nfsv4.1-always-clear-the-nfs_ino_layoutcommit-in-layoutreturn.patch [new file with mode: 0644]
queue-3.8/nfsv4.1-fix-a-race-in-pnfs-layoutcommit.patch [new file with mode: 0644]
queue-3.8/pnfs-block-removing-dm-device-maybe-cause-oops-when-call-dev_remove.patch [new file with mode: 0644]
queue-3.8/series
queue-3.8/tty-atmel_serial_probe-index-of-atmel_ports-fix.patch [new file with mode: 0644]
queue-3.8/usb-ehci-fix-bug-in-itd-sitd-dma-pool-allocation.patch [new file with mode: 0644]
queue-3.8/usb-ftdi_sio-add-support-for-mitsubishi-fx-usb-aw-bd.patch [new file with mode: 0644]
queue-3.8/usb-xhci-fix-trb-transfer-length-macro-used-for-event-trb.patch [new file with mode: 0644]
queue-3.8/vt-synchronize_rcu-under-spinlock-is-not-nice.patch [new file with mode: 0644]
queue-3.8/xen-blkback-correctly-respond-to-unknown-non-native-requests.patch [new file with mode: 0644]
queue-3.8/xen-blkback-fix-dispatch_rw_block_io-error-path.patch [new file with mode: 0644]
queue-3.8/xen-blkfront-switch-from-llist-to-list.patch [new file with mode: 0644]
queue-3.8/xen-pciback-notify-hypervisor-about-devices-intended-to-be-assigned-to-guests.patch [new file with mode: 0644]

diff --git a/queue-3.8/mwifiex-cancel-cmd-timer-and-free-curr_cmd-in-shutdown-process.patch b/queue-3.8/mwifiex-cancel-cmd-timer-and-free-curr_cmd-in-shutdown-process.patch
new file mode 100644 (file)
index 0000000..8b827e2
--- /dev/null
@@ -0,0 +1,40 @@
+From 084c7189acb3f969c855536166042e27f5dd703f Mon Sep 17 00:00:00 2001
+From: Bing Zhao <bzhao@marvell.com>
+Date: Fri, 15 Mar 2013 18:47:07 -0700
+Subject: mwifiex: cancel cmd timer and free curr_cmd in shutdown process
+
+From: Bing Zhao <bzhao@marvell.com>
+
+commit 084c7189acb3f969c855536166042e27f5dd703f upstream.
+
+curr_cmd points to the command that is in processing or waiting
+for its command response from firmware. If the function shutdown
+happens to occur at this time we should cancel the cmd timer and
+put the command back to free queue.
+
+Tested-by: Marco Cesarano <marco@marvell.com>
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/init.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/net/wireless/mwifiex/init.c
++++ b/drivers/net/wireless/mwifiex/init.c
+@@ -707,6 +707,14 @@ mwifiex_shutdown_drv(struct mwifiex_adap
+               return ret;
+       }
++      /* cancel current command */
++      if (adapter->curr_cmd) {
++              dev_warn(adapter->dev, "curr_cmd is still in processing\n");
++              del_timer(&adapter->cmd_timer);
++              mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
++              adapter->curr_cmd = NULL;
++      }
++
+       /* shut down mwifiex */
+       dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
diff --git a/queue-3.8/mwifiex-fix-race-when-queuing-commands.patch b/queue-3.8/mwifiex-fix-race-when-queuing-commands.patch
new file mode 100644 (file)
index 0000000..d426b2a
--- /dev/null
@@ -0,0 +1,138 @@
+From 00d7ea11ff0783e24fe70778f3141270b561aaa1 Mon Sep 17 00:00:00 2001
+From: Amitkumar Karwar <akarwar@marvell.com>
+Date: Fri, 15 Mar 2013 18:47:05 -0700
+Subject: mwifiex: fix race when queuing commands
+
+From: Amitkumar Karwar <akarwar@marvell.com>
+
+commit 00d7ea11ff0783e24fe70778f3141270b561aaa1 upstream.
+
+Running the following script repeatedly on XO-4 with SD8787
+produces command timeout and system lockup.
+
+insmod mwifiex_sdio.ko
+sleep 1
+ifconfig eth0 up
+iwlist eth0 scan &
+sleep 0.5
+rmmod mwifiex_sdio
+
+mwifiex_send_cmd_async() is called for sync as well as async
+commands. (mwifiex_send_cmd_sync() internally calls it for
+sync command.)
+
+"adapter->cmd_queued" gets filled inside mwifiex_send_cmd_async()
+routine for both types of commands. But it is used only for sync
+commands in mwifiex_wait_queue_complete(). This could lead to a
+race when two threads try to queue a sync command with another
+sync/async command simultaneously.
+
+Get rid of global variable and pass command node as a parameter
+to mwifiex_wait_queue_complete() to fix the problem.
+
+Reported-by: Daniel Drake <dsd@laptop.org>
+Tested-by: Daniel Drake <dsd@laptop.org>
+Tested-by: Marco Cesarano <marco@marvell.com>
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/cmdevt.c    |    5 ++---
+ drivers/net/wireless/mwifiex/main.h      |    4 ++--
+ drivers/net/wireless/mwifiex/scan.c      |    8 ++++----
+ drivers/net/wireless/mwifiex/sta_ioctl.c |   10 ++--------
+ 4 files changed, 10 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/cmdevt.c
++++ b/drivers/net/wireless/mwifiex/cmdevt.c
+@@ -488,8 +488,6 @@ int mwifiex_send_cmd_sync(struct mwifiex
+       ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
+                                    data_buf);
+-      if (!ret)
+-              ret = mwifiex_wait_queue_complete(adapter);
+       return ret;
+ }
+@@ -592,9 +590,10 @@ int mwifiex_send_cmd_async(struct mwifie
+       if (cmd_no == HostCmd_CMD_802_11_SCAN) {
+               mwifiex_queue_scan_cmd(priv, cmd_node);
+       } else {
+-              adapter->cmd_queued = cmd_node;
+               mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+               queue_work(adapter->workqueue, &adapter->main_work);
++              if (cmd_node->wait_q_enabled)
++                      ret = mwifiex_wait_queue_complete(adapter, cmd_node);
+       }
+       return ret;
+--- a/drivers/net/wireless/mwifiex/main.h
++++ b/drivers/net/wireless/mwifiex/main.h
+@@ -714,7 +714,6 @@ struct mwifiex_adapter {
+       u16 cmd_wait_q_required;
+       struct mwifiex_wait_queue cmd_wait_q;
+       u8 scan_wait_q_woken;
+-      struct cmd_ctrl_node *cmd_queued;
+       spinlock_t queue_lock;          /* lock for tx queues */
+       struct completion fw_load;
+       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
+@@ -994,7 +993,8 @@ int mwifiex_request_set_multicast_list(s
+                       struct mwifiex_multicast_list *mcast_list);
+ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
+                           struct net_device *dev);
+-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
++int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
++                              struct cmd_ctrl_node *cmd_queued);
+ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+                     struct cfg80211_ssid *req_ssid);
+ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
+--- a/drivers/net/wireless/mwifiex/scan.c
++++ b/drivers/net/wireless/mwifiex/scan.c
+@@ -1366,10 +1366,13 @@ int mwifiex_scan_networks(struct mwifiex
+                       list_del(&cmd_node->list);
+                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                              flags);
+-                      adapter->cmd_queued = cmd_node;
+                       mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
+                                                       true);
+                       queue_work(adapter->workqueue, &adapter->main_work);
++
++                      /* Perform internal scan synchronously */
++                      if (!priv->scan_request)
++                              mwifiex_wait_queue_complete(adapter, cmd_node);
+               } else {
+                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                              flags);
+@@ -1923,9 +1926,6 @@ int mwifiex_request_scan(struct mwifiex_
+               /* Normal scan */
+               ret = mwifiex_scan_networks(priv, NULL);
+-      if (!ret)
+-              ret = mwifiex_wait_queue_complete(priv->adapter);
+-
+       up(&priv->async_sem);
+       return ret;
+--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
+@@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifi
+  * This function waits on a cmd wait queue. It also cancels the pending
+  * request after waking up, in case of errors.
+  */
+-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
++int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
++                              struct cmd_ctrl_node *cmd_queued)
+ {
+       int status;
+-      struct cmd_ctrl_node *cmd_queued;
+-
+-      if (!adapter->cmd_queued)
+-              return 0;
+-
+-      cmd_queued = adapter->cmd_queued;
+-      adapter->cmd_queued = NULL;
+       dev_dbg(adapter->dev, "cmd pending\n");
+       atomic_inc(&adapter->cmd_pending);
diff --git a/queue-3.8/mwifiex-skip-pending-commands-after-function-shutdown.patch b/queue-3.8/mwifiex-skip-pending-commands-after-function-shutdown.patch
new file mode 100644 (file)
index 0000000..0a9d29a
--- /dev/null
@@ -0,0 +1,60 @@
+From a3e240cacc93a06bff3313e28938e980d01a2160 Mon Sep 17 00:00:00 2001
+From: Bing Zhao <bzhao@marvell.com>
+Date: Fri, 15 Mar 2013 18:47:06 -0700
+Subject: mwifiex: skip pending commands after function shutdown
+
+From: Bing Zhao <bzhao@marvell.com>
+
+commit a3e240cacc93a06bff3313e28938e980d01a2160 upstream.
+
+During rmmod mwifiex_sdio processing FUNC_SHUTDOWN command is
+sent to firmware. Firmware expcets only FUNC_INIT once WLAN
+function is shut down.
+
+Any command pending in the command queue should be ignored and
+freed.
+
+Tested-by: Daniel Drake <dsd@laptop.org>
+Tested-by: Marco Cesarano <marco@marvell.com>
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/cmdevt.c |   17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/cmdevt.c
++++ b/drivers/net/wireless/mwifiex/cmdevt.c
+@@ -156,6 +156,20 @@ static int mwifiex_dnld_cmd_to_fw(struct
+               return -1;
+       }
++      cmd_code = le16_to_cpu(host_cmd->command);
++      cmd_size = le16_to_cpu(host_cmd->size);
++
++      if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
++          cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
++          cmd_code != HostCmd_CMD_FUNC_INIT) {
++              dev_err(adapter->dev,
++                      "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
++                      cmd_code);
++              mwifiex_complete_cmd(adapter, cmd_node);
++              mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
++              return -1;
++      }
++
+       /* Set command sequence number */
+       adapter->seq_num++;
+       host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
+@@ -167,9 +181,6 @@ static int mwifiex_dnld_cmd_to_fw(struct
+       adapter->curr_cmd = cmd_node;
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+-      cmd_code = le16_to_cpu(host_cmd->command);
+-      cmd_size = le16_to_cpu(host_cmd->size);
+-
+       /* Adjust skb length */
+       if (cmd_node->cmd_skb->len > cmd_size)
+               /*
diff --git a/queue-3.8/nest-rename_lock-inside-vfsmount_lock.patch b/queue-3.8/nest-rename_lock-inside-vfsmount_lock.patch
new file mode 100644 (file)
index 0000000..09b06ce
--- /dev/null
@@ -0,0 +1,119 @@
+From 7ea600b5314529f9d1b9d6d3c41cb26fce6a7a4a Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 26 Mar 2013 18:25:57 -0400
+Subject: Nest rename_lock inside vfsmount_lock
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 7ea600b5314529f9d1b9d6d3c41cb26fce6a7a4a upstream.
+
+... lest we get livelocks between path_is_under() and d_path() and friends.
+
+The thing is, wrt fairness lglocks are more similar to rwsems than to rwlocks;
+it is possible to have thread B spin on attempt to take lock shared while thread
+A is already holding it shared, if B is on lower-numbered CPU than A and there's
+a thread C spinning on attempt to take the same lock exclusive.
+
+As the result, we need consistent ordering between vfsmount_lock (lglock) and
+rename_lock (seq_lock), even though everything that takes both is going to take
+vfsmount_lock only shared.
+
+Spotted-by: Brad Spengler <spender@grsecurity.net>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/dcache.c |   16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -2552,7 +2552,6 @@ static int prepend_path(const struct pat
+       bool slash = false;
+       int error = 0;
+-      br_read_lock(&vfsmount_lock);
+       while (dentry != root->dentry || vfsmnt != root->mnt) {
+               struct dentry * parent;
+@@ -2582,8 +2581,6 @@ static int prepend_path(const struct pat
+       if (!error && !slash)
+               error = prepend(buffer, buflen, "/", 1);
+-out:
+-      br_read_unlock(&vfsmount_lock);
+       return error;
+ global_root:
+@@ -2600,7 +2597,7 @@ global_root:
+               error = prepend(buffer, buflen, "/", 1);
+       if (!error)
+               error = is_mounted(vfsmnt) ? 1 : 2;
+-      goto out;
++      return error;
+ }
+ /**
+@@ -2627,9 +2624,11 @@ char *__d_path(const struct path *path,
+       int error;
+       prepend(&res, &buflen, "\0", 1);
++      br_read_lock(&vfsmount_lock);
+       write_seqlock(&rename_lock);
+       error = prepend_path(path, root, &res, &buflen);
+       write_sequnlock(&rename_lock);
++      br_read_unlock(&vfsmount_lock);
+       if (error < 0)
+               return ERR_PTR(error);
+@@ -2646,9 +2645,11 @@ char *d_absolute_path(const struct path
+       int error;
+       prepend(&res, &buflen, "\0", 1);
++      br_read_lock(&vfsmount_lock);
+       write_seqlock(&rename_lock);
+       error = prepend_path(path, &root, &res, &buflen);
+       write_sequnlock(&rename_lock);
++      br_read_unlock(&vfsmount_lock);
+       if (error > 1)
+               error = -EINVAL;
+@@ -2712,11 +2713,13 @@ char *d_path(const struct path *path, ch
+               return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
+       get_fs_root(current->fs, &root);
++      br_read_lock(&vfsmount_lock);
+       write_seqlock(&rename_lock);
+       error = path_with_deleted(path, &root, &res, &buflen);
++      write_sequnlock(&rename_lock);
++      br_read_unlock(&vfsmount_lock);
+       if (error < 0)
+               res = ERR_PTR(error);
+-      write_sequnlock(&rename_lock);
+       path_put(&root);
+       return res;
+ }
+@@ -2871,6 +2874,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
+       get_fs_root_and_pwd(current->fs, &root, &pwd);
+       error = -ENOENT;
++      br_read_lock(&vfsmount_lock);
+       write_seqlock(&rename_lock);
+       if (!d_unlinked(pwd.dentry)) {
+               unsigned long len;
+@@ -2880,6 +2884,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
+               prepend(&cwd, &buflen, "\0", 1);
+               error = prepend_path(&pwd, &root, &cwd, &buflen);
+               write_sequnlock(&rename_lock);
++              br_read_unlock(&vfsmount_lock);
+               if (error < 0)
+                       goto out;
+@@ -2900,6 +2905,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
+               }
+       } else {
+               write_sequnlock(&rename_lock);
++              br_read_unlock(&vfsmount_lock);
+       }
+ out:
diff --git a/queue-3.8/net-irda-add-missing-error-path-release_sock-call.patch b/queue-3.8/net-irda-add-missing-error-path-release_sock-call.patch
new file mode 100644 (file)
index 0000000..3db2837
--- /dev/null
@@ -0,0 +1,36 @@
+From 896ee0eee6261e30c3623be931c3f621428947df Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 20 Mar 2013 05:19:24 +0000
+Subject: net/irda: add missing error path release_sock call
+
+From: Kees Cook <keescook@chromium.org>
+
+commit 896ee0eee6261e30c3623be931c3f621428947df upstream.
+
+This makes sure that release_sock is called for all error conditions in
+irda_getsockopt.
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Reported-by: Brad Spengler <spender@grsecurity.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/irda/af_irda.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/irda/af_irda.c
++++ b/net/irda/af_irda.c
+@@ -2584,8 +2584,10 @@ bed:
+                                   NULL, NULL, NULL);
+               /* Check if the we got some results */
+-              if (!self->cachedaddr)
+-                      return -EAGAIN;         /* Didn't find any devices */
++              if (!self->cachedaddr) {
++                      err = -EAGAIN;          /* Didn't find any devices */
++                      goto out;
++              }
+               daddr = self->cachedaddr;
+               /* Cleanup */
+               self->cachedaddr = 0;
diff --git a/queue-3.8/nfsv4-fix-the-string-length-returned-by-the-idmapper.patch b/queue-3.8/nfsv4-fix-the-string-length-returned-by-the-idmapper.patch
new file mode 100644 (file)
index 0000000..82cc2cd
--- /dev/null
@@ -0,0 +1,64 @@
+From cf4ab538f1516606d3ae730dce15d6f33d96b7e1 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Fri, 8 Mar 2013 12:56:37 -0500
+Subject: NFSv4: Fix the string length returned by the idmapper
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit cf4ab538f1516606d3ae730dce15d6f33d96b7e1 upstream.
+
+Functions like nfs_map_uid_to_name() and nfs_map_gid_to_group() are
+expected to return a string without any terminating NUL character.
+Regression introduced by commit 57e62324e469e092ecc6c94a7a86fe4bd6ac5172
+(NFS: Store the legacy idmapper result in the keyring).
+
+Reported-by: Dave Chiluk <dave.chiluk@canonical.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Cc: Bryan Schumaker <bjschuma@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/idmap.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/fs/nfs/idmap.c
++++ b/fs/nfs/idmap.c
+@@ -725,9 +725,9 @@ out1:
+       return ret;
+ }
+-static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data)
++static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
+ {
+-      return key_instantiate_and_link(key, data, strlen(data) + 1,
++      return key_instantiate_and_link(key, data, datalen,
+                                       id_resolver_cache->thread_keyring,
+                                       authkey);
+ }
+@@ -737,6 +737,7 @@ static int nfs_idmap_read_and_verify_mes
+               struct key *key, struct key *authkey)
+ {
+       char id_str[NFS_UINT_MAXLEN];
++      size_t len;
+       int ret = -ENOKEY;
+       /* ret = -ENOKEY */
+@@ -746,13 +747,15 @@ static int nfs_idmap_read_and_verify_mes
+       case IDMAP_CONV_NAMETOID:
+               if (strcmp(upcall->im_name, im->im_name) != 0)
+                       break;
+-              sprintf(id_str, "%d", im->im_id);
+-              ret = nfs_idmap_instantiate(key, authkey, id_str);
++              /* Note: here we store the NUL terminator too */
++              len = sprintf(id_str, "%d", im->im_id) + 1;
++              ret = nfs_idmap_instantiate(key, authkey, id_str, len);
+               break;
+       case IDMAP_CONV_IDTONAME:
+               if (upcall->im_id != im->im_id)
+                       break;
+-              ret = nfs_idmap_instantiate(key, authkey, im->im_name);
++              len = strlen(im->im_name);
++              ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
+               break;
+       default:
+               ret = -EINVAL;
diff --git a/queue-3.8/nfsv4.1-always-clear-the-nfs_ino_layoutcommit-in-layoutreturn.patch b/queue-3.8/nfsv4.1-always-clear-the-nfs_ino_layoutcommit-in-layoutreturn.patch
new file mode 100644 (file)
index 0000000..39d8a22
--- /dev/null
@@ -0,0 +1,121 @@
+From 24956804349ca0eadcdde032d65e8c00b4214096 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Wed, 20 Mar 2013 13:03:00 -0400
+Subject: NFSv4.1: Always clear the NFS_INO_LAYOUTCOMMIT in layoutreturn
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 24956804349ca0eadcdde032d65e8c00b4214096 upstream.
+
+Note that clearing NFS_INO_LAYOUTCOMMIT is tricky, since it requires
+you to also clear the NFS_LSEG_LAYOUTCOMMIT bits from the layout
+segments.
+The only two sites that need to do this are the ones that call
+pnfs_return_layout() without first doing a layout commit.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Acked-by: Benny Halevy <bhalevy@tonian.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4filelayout.c |    1 -
+ fs/nfs/pnfs.c           |   35 +++++++++++++++++++++++++++--------
+ 2 files changed, 27 insertions(+), 9 deletions(-)
+
+--- a/fs/nfs/nfs4filelayout.c
++++ b/fs/nfs/nfs4filelayout.c
+@@ -129,7 +129,6 @@ static void filelayout_fenceme(struct in
+ {
+       if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+               return;
+-      clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
+       pnfs_return_layout(inode);
+ }
+--- a/fs/nfs/pnfs.c
++++ b/fs/nfs/pnfs.c
+@@ -417,6 +417,16 @@ should_free_lseg(struct pnfs_layout_rang
+              lo_seg_intersecting(lseg_range, recall_range);
+ }
++static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
++              struct list_head *tmp_list)
++{
++      if (!atomic_dec_and_test(&lseg->pls_refcount))
++              return false;
++      pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
++      list_add(&lseg->pls_list, tmp_list);
++      return true;
++}
++
+ /* Returns 1 if lseg is removed from list, 0 otherwise */
+ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
+                            struct list_head *tmp_list)
+@@ -430,11 +440,8 @@ static int mark_lseg_invalid(struct pnfs
+                */
+               dprintk("%s: lseg %p ref %d\n", __func__, lseg,
+                       atomic_read(&lseg->pls_refcount));
+-              if (atomic_dec_and_test(&lseg->pls_refcount)) {
+-                      pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
+-                      list_add(&lseg->pls_list, tmp_list);
++              if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list))
+                       rv = 1;
+-              }
+       }
+       return rv;
+ }
+@@ -777,6 +784,21 @@ send_layoutget(struct pnfs_layout_hdr *l
+       return lseg;
+ }
++static void pnfs_clear_layoutcommit(struct inode *inode,
++              struct list_head *head)
++{
++      struct nfs_inode *nfsi = NFS_I(inode);
++      struct pnfs_layout_segment *lseg, *tmp;
++
++      if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
++              return;
++      list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) {
++              if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
++                      continue;
++              pnfs_lseg_dec_and_remove_zero(lseg, head);
++      }
++}
++
+ /*
+  * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
+  * when the layout segment list is empty.
+@@ -808,6 +830,7 @@ _pnfs_return_layout(struct inode *ino)
+       /* Reference matched in nfs4_layoutreturn_release */
+       pnfs_get_layout_hdr(lo);
+       empty = list_empty(&lo->plh_segs);
++      pnfs_clear_layoutcommit(ino, &tmp_list);
+       pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
+       /* Don't send a LAYOUTRETURN if list was initially empty */
+       if (empty) {
+@@ -820,8 +843,6 @@ _pnfs_return_layout(struct inode *ino)
+       spin_unlock(&ino->i_lock);
+       pnfs_free_lseg_list(&tmp_list);
+-      WARN_ON(test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags));
+-
+       lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
+       if (unlikely(lrp == NULL)) {
+               status = -ENOMEM;
+@@ -1459,7 +1480,6 @@ static void pnfs_ld_handle_write_error(s
+       dprintk("pnfs write error = %d\n", hdr->pnfs_error);
+       if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
+           PNFS_LAYOUTRET_ON_ERROR) {
+-              clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
+               pnfs_return_layout(hdr->inode);
+       }
+       if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
+@@ -1614,7 +1634,6 @@ static void pnfs_ld_handle_read_error(st
+       dprintk("pnfs read error = %d\n", hdr->pnfs_error);
+       if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
+           PNFS_LAYOUTRET_ON_ERROR) {
+-              clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
+               pnfs_return_layout(hdr->inode);
+       }
+       if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
diff --git a/queue-3.8/nfsv4.1-fix-a-race-in-pnfs-layoutcommit.patch b/queue-3.8/nfsv4.1-fix-a-race-in-pnfs-layoutcommit.patch
new file mode 100644 (file)
index 0000000..d05e2f9
--- /dev/null
@@ -0,0 +1,92 @@
+From a073dbff359f4741013ae4b8395f5364c5e00b48 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Wed, 20 Mar 2013 12:34:32 -0400
+Subject: NFSv4.1: Fix a race in pNFS layoutcommit
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit a073dbff359f4741013ae4b8395f5364c5e00b48 upstream.
+
+We need to clear the NFS_LSEG_LAYOUTCOMMIT bits atomically with the
+NFS_INO_LAYOUTCOMMIT bit, otherwise we may end up with situations
+where the two are out of sync.
+The first half of the problem is to ensure that pnfs_layoutcommit_inode
+clears the NFS_LSEG_LAYOUTCOMMIT bit through pnfs_list_write_lseg.
+We still need to keep the reference to those segments until the RPC call
+is finished, so in order to make it clear _where_ those references come
+from, we add a helper pnfs_list_write_lseg_done() that cleans up after
+pnfs_list_write_lseg.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Acked-by: Benny Halevy <bhalevy@tonian.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |   14 --------------
+ fs/nfs/pnfs.c     |   19 ++++++++++++++++++-
+ 2 files changed, 18 insertions(+), 15 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -6366,22 +6366,8 @@ nfs4_layoutcommit_done(struct rpc_task *
+ static void nfs4_layoutcommit_release(void *calldata)
+ {
+       struct nfs4_layoutcommit_data *data = calldata;
+-      struct pnfs_layout_segment *lseg, *tmp;
+-      unsigned long *bitlock = &NFS_I(data->args.inode)->flags;
+       pnfs_cleanup_layoutcommit(data);
+-      /* Matched by references in pnfs_set_layoutcommit */
+-      list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
+-              list_del_init(&lseg->pls_lc_list);
+-              if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
+-                                     &lseg->pls_flags))
+-                      pnfs_put_lseg(lseg);
+-      }
+-
+-      clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
+-      smp_mb__after_clear_bit();
+-      wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+-
+       put_rpccred(data->cred);
+       kfree(data);
+ }
+--- a/fs/nfs/pnfs.c
++++ b/fs/nfs/pnfs.c
+@@ -1747,11 +1747,27 @@ static void pnfs_list_write_lseg(struct
+       list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
+               if (lseg->pls_range.iomode == IOMODE_RW &&
+-                  test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
++                  test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+                       list_add(&lseg->pls_lc_list, listp);
+       }
+ }
++static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
++{
++      struct pnfs_layout_segment *lseg, *tmp;
++      unsigned long *bitlock = &NFS_I(inode)->flags;
++
++      /* Matched by references in pnfs_set_layoutcommit */
++      list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
++              list_del_init(&lseg->pls_lc_list);
++              pnfs_put_lseg(lseg);
++      }
++
++      clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
++      smp_mb__after_clear_bit();
++      wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
++}
++
+ void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
+ {
+       pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode);
+@@ -1796,6 +1812,7 @@ void pnfs_cleanup_layoutcommit(struct nf
+       if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
+               nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
++      pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list);
+ }
+ /*
diff --git a/queue-3.8/pnfs-block-removing-dm-device-maybe-cause-oops-when-call-dev_remove.patch b/queue-3.8/pnfs-block-removing-dm-device-maybe-cause-oops-when-call-dev_remove.patch
new file mode 100644 (file)
index 0000000..fc340d9
--- /dev/null
@@ -0,0 +1,43 @@
+From 4376c94618c26225e69e17b7c91169c45a90b292 Mon Sep 17 00:00:00 2001
+From: fanchaoting <fanchaoting@cn.fujitsu.com>
+Date: Thu, 21 Mar 2013 09:15:30 +0800
+Subject: pnfs-block: removing DM device maybe cause oops when call dev_remove
+
+From: fanchaoting <fanchaoting@cn.fujitsu.com>
+
+commit 4376c94618c26225e69e17b7c91169c45a90b292 upstream.
+
+when pnfs block using device mapper,if umounting later,it maybe
+cause oops. we apply "1 + sizeof(bl_umount_request)" memory for
+msg->data, the memory maybe overflow when we do "memcpy(&dataptr
+[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request))",
+because the size of bl_msg is more than 1 byte.
+
+Signed-off-by: fanchaoting<fanchaoting@cn.fujitsu.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/blocklayout/blocklayoutdm.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/nfs/blocklayout/blocklayoutdm.c
++++ b/fs/nfs/blocklayout/blocklayoutdm.c
+@@ -55,7 +55,8 @@ static void dev_remove(struct net *net,
+       bl_pipe_msg.bl_wq = &nn->bl_wq;
+       memset(msg, 0, sizeof(*msg));
+-      msg->data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS);
++      msg->len = sizeof(bl_msg) + bl_msg.totallen;
++      msg->data = kzalloc(msg->len, GFP_NOFS);
+       if (!msg->data)
+               goto out;
+@@ -66,7 +67,6 @@ static void dev_remove(struct net *net,
+       memcpy(msg->data, &bl_msg, sizeof(bl_msg));
+       dataptr = (uint8_t *) msg->data;
+       memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
+-      msg->len = sizeof(bl_msg) + bl_msg.totallen;
+       add_wait_queue(&nn->bl_wq, &wq);
+       if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) {
index 92796c6dd14fcf7ca9fd36f6a2718c6147408bb4..82d1382e97e33d6886abc03fdffaf155a71f11f7 100644 (file)
@@ -23,3 +23,21 @@ b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch
 tg3-fix-length-overflow-in-vpd-firmware-parsing.patch
 mac80211-always-synchronize_net-during-station-removal.patch
 iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch
+xen-pciback-notify-hypervisor-about-devices-intended-to-be-assigned-to-guests.patch
+xen-blkback-correctly-respond-to-unknown-non-native-requests.patch
+xen-blkback-fix-dispatch_rw_block_io-error-path.patch
+xen-blkfront-switch-from-llist-to-list.patch
+tty-atmel_serial_probe-index-of-atmel_ports-fix.patch
+usb-ftdi_sio-add-support-for-mitsubishi-fx-usb-aw-bd.patch
+vt-synchronize_rcu-under-spinlock-is-not-nice.patch
+mwifiex-fix-race-when-queuing-commands.patch
+mwifiex-skip-pending-commands-after-function-shutdown.patch
+mwifiex-cancel-cmd-timer-and-free-curr_cmd-in-shutdown-process.patch
+pnfs-block-removing-dm-device-maybe-cause-oops-when-call-dev_remove.patch
+nfsv4-fix-the-string-length-returned-by-the-idmapper.patch
+nfsv4.1-fix-a-race-in-pnfs-layoutcommit.patch
+nfsv4.1-always-clear-the-nfs_ino_layoutcommit-in-layoutreturn.patch
+net-irda-add-missing-error-path-release_sock-call.patch
+nest-rename_lock-inside-vfsmount_lock.patch
+usb-ehci-fix-bug-in-itd-sitd-dma-pool-allocation.patch
+usb-xhci-fix-trb-transfer-length-macro-used-for-event-trb.patch
diff --git a/queue-3.8/tty-atmel_serial_probe-index-of-atmel_ports-fix.patch b/queue-3.8/tty-atmel_serial_probe-index-of-atmel_ports-fix.patch
new file mode 100644 (file)
index 0000000..84e5558
--- /dev/null
@@ -0,0 +1,59 @@
+From 503bded92da283b2f31d87e054c4c6d30c3c2340 Mon Sep 17 00:00:00 2001
+From: Pawel Wieczorkiewicz <wpawel@gmail.com>
+Date: Wed, 20 Feb 2013 17:26:20 +0100
+Subject: tty: atmel_serial_probe(): index of atmel_ports[] fix
+
+From: Pawel Wieczorkiewicz <wpawel@gmail.com>
+
+commit 503bded92da283b2f31d87e054c4c6d30c3c2340 upstream.
+
+Index of atmel_ports[ATMEL_MAX_UART] should be smaller
+than ATMEL_MAX_UART.
+
+Signed-off-by: Pawel Wieczorkiewicz <wpawel@gmail.com>
+Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/atmel_serial.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -158,7 +158,7 @@ struct atmel_uart_port {
+ };
+ static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
+-static unsigned long atmel_ports_in_use;
++static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);
+ #ifdef SUPPORT_SYSRQ
+ static struct console atmel_console;
+@@ -1768,15 +1768,14 @@ static int atmel_serial_probe(struct pla
+       if (ret < 0)
+               /* port id not found in platform data nor device-tree aliases:
+                * auto-enumerate it */
+-              ret = find_first_zero_bit(&atmel_ports_in_use,
+-                              sizeof(atmel_ports_in_use));
++              ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART);
+-      if (ret > ATMEL_MAX_UART) {
++      if (ret >= ATMEL_MAX_UART) {
+               ret = -ENODEV;
+               goto err;
+       }
+-      if (test_and_set_bit(ret, &atmel_ports_in_use)) {
++      if (test_and_set_bit(ret, atmel_ports_in_use)) {
+               /* port already in use */
+               ret = -EBUSY;
+               goto err;
+@@ -1856,7 +1855,7 @@ static int atmel_serial_remove(struct pl
+       /* "port" is allocated statically, so we shouldn't free it */
+-      clear_bit(port->line, &atmel_ports_in_use);
++      clear_bit(port->line, atmel_ports_in_use);
+       clk_put(atmel_port->clk);
diff --git a/queue-3.8/usb-ehci-fix-bug-in-itd-sitd-dma-pool-allocation.patch b/queue-3.8/usb-ehci-fix-bug-in-itd-sitd-dma-pool-allocation.patch
new file mode 100644 (file)
index 0000000..dc85334
--- /dev/null
@@ -0,0 +1,86 @@
+From 85ecd0322b9a1a9f451d9150e9460ab42fd17219 Mon Sep 17 00:00:00 2001
+From: Soeren Moch <smoch@web.de>
+Date: Fri, 22 Mar 2013 12:16:52 -0400
+Subject: USB: EHCI: fix bug in iTD/siTD DMA pool allocation
+
+From: Soeren Moch <smoch@web.de>
+
+commit 85ecd0322b9a1a9f451d9150e9460ab42fd17219 upstream.
+
+[Description written by Alan Stern]
+
+Soeren tracked down a very difficult bug in ehci-hcd's DMA pool
+management of iTD and siTD structures.  Some background: ehci-hcd
+gives each isochronous endpoint its own set of active and free itd's
+(or sitd's for full-speed devices).  When a new itd is needed, it is
+taken from the head of the free list, if possible.  However, itd's
+must not be used twice in a single frame because the hardware
+continues to access the data structure for the entire duration of a
+frame.  Therefore if the itd at the head of the free list has its
+"frame" member equal to the current value of ehci->now_frame, it
+cannot be reused and instead a new itd is allocated from the DMA pool.
+The entries on the free list are not released back to the pool until
+the endpoint is no longer in use.
+
+The bug arises from the fact that sometimes an itd can be moved back
+onto the free list before itd->frame has been set properly.  In
+Soeren's case, this happened because ehci-hcd can allocate one more
+itd than it actually needs for an URB; the extra itd may or may not be
+required depending on how the transfer aligns with a frame boundary.
+For example, an URB with 8 isochronous packets will cause two itd's to
+be allocated.  If the URB is scheduled to start in microframe 3 of
+frame N then it will require both itds: one for microframes 3 - 7 of
+frame N and one for microframes 0 - 2 of frame N+1.  But if the URB
+had been scheduled to start in microframe 0 then it would require only
+the first itd, which could cover microframes 0 - 7 of frame N.  The
+second itd would be returned to the end of the free list.
+
+The itd allocation routine initializes the entire structure to 0, so
+the extra itd ends up on the free list with itd->frame set to 0
+instead of a meaningful value.  After a while the itd reaches the head
+of the list, and occasionally this happens when ehci->now_frame is
+equal to 0.  Then, even though it would be okay to reuse this itd, the
+driver thinks it must get another itd from the DMA pool.
+
+For as long as the isochronous endpoint remains in use, this flaw in
+the mechanism causes more and more itd's to be taken slowly from the
+DMA pool.  Since none are released back, the pool eventually becomes
+exhausted.
+
+This reuslts in memory allocation failures, which typically show up
+during a long-running audio stream.  Video might suffer the same
+effect.
+
+The fix is very simple.  To prevent allocations from the pool when
+they aren't needed, make sure that itd's sent back to the free list
+prematurely have itd->frame set to an invalid value which can never be
+equal to ehci->now_frame.
+
+This should be applied to -stable kernels going back to 3.6.
+
+Signed-off-by: Soeren Moch <smoch@web.de>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/ehci-sched.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1214,6 +1214,7 @@ itd_urb_transaction (
+               memset (itd, 0, sizeof *itd);
+               itd->itd_dma = itd_dma;
++              itd->frame = 9999;              /* an invalid value */
+               list_add (&itd->itd_list, &sched->td_list);
+       }
+       spin_unlock_irqrestore (&ehci->lock, flags);
+@@ -1915,6 +1916,7 @@ sitd_urb_transaction (
+               memset (sitd, 0, sizeof *sitd);
+               sitd->sitd_dma = sitd_dma;
++              sitd->frame = 9999;             /* an invalid value */
+               list_add (&sitd->sitd_list, &iso_sched->td_list);
+       }
diff --git a/queue-3.8/usb-ftdi_sio-add-support-for-mitsubishi-fx-usb-aw-bd.patch b/queue-3.8/usb-ftdi_sio-add-support-for-mitsubishi-fx-usb-aw-bd.patch
new file mode 100644 (file)
index 0000000..fd647a4
--- /dev/null
@@ -0,0 +1,49 @@
+From 482b0b5d82bd916cc0c55a2abf65bdc69023b843 Mon Sep 17 00:00:00 2001
+From: Konstantin Holoborodko <klh.kernel@gmail.com>
+Date: Fri, 29 Mar 2013 00:06:13 +0900
+Subject: usb: ftdi_sio: Add support for Mitsubishi FX-USB-AW/-BD
+
+From: Konstantin Holoborodko <klh.kernel@gmail.com>
+
+commit 482b0b5d82bd916cc0c55a2abf65bdc69023b843 upstream.
+
+It enhances the driver for FTDI-based USB serial adapters
+to recognize Mitsubishi Electric Corp. USB/RS422 Converters
+as FT232BM chips and support them.
+https://search.meau.com/?q=FX-USB-AW
+
+Signed-off-by: Konstantin Holoborodko <klh.kernel@gmail.com>
+Tested-by: Konstantin Holoborodko <klh.kernel@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ftdi_sio.c     |    1 +
+ drivers/usb/serial/ftdi_sio_ids.h |    7 +++++++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -642,6 +642,7 @@ static struct usb_device_id id_table_com
+       { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
+       { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
+       { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
++      { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
+       { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
+       { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
+       { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -584,6 +584,13 @@
+ #define CONTEC_COM1USBH_PID   0x8311  /* COM-1(USB)H */
+ /*
++ * Mitsubishi Electric Corp. (http://www.meau.com)
++ * Submitted by Konstantin Holoborodko
++ */
++#define MITSUBISHI_VID                0x06D3
++#define MITSUBISHI_FXUSB_PID  0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
++
++/*
+  * Definitions for B&B Electronics products.
+  */
+ #define BANDB_VID             0x0856  /* B&B Electronics Vendor ID */
diff --git a/queue-3.8/usb-xhci-fix-trb-transfer-length-macro-used-for-event-trb.patch b/queue-3.8/usb-xhci-fix-trb-transfer-length-macro-used-for-event-trb.patch
new file mode 100644 (file)
index 0000000..365eeb8
--- /dev/null
@@ -0,0 +1,131 @@
+From 1c11a172cb30492f5f6a82c6e118fdcd9946c34f Mon Sep 17 00:00:00 2001
+From: Vivek Gautam <gautam.vivek@samsung.com>
+Date: Thu, 21 Mar 2013 12:06:48 +0530
+Subject: usb: xhci: Fix TRB transfer length macro used for Event TRB.
+
+From: Vivek Gautam <gautam.vivek@samsung.com>
+
+commit 1c11a172cb30492f5f6a82c6e118fdcd9946c34f upstream.
+
+Use proper macro while extracting TRB transfer length from
+Transfer event TRBs. Adding a macro EVENT_TRB_LEN (bits 0:23)
+for the same, and use it instead of TRB_LEN (bits 0:16) in
+case of event TRBs.
+
+This patch should be backported to kernels as old as 2.6.31, that
+contain the commit b10de142119a676552df3f0d2e3a9d647036c26a "USB: xhci:
+Bulk transfer support".  This patch will have issues applying to older
+kernels.
+
+Signed-off-by: Vivek gautam <gautam.vivek@samsung.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c |   24 ++++++++++++------------
+ drivers/usb/host/xhci.h      |    4 ++++
+ 2 files changed, 16 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2027,8 +2027,8 @@ static int process_ctrl_td(struct xhci_h
+               if (event_trb != ep_ring->dequeue &&
+                               event_trb != td->last_trb)
+                       td->urb->actual_length =
+-                              td->urb->transfer_buffer_length
+-                              - TRB_LEN(le32_to_cpu(event->transfer_len));
++                              td->urb->transfer_buffer_length -
++                              EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+               else
+                       td->urb->actual_length = 0;
+@@ -2060,7 +2060,7 @@ static int process_ctrl_td(struct xhci_h
+               /* Maybe the event was for the data stage? */
+                       td->urb->actual_length =
+                               td->urb->transfer_buffer_length -
+-                              TRB_LEN(le32_to_cpu(event->transfer_len));
++                              EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+                       xhci_dbg(xhci, "Waiting for status "
+                                       "stage event\n");
+                       return 0;
+@@ -2096,7 +2096,7 @@ static int process_isoc_td(struct xhci_h
+       /* handle completion code */
+       switch (trb_comp_code) {
+       case COMP_SUCCESS:
+-              if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
++              if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+                       frame->status = 0;
+                       break;
+               }
+@@ -2141,7 +2141,7 @@ static int process_isoc_td(struct xhci_h
+                               len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
+               }
+               len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+-                      TRB_LEN(le32_to_cpu(event->transfer_len));
++                      EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+               if (trb_comp_code != COMP_STOP_INVAL) {
+                       frame->actual_length = len;
+@@ -2199,7 +2199,7 @@ static int process_bulk_intr_td(struct x
+       case COMP_SUCCESS:
+               /* Double check that the HW transferred everything. */
+               if (event_trb != td->last_trb ||
+-                              TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
++                  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+                       xhci_warn(xhci, "WARN Successful completion "
+                                       "on short TX\n");
+                       if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+@@ -2227,18 +2227,18 @@ static int process_bulk_intr_td(struct x
+                               "%d bytes untransferred\n",
+                               td->urb->ep->desc.bEndpointAddress,
+                               td->urb->transfer_buffer_length,
+-                              TRB_LEN(le32_to_cpu(event->transfer_len)));
++                              EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+       /* Fast path - was this the last TRB in the TD for this URB? */
+       if (event_trb == td->last_trb) {
+-              if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
++              if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+                       td->urb->actual_length =
+                               td->urb->transfer_buffer_length -
+-                              TRB_LEN(le32_to_cpu(event->transfer_len));
++                              EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+                       if (td->urb->transfer_buffer_length <
+                                       td->urb->actual_length) {
+                               xhci_warn(xhci, "HC gave bad length "
+                                               "of %d bytes left\n",
+-                                        TRB_LEN(le32_to_cpu(event->transfer_len)));
++                                        EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+                               td->urb->actual_length = 0;
+                               if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+                                       *status = -EREMOTEIO;
+@@ -2280,7 +2280,7 @@ static int process_bulk_intr_td(struct x
+               if (trb_comp_code != COMP_STOP_INVAL)
+                       td->urb->actual_length +=
+                               TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+-                              TRB_LEN(le32_to_cpu(event->transfer_len));
++                              EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+       }
+       return finish_td(xhci, td, event_trb, event, ep, status, false);
+@@ -2368,7 +2368,7 @@ static int handle_tx_event(struct xhci_h
+        * transfer type
+        */
+       case COMP_SUCCESS:
+-              if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
++              if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+                       break;
+               if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+                       trb_comp_code = COMP_SHORT_TX;
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -972,6 +972,10 @@ struct xhci_transfer_event {
+       __le32  flags;
+ };
++/* Transfer event TRB length bit mask */
++/* bits 0:23 */
++#define       EVENT_TRB_LEN(p)                ((p) & 0xffffff)
++
+ /** Transfer Event bit fields **/
+ #define       TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f)
diff --git a/queue-3.8/vt-synchronize_rcu-under-spinlock-is-not-nice.patch b/queue-3.8/vt-synchronize_rcu-under-spinlock-is-not-nice.patch
new file mode 100644 (file)
index 0000000..7085ea7
--- /dev/null
@@ -0,0 +1,45 @@
+From e8cd81693bbbb15db57d3c9aa7dd90eda4842874 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 26 Mar 2013 20:30:17 -0400
+Subject: vt: synchronize_rcu() under spinlock is not nice...
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit e8cd81693bbbb15db57d3c9aa7dd90eda4842874 upstream.
+
+vcs_poll_data_free() calls unregister_vt_notifier(), which calls
+atomic_notifier_chain_unregister(), which calls synchronize_rcu().
+Do it *after* we'd dropped ->f_lock.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/vc_screen.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/vt/vc_screen.c
++++ b/drivers/tty/vt/vc_screen.c
+@@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data
+ static struct vcs_poll_data *
+ vcs_poll_data_get(struct file *file)
+ {
+-      struct vcs_poll_data *poll = file->private_data;
++      struct vcs_poll_data *poll = file->private_data, *kill = NULL;
+       if (poll)
+               return poll;
+@@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file)
+               file->private_data = poll;
+       } else {
+               /* someone else raced ahead of us */
+-              vcs_poll_data_free(poll);
++              kill = poll;
+               poll = file->private_data;
+       }
+       spin_unlock(&file->f_lock);
++      if (kill)
++              vcs_poll_data_free(kill);
+       return poll;
+ }
diff --git a/queue-3.8/xen-blkback-correctly-respond-to-unknown-non-native-requests.patch b/queue-3.8/xen-blkback-correctly-respond-to-unknown-non-native-requests.patch
new file mode 100644 (file)
index 0000000..798eefa
--- /dev/null
@@ -0,0 +1,177 @@
+From 0e367ae46503cfe7791460c8ba8434a5d60b2bd5 Mon Sep 17 00:00:00 2001
+From: David Vrabel <david.vrabel@citrix.com>
+Date: Thu, 7 Mar 2013 17:32:01 +0000
+Subject: xen/blkback: correctly respond to unknown, non-native requests
+
+From: David Vrabel <david.vrabel@citrix.com>
+
+commit 0e367ae46503cfe7791460c8ba8434a5d60b2bd5 upstream.
+
+If the frontend is using a non-native protocol (e.g., a 64-bit
+frontend with a 32-bit backend) and it sent an unrecognized request,
+the request was not translated and the response would have the
+incorrect ID.  This may cause the frontend driver to behave
+incorrectly or crash.
+
+Since the ID field in the request is always in the same place,
+regardless of the request type we can get the correct ID and make a
+valid response (which will report BLKIF_RSP_EOPNOTSUPP).
+
+This bug affected 64-bit SLES 11 guests when using a 32-bit backend.
+This guest does a BLKIF_OP_RESERVED_1 (BLKIF_OP_PACKET in the SLES
+source) and would crash in blkif_int() as the ID in the response would
+be invalid.
+
+Signed-off-by: David Vrabel <david.vrabel@citrix.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/xen-blkback/blkback.c |   31 +++++++++++++++++++++++++++----
+ drivers/block/xen-blkback/common.h  |   25 +++++++++++++++++++++++++
+ include/xen/interface/io/blkif.h    |   10 ++++++++++
+ 3 files changed, 62 insertions(+), 4 deletions(-)
+
+--- a/drivers/block/xen-blkback/blkback.c
++++ b/drivers/block/xen-blkback/blkback.c
+@@ -679,6 +679,16 @@ static int dispatch_discard_io(struct xe
+       return err;
+ }
++static int dispatch_other_io(struct xen_blkif *blkif,
++                           struct blkif_request *req,
++                           struct pending_req *pending_req)
++{
++      free_req(pending_req);
++      make_response(blkif, req->u.other.id, req->operation,
++                    BLKIF_RSP_EOPNOTSUPP);
++      return -EIO;
++}
++
+ static void xen_blk_drain_io(struct xen_blkif *blkif)
+ {
+       atomic_set(&blkif->drain, 1);
+@@ -800,17 +810,30 @@ __do_block_io_op(struct xen_blkif *blkif
+               /* Apply all sanity checks to /private copy/ of request. */
+               barrier();
+-              if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
++
++              switch (req.operation) {
++              case BLKIF_OP_READ:
++              case BLKIF_OP_WRITE:
++              case BLKIF_OP_WRITE_BARRIER:
++              case BLKIF_OP_FLUSH_DISKCACHE:
++                      if (dispatch_rw_block_io(blkif, &req, pending_req))
++                              goto done;
++                      break;
++              case BLKIF_OP_DISCARD:
+                       free_req(pending_req);
+                       if (dispatch_discard_io(blkif, &req))
+-                              break;
+-              } else if (dispatch_rw_block_io(blkif, &req, pending_req))
++                              goto done;
+                       break;
++              default:
++                      if (dispatch_other_io(blkif, &req, pending_req))
++                              goto done;
++                      break;
++              }
+               /* Yield point for this unbounded loop. */
+               cond_resched();
+       }
+-
++done:
+       return more_to_do;
+ }
+--- a/drivers/block/xen-blkback/common.h
++++ b/drivers/block/xen-blkback/common.h
+@@ -77,11 +77,18 @@ struct blkif_x86_32_request_discard {
+       uint64_t       nr_sectors;
+ } __attribute__((__packed__));
++struct blkif_x86_32_request_other {
++      uint8_t        _pad1;
++      blkif_vdev_t   _pad2;
++      uint64_t       id;           /* private guest value, echoed in resp  */
++} __attribute__((__packed__));
++
+ struct blkif_x86_32_request {
+       uint8_t        operation;    /* BLKIF_OP_???                         */
+       union {
+               struct blkif_x86_32_request_rw rw;
+               struct blkif_x86_32_request_discard discard;
++              struct blkif_x86_32_request_other other;
+       } u;
+ } __attribute__((__packed__));
+@@ -113,11 +120,19 @@ struct blkif_x86_64_request_discard {
+       uint64_t       nr_sectors;
+ } __attribute__((__packed__));
++struct blkif_x86_64_request_other {
++      uint8_t        _pad1;
++      blkif_vdev_t   _pad2;
++      uint32_t       _pad3;        /* offsetof(blkif_..,u.discard.id)==8   */
++      uint64_t       id;           /* private guest value, echoed in resp  */
++} __attribute__((__packed__));
++
+ struct blkif_x86_64_request {
+       uint8_t        operation;    /* BLKIF_OP_???                         */
+       union {
+               struct blkif_x86_64_request_rw rw;
+               struct blkif_x86_64_request_discard discard;
++              struct blkif_x86_64_request_other other;
+       } u;
+ } __attribute__((__packed__));
+@@ -278,6 +293,11 @@ static inline void blkif_get_x86_32_req(
+               dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+               break;
+       default:
++              /*
++               * Don't know how to translate this op. Only get the
++               * ID so failure can be reported to the frontend.
++               */
++              dst->u.other.id = src->u.other.id;
+               break;
+       }
+ }
+@@ -309,6 +329,11 @@ static inline void blkif_get_x86_64_req(
+               dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+               break;
+       default:
++              /*
++               * Don't know how to translate this op. Only get the
++               * ID so failure can be reported to the frontend.
++               */
++              dst->u.other.id = src->u.other.id;
+               break;
+       }
+ }
+--- a/include/xen/interface/io/blkif.h
++++ b/include/xen/interface/io/blkif.h
+@@ -138,11 +138,21 @@ struct blkif_request_discard {
+       uint8_t        _pad3;
+ } __attribute__((__packed__));
++struct blkif_request_other {
++      uint8_t      _pad1;
++      blkif_vdev_t _pad2;        /* only for read/write requests         */
++#ifdef CONFIG_X86_64
++      uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
++#endif
++      uint64_t     id;           /* private guest value, echoed in resp  */
++} __attribute__((__packed__));
++
+ struct blkif_request {
+       uint8_t        operation;    /* BLKIF_OP_???                         */
+       union {
+               struct blkif_request_rw rw;
+               struct blkif_request_discard discard;
++              struct blkif_request_other other;
+       } u;
+ } __attribute__((__packed__));
diff --git a/queue-3.8/xen-blkback-fix-dispatch_rw_block_io-error-path.patch b/queue-3.8/xen-blkback-fix-dispatch_rw_block_io-error-path.patch
new file mode 100644 (file)
index 0000000..6f06558
--- /dev/null
@@ -0,0 +1,49 @@
+From 0e5e098ac22dae38f957e951b70d3cf73beff0f7 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <JBeulich@suse.com>
+Date: Mon, 11 Mar 2013 09:39:55 +0000
+Subject: xen-blkback: fix dispatch_rw_block_io() error path
+
+From: Jan Beulich <JBeulich@suse.com>
+
+commit 0e5e098ac22dae38f957e951b70d3cf73beff0f7 upstream.
+
+Commit 7708992 ("xen/blkback: Seperate the bio allocation and the bio
+submission") consolidated the pendcnt updates to just a single write,
+neglecting the fact that the error path relied on it getting set to 1
+up front (such that the decrement in __end_block_io_op() would actually
+drop the count to zero, triggering the necessary cleanup actions).
+
+Also remove a misleading and a stale (after said commit) comment.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/xen-blkback/blkback.c |    7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- a/drivers/block/xen-blkback/blkback.c
++++ b/drivers/block/xen-blkback/blkback.c
+@@ -1001,13 +1001,7 @@ static int dispatch_rw_block_io(struct x
+               bio->bi_end_io  = end_block_io_op;
+       }
+-      /*
+-       * We set it one so that the last submit_bio does not have to call
+-       * atomic_inc.
+-       */
+       atomic_set(&pending_req->pendcnt, nbio);
+-
+-      /* Get a reference count for the disk queue and start sending I/O */
+       blk_start_plug(&plug);
+       for (i = 0; i < nbio; i++)
+@@ -1035,6 +1029,7 @@ static int dispatch_rw_block_io(struct x
+  fail_put_bio:
+       for (i = 0; i < nbio; i++)
+               bio_put(biolist[i]);
++      atomic_set(&pending_req->pendcnt, 1);
+       __end_block_io_op(pending_req, -EINVAL);
+       msleep(1); /* back off a bit */
+       return -EIO;
diff --git a/queue-3.8/xen-blkfront-switch-from-llist-to-list.patch b/queue-3.8/xen-blkfront-switch-from-llist-to-list.patch
new file mode 100644 (file)
index 0000000..8d35a7e
--- /dev/null
@@ -0,0 +1,133 @@
+From 155b7edb51430a280f86c1e21b7be308b0d219d4 Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Mon, 18 Mar 2013 17:49:34 +0100
+Subject: xen-blkfront: switch from llist to list
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+commit 155b7edb51430a280f86c1e21b7be308b0d219d4 upstream.
+
+The git commit f84adf4921ae3115502f44ff467b04bf2f88cf04
+(xen-blkfront: drop the use of llist_for_each_entry_safe)
+
+was a stop-gate to fix a GCC4.1 bug. The appropiate way
+is to actually use an list instead of using an llist.
+
+As such this patch replaces the usage of llist with an
+list.
+
+Since we always manipulate the list while holding the io_lock, there's
+no need for additional locking (llist used previously is safe to use
+concurrently without additional locking).
+
+Signed-off-by: Roger Pau MonnĂ© <roger.pau@citrix.com>
+[v1: Redid the git commit description]
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/xen-blkfront.c |   41 ++++++++++++++++++-----------------------
+ 1 file changed, 18 insertions(+), 23 deletions(-)
+
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -44,7 +44,7 @@
+ #include <linux/mutex.h>
+ #include <linux/scatterlist.h>
+ #include <linux/bitmap.h>
+-#include <linux/llist.h>
++#include <linux/list.h>
+ #include <xen/xen.h>
+ #include <xen/xenbus.h>
+@@ -68,7 +68,7 @@ enum blkif_state {
+ struct grant {
+       grant_ref_t gref;
+       unsigned long pfn;
+-      struct llist_node node;
++      struct list_head node;
+ };
+ struct blk_shadow {
+@@ -105,7 +105,7 @@ struct blkfront_info
+       struct work_struct work;
+       struct gnttab_free_callback callback;
+       struct blk_shadow shadow[BLK_RING_SIZE];
+-      struct llist_head persistent_gnts;
++      struct list_head persistent_gnts;
+       unsigned int persistent_gnts_c;
+       unsigned long shadow_free;
+       unsigned int feature_flush;
+@@ -371,10 +371,11 @@ static int blkif_queue_request(struct re
+                       lsect = fsect + (sg->length >> 9) - 1;
+                       if (info->persistent_gnts_c) {
+-                              BUG_ON(llist_empty(&info->persistent_gnts));
+-                              gnt_list_entry = llist_entry(
+-                                      llist_del_first(&info->persistent_gnts),
+-                                      struct grant, node);
++                              BUG_ON(list_empty(&info->persistent_gnts));
++                              gnt_list_entry = list_first_entry(
++                                                    &info->persistent_gnts,
++                                                    struct grant, node);
++                              list_del(&gnt_list_entry->node);
+                               ref = gnt_list_entry->gref;
+                               buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn);
+@@ -790,9 +791,8 @@ static void blkif_restart_queue(struct w
+ static void blkif_free(struct blkfront_info *info, int suspend)
+ {
+-      struct llist_node *all_gnts;
+-      struct grant *persistent_gnt, *tmp;
+-      struct llist_node *n;
++      struct grant *persistent_gnt;
++      struct grant *n;
+       /* Prevent new requests being issued until we fix things up. */
+       spin_lock_irq(&info->io_lock);
+@@ -804,20 +804,15 @@ static void blkif_free(struct blkfront_i
+       /* Remove all persistent grants */
+       if (info->persistent_gnts_c) {
+-              all_gnts = llist_del_all(&info->persistent_gnts);
+-              persistent_gnt = llist_entry(all_gnts, typeof(*(persistent_gnt)), node);
+-              while (persistent_gnt) {
++              list_for_each_entry_safe(persistent_gnt, n,
++                                       &info->persistent_gnts, node) {
++                      list_del(&persistent_gnt->node);
+                       gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
+                       __free_page(pfn_to_page(persistent_gnt->pfn));
+-                      tmp = persistent_gnt;
+-                      n = persistent_gnt->node.next;
+-                      if (n)
+-                              persistent_gnt = llist_entry(n, typeof(*(persistent_gnt)), node);
+-                      else
+-                              persistent_gnt = NULL;
+-                      kfree(tmp);
++                      kfree(persistent_gnt);
++                      info->persistent_gnts_c--;
+               }
+-              info->persistent_gnts_c = 0;
++              BUG_ON(info->persistent_gnts_c != 0);
+       }
+       /* No more gnttab callback work. */
+@@ -875,7 +870,7 @@ static void blkif_completion(struct blk_
+       }
+       /* Add the persistent grant into the list of free grants */
+       for (i = 0; i < s->req.u.rw.nr_segments; i++) {
+-              llist_add(&s->grants_used[i]->node, &info->persistent_gnts);
++              list_add(&s->grants_used[i]->node, &info->persistent_gnts);
+               info->persistent_gnts_c++;
+       }
+ }
+@@ -1171,7 +1166,7 @@ static int blkfront_probe(struct xenbus_
+       spin_lock_init(&info->io_lock);
+       info->xbdev = dev;
+       info->vdevice = vdevice;
+-      init_llist_head(&info->persistent_gnts);
++      INIT_LIST_HEAD(&info->persistent_gnts);
+       info->persistent_gnts_c = 0;
+       info->connected = BLKIF_STATE_DISCONNECTED;
+       INIT_WORK(&info->work, blkif_restart_queue);
diff --git a/queue-3.8/xen-pciback-notify-hypervisor-about-devices-intended-to-be-assigned-to-guests.patch b/queue-3.8/xen-pciback-notify-hypervisor-about-devices-intended-to-be-assigned-to-guests.patch
new file mode 100644 (file)
index 0000000..32fc28c
--- /dev/null
@@ -0,0 +1,178 @@
+From 909b3fdb0dd4f3db07b2d75425a00a2adb551383 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <JBeulich@suse.com>
+Date: Tue, 12 Mar 2013 15:06:23 +0000
+Subject: xen-pciback: notify hypervisor about devices intended to be assigned to guests
+
+From: Jan Beulich <JBeulich@suse.com>
+
+commit 909b3fdb0dd4f3db07b2d75425a00a2adb551383 upstream.
+
+For MSI-X capable devices the hypervisor wants to write protect the
+MSI-X table and PBA, yet it can't assume that resources have been
+assigned to their final values at device enumeration time. Thus have
+pciback do that notification, as having the device controlled by it is
+a prerequisite to assigning the device to guests anyway.
+
+This is the kernel part of hypervisor side commit 4245d33 ("x86/MSI:
+add mechanism to fully protect MSI-X table from PV guest accesses") on
+the master branch of git://xenbits.xen.org/xen.git.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/xen/hypercall.h |    4 +-
+ drivers/xen/fallback.c               |    3 +
+ drivers/xen/xen-pciback/pci_stub.c   |   59 ++++++++++++++++++++++++++---------
+ include/xen/interface/physdev.h      |    6 +++
+ 4 files changed, 54 insertions(+), 18 deletions(-)
+
+--- a/arch/x86/include/asm/xen/hypercall.h
++++ b/arch/x86/include/asm/xen/hypercall.h
+@@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count
+       return _hypercall3(int, console_io, cmd, count, str);
+ }
+-extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
++extern int __must_check xen_physdev_op_compat(int, void *);
+ static inline int
+ HYPERVISOR_physdev_op(int cmd, void *arg)
+ {
+       int rc = _hypercall2(int, physdev_op, cmd, arg);
+       if (unlikely(rc == -ENOSYS))
+-              rc = HYPERVISOR_physdev_op_compat(cmd, arg);
++              rc = xen_physdev_op_compat(cmd, arg);
+       return rc;
+ }
+--- a/drivers/xen/fallback.c
++++ b/drivers/xen/fallback.c
+@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd,
+ }
+ EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
+-int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
++int xen_physdev_op_compat(int cmd, void *arg)
+ {
+       struct physdev_op op;
+       int rc;
+@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd
+       return rc;
+ }
++EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
+--- a/drivers/xen/xen-pciback/pci_stub.c
++++ b/drivers/xen/xen-pciback/pci_stub.c
+@@ -17,6 +17,7 @@
+ #include <xen/events.h>
+ #include <asm/xen/pci.h>
+ #include <asm/xen/hypervisor.h>
++#include <xen/interface/physdev.h>
+ #include "pciback.h"
+ #include "conf_space.h"
+ #include "conf_space_quirks.h"
+@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_de
+ static void pcistub_device_release(struct kref *kref)
+ {
+       struct pcistub_device *psdev;
++      struct pci_dev *dev;
+       struct xen_pcibk_dev_data *dev_data;
+       psdev = container_of(kref, struct pcistub_device, kref);
+-      dev_data = pci_get_drvdata(psdev->dev);
++      dev = psdev->dev;
++      dev_data = pci_get_drvdata(dev);
+-      dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
++      dev_dbg(&dev->dev, "pcistub_device_release\n");
+-      xen_unregister_device_domain_owner(psdev->dev);
++      xen_unregister_device_domain_owner(dev);
+       /* Call the reset function which does not take lock as this
+        * is called from "unbind" which takes a device_lock mutex.
+        */
+-      __pci_reset_function_locked(psdev->dev);
+-      if (pci_load_and_free_saved_state(psdev->dev,
+-                                        &dev_data->pci_saved_state)) {
+-              dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n");
+-      } else
+-              pci_restore_state(psdev->dev);
++      __pci_reset_function_locked(dev);
++      if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
++              dev_dbg(&dev->dev, "Could not reload PCI state\n");
++      else
++              pci_restore_state(dev);
++
++      if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
++              struct physdev_pci_device ppdev = {
++                      .seg = pci_domain_nr(dev->bus),
++                      .bus = dev->bus->number,
++                      .devfn = dev->devfn
++              };
++              int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix,
++                                              &ppdev);
++
++              if (err)
++                      dev_warn(&dev->dev, "MSI-X release failed (%d)\n",
++                               err);
++      }
+       /* Disable the device */
+-      xen_pcibk_reset_device(psdev->dev);
++      xen_pcibk_reset_device(dev);
+       kfree(dev_data);
+-      pci_set_drvdata(psdev->dev, NULL);
++      pci_set_drvdata(dev, NULL);
+       /* Clean-up the device */
+-      xen_pcibk_config_free_dyn_fields(psdev->dev);
+-      xen_pcibk_config_free_dev(psdev->dev);
++      xen_pcibk_config_free_dyn_fields(dev);
++      xen_pcibk_config_free_dev(dev);
+-      psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
+-      pci_dev_put(psdev->dev);
++      dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
++      pci_dev_put(dev);
+       kfree(psdev);
+ }
+@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pc
+       if (err)
+               goto config_release;
++      if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
++              struct physdev_pci_device ppdev = {
++                      .seg = pci_domain_nr(dev->bus),
++                      .bus = dev->bus->number,
++                      .devfn = dev->devfn
++              };
++
++              err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev);
++              if (err)
++                      dev_err(&dev->dev, "MSI-X preparation failed (%d)\n",
++                              err);
++      }
++
+       /* We need the device active to save the state. */
+       dev_dbg(&dev->dev, "save state of device\n");
+       pci_save_state(dev);
+--- a/include/xen/interface/physdev.h
++++ b/include/xen/interface/physdev.h
+@@ -251,6 +251,12 @@ struct physdev_pci_device_add {
+ #define PHYSDEVOP_pci_device_remove     26
+ #define PHYSDEVOP_restore_msi_ext       27
++/*
++ * Dom0 should use these two to announce MMIO resources assigned to
++ * MSI-X capable devices won't (prepare) or may (release) change.
++ */
++#define PHYSDEVOP_prepare_msix          30
++#define PHYSDEVOP_release_msix          31
+ struct physdev_pci_device {
+     /* IN */
+     uint16_t seg;