--- /dev/null
+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");
+
--- /dev/null
+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);
--- /dev/null
+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)
+ /*
--- /dev/null
+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:
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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))
--- /dev/null
+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);
+ }
+
+ /*
--- /dev/null
+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) {
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
--- /dev/null
+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);
+
--- /dev/null
+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);
+ }
+
--- /dev/null
+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 */
--- /dev/null
+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)
+
--- /dev/null
+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;
+ }
--- /dev/null
+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__));
+
--- /dev/null
+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;
--- /dev/null
+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);
--- /dev/null
+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;