--- /dev/null
+From 096f41d3a8fcbb8dde7f71379b1ca85fe213eded Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Thu, 13 Apr 2017 18:35:59 +0800
+Subject: af_key: Fix sadb_x_ipsecrequest parsing
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit 096f41d3a8fcbb8dde7f71379b1ca85fe213eded upstream.
+
+The parsing of sadb_x_ipsecrequest is broken in a number of ways.
+First of all we're not verifying sadb_x_ipsecrequest_len. This
+is needed when the structure carries addresses at the end. Worse
+we don't even look at the length when we parse those optional
+addresses.
+
+The migration code had similar parsing code that's better but
+it also has some deficiencies. The length is overcounted first
+of all as it includes the header itself. It also fails to check
+the length before dereferencing the sa_family field.
+
+This patch fixes those problems in parse_sockaddr_pair and then
+uses it in parse_ipsecrequest.
+
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/key/af_key.c | 47 ++++++++++++++++++++++++++---------------------
+ 1 file changed, 26 insertions(+), 21 deletions(-)
+
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -65,6 +65,10 @@ struct pfkey_sock {
+ } dump;
+ };
+
++static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
++ xfrm_address_t *saddr, xfrm_address_t *daddr,
++ u16 *family);
++
+ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+ {
+ return (struct pfkey_sock *)sk;
+@@ -1922,19 +1926,14 @@ parse_ipsecrequest(struct xfrm_policy *x
+
+ /* addresses present only in tunnel mode */
+ if (t->mode == XFRM_MODE_TUNNEL) {
+- u8 *sa = (u8 *) (rq + 1);
+- int family, socklen;
++ int err;
+
+- family = pfkey_sockaddr_extract((struct sockaddr *)sa,
+- &t->saddr);
+- if (!family)
+- return -EINVAL;
+-
+- socklen = pfkey_sockaddr_len(family);
+- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
+- &t->id.daddr) != family)
+- return -EINVAL;
+- t->encap_family = family;
++ err = parse_sockaddr_pair(
++ (struct sockaddr *)(rq + 1),
++ rq->sadb_x_ipsecrequest_len - sizeof(*rq),
++ &t->saddr, &t->id.daddr, &t->encap_family);
++ if (err)
++ return err;
+ } else
+ t->encap_family = xp->family;
+
+@@ -1954,7 +1953,11 @@ parse_ipsecrequests(struct xfrm_policy *
+ if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
+ return -EINVAL;
+
+- while (len >= sizeof(struct sadb_x_ipsecrequest)) {
++ while (len >= sizeof(*rq)) {
++ if (len < rq->sadb_x_ipsecrequest_len ||
++ rq->sadb_x_ipsecrequest_len < sizeof(*rq))
++ return -EINVAL;
++
+ if ((err = parse_ipsecrequest(xp, rq)) < 0)
+ return err;
+ len -= rq->sadb_x_ipsecrequest_len;
+@@ -2417,7 +2420,6 @@ out:
+ return err;
+ }
+
+-#ifdef CONFIG_NET_KEY_MIGRATE
+ static int pfkey_sockaddr_pair_size(sa_family_t family)
+ {
+ return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
+@@ -2429,7 +2431,7 @@ static int parse_sockaddr_pair(struct so
+ {
+ int af, socklen;
+
+- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
++ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
+ return -EINVAL;
+
+ af = pfkey_sockaddr_extract(sa, saddr);
+@@ -2445,6 +2447,7 @@ static int parse_sockaddr_pair(struct so
+ return 0;
+ }
+
++#ifdef CONFIG_NET_KEY_MIGRATE
+ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
+ struct xfrm_migrate *m)
+ {
+@@ -2452,13 +2455,14 @@ static int ipsecrequests_to_migrate(stru
+ struct sadb_x_ipsecrequest *rq2;
+ int mode;
+
+- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
+- len < rq1->sadb_x_ipsecrequest_len)
++ if (len < sizeof(*rq1) ||
++ len < rq1->sadb_x_ipsecrequest_len ||
++ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
+ return -EINVAL;
+
+ /* old endoints */
+ err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
+- rq1->sadb_x_ipsecrequest_len,
++ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
+ &m->old_saddr, &m->old_daddr,
+ &m->old_family);
+ if (err)
+@@ -2467,13 +2471,14 @@ static int ipsecrequests_to_migrate(stru
+ rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
+ len -= rq1->sadb_x_ipsecrequest_len;
+
+- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
+- len < rq2->sadb_x_ipsecrequest_len)
++ if (len <= sizeof(*rq2) ||
++ len < rq2->sadb_x_ipsecrequest_len ||
++ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
+ return -EINVAL;
+
+ /* new endpoints */
+ err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
+- rq2->sadb_x_ipsecrequest_len,
++ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
+ &m->new_saddr, &m->new_daddr,
+ &m->new_family);
+ if (err)
--- /dev/null
+From 3c5ab3f395d66a9e4e937fcfdf6ebc63894f028b Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Sat, 29 Apr 2017 20:33:09 +0300
+Subject: ipvs: SNAT packet replies only for NATed connections
+
+From: Julian Anastasov <ja@ssi.bg>
+
+commit 3c5ab3f395d66a9e4e937fcfdf6ebc63894f028b upstream.
+
+We do not check if packet from real server is for NAT
+connection before performing SNAT. This causes problems
+for setups that use DR/TUN and allow local clients to
+access the real server directly, for example:
+
+- local client in director creates IPVS-DR/TUN connection
+CIP->VIP and the request packets are routed to RIP.
+Talks are finished but IPVS connection is not expired yet.
+
+- second local client creates non-IPVS connection CIP->RIP
+with same reply tuple RIP->CIP and when replies are received
+on LOCAL_IN we wrongly assign them for the first client
+connection because RIP->CIP matches the reply direction.
+As result, IPVS SNATs replies for non-IPVS connections.
+
+The problem is more visible to local UDP clients but in rare
+cases it can happen also for TCP or remote clients when the
+real server sends the reply traffic via the director.
+
+So, better to be more precise for the reply traffic.
+As replies are not expected for DR/TUN connections, better
+to not touch them.
+
+Reported-by: Nick Moriarty <nick.moriarty@york.ac.uk>
+Tested-by: Nick Moriarty <nick.moriarty@york.ac.uk>
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/ipvs/ip_vs_core.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -849,10 +849,8 @@ static int handle_response_icmp(int af,
+ {
+ unsigned int verdict = NF_DROP;
+
+- if (IP_VS_FWD_METHOD(cp) != 0) {
+- pr_err("shouldn't reach here, because the box is on the "
+- "half connection in the tun/dr module.\n");
+- }
++ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
++ goto ignore_cp;
+
+ /* Ensure the checksum is correct */
+ if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
+@@ -886,6 +884,8 @@ static int handle_response_icmp(int af,
+ ip_vs_notrack(skb);
+ else
+ ip_vs_update_conntrack(skb, cp, 0);
++
++ignore_cp:
+ verdict = NF_ACCEPT;
+
+ out:
+@@ -1385,8 +1385,11 @@ ip_vs_out(struct netns_ipvs *ipvs, unsig
+ */
+ cp = pp->conn_out_get(ipvs, af, skb, &iph);
+
+- if (likely(cp))
++ if (likely(cp)) {
++ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
++ goto ignore_cp;
+ return handle_response(af, skb, pd, cp, &iph, hooknum);
++ }
+
+ /* Check for real-server-started requests */
+ if (atomic_read(&ipvs->conn_out_counter)) {
+@@ -1444,9 +1447,15 @@ ip_vs_out(struct netns_ipvs *ipvs, unsig
+ }
+ }
+ }
++
++out:
+ IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
+ "ip_vs_out: packet continues traversal as normal");
+ return NF_ACCEPT;
++
++ignore_cp:
++ __ip_vs_conn_put(cp);
++ goto out;
+ }
+
+ /*
--- /dev/null
+From f9c79bc05a2a91f4fba8bfd653579e066714b1ec Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Wed, 7 Jun 2017 19:05:31 -0400
+Subject: md: don't use flush_signals in userspace processes
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit f9c79bc05a2a91f4fba8bfd653579e066714b1ec upstream.
+
+The function flush_signals clears all pending signals for the process. It
+may be used by kernel threads when we need to prepare a kernel thread for
+responding to signals. However using this function for an userspaces
+processes is incorrect - clearing signals without the program expecting it
+can cause misbehavior.
+
+The raid1 and raid5 code uses flush_signals in its request routine because
+it wants to prepare for an interruptible wait. This patch drops
+flush_signals and uses sigprocmask instead to block all signals (including
+SIGKILL) around the schedule() call. The signals are not lost, but the
+schedule() call won't respond to them.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Shaohua Li <shli@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/raid1.c | 5 ++++-
+ drivers/md/raid5.c | 5 ++++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1073,7 +1073,7 @@ static void raid1_make_request(struct md
+ */
+ DEFINE_WAIT(w);
+ for (;;) {
+- flush_signals(current);
++ sigset_t full, old;
+ prepare_to_wait(&conf->wait_barrier,
+ &w, TASK_INTERRUPTIBLE);
+ if (bio_end_sector(bio) <= mddev->suspend_lo ||
+@@ -1082,7 +1082,10 @@ static void raid1_make_request(struct md
+ !md_cluster_ops->area_resyncing(mddev, WRITE,
+ bio->bi_iter.bi_sector, bio_end_sector(bio))))
+ break;
++ sigfillset(&full);
++ sigprocmask(SIG_BLOCK, &full, &old);
+ schedule();
++ sigprocmask(SIG_SETMASK, &old, NULL);
+ }
+ finish_wait(&conf->wait_barrier, &w);
+ }
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -5300,12 +5300,15 @@ static void raid5_make_request(struct md
+ * userspace, we want an interruptible
+ * wait.
+ */
+- flush_signals(current);
+ prepare_to_wait(&conf->wait_for_overlap,
+ &w, TASK_INTERRUPTIBLE);
+ if (logical_sector >= mddev->suspend_lo &&
+ logical_sector < mddev->suspend_hi) {
++ sigset_t full, old;
++ sigfillset(&full);
++ sigprocmask(SIG_BLOCK, &full, &old);
+ schedule();
++ sigprocmask(SIG_SETMASK, &old, NULL);
+ do_prepare = true;
+ }
+ goto retry;
--- /dev/null
+From d90b336f3f652ff0441e631a06236f785581c8f7 Mon Sep 17 00:00:00 2001
+From: Devin Heitmueller <dheitmueller@kernellabs.com>
+Date: Fri, 21 Apr 2017 13:28:37 -0300
+Subject: [media] mxl111sf: Fix driver to use heap allocate buffers for USB messages
+
+From: Devin Heitmueller <dheitmueller@kernellabs.com>
+
+commit d90b336f3f652ff0441e631a06236f785581c8f7 upstream.
+
+The recent changes in 4.9 to mandate USB buffers be heap allocated
+broke this driver, which was allocating the buffers on the stack.
+This resulted in the device failing at initialization.
+
+Introduce dedicated send/receive buffers as part of the state
+structure, and add a mutex to protect access to them.
+
+Note: we also had to tweak the API to mxl111sf_ctrl_msg to pass
+the pointer to the state struct rather than the device, since
+we need it inside the function to access the buffers and the
+mutex. This patch adjusts the callers to match the API change.
+
+Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
+Reported-by: Doug Lung <dlung0@gmail.com>
+Cc: Michael Ira Krufky <mkrufky@linuxtv.org>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c | 4 +--
+ drivers/media/usb/dvb-usb-v2/mxl111sf.c | 32 ++++++++++++++++------------
+ drivers/media/usb/dvb-usb-v2/mxl111sf.h | 8 ++++++-
+ 3 files changed, 28 insertions(+), 16 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
+@@ -320,7 +320,7 @@ fail:
+ static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
+ u8 index, u8 *wdata)
+ {
+- int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
++ int ret = mxl111sf_ctrl_msg(state, wdata[0],
+ &wdata[1], 25, NULL, 0);
+ mxl_fail(ret);
+
+@@ -330,7 +330,7 @@ static int mxl111sf_i2c_send_data(struct
+ static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
+ u8 index, u8 *wdata, u8 *rdata)
+ {
+- int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
++ int ret = mxl111sf_ctrl_msg(state, wdata[0],
+ &wdata[1], 25, rdata, 24);
+ mxl_fail(ret);
+
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+@@ -24,9 +24,6 @@
+ #include "lgdt3305.h"
+ #include "lg2160.h"
+
+-/* Max transfer size done by I2C transfer functions */
+-#define MAX_XFER_SIZE 64
+-
+ int dvb_usb_mxl111sf_debug;
+ module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level "
+@@ -56,27 +53,34 @@ MODULE_PARM_DESC(rfswitch, "force rf swi
+
+ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
++int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
+ u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+ {
++ struct dvb_usb_device *d = state->d;
+ int wo = (rbuf == NULL || rlen == 0); /* write-only */
+ int ret;
+- u8 sndbuf[MAX_XFER_SIZE];
+
+- if (1 + wlen > sizeof(sndbuf)) {
++ if (1 + wlen > MXL_MAX_XFER_SIZE) {
+ pr_warn("%s: len=%d is too big!\n", __func__, wlen);
+ return -EOPNOTSUPP;
+ }
+
+ pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
+
+- memset(sndbuf, 0, 1+wlen);
++ mutex_lock(&state->msg_lock);
++ memset(state->sndbuf, 0, 1+wlen);
++ memset(state->rcvbuf, 0, rlen);
++
++ state->sndbuf[0] = cmd;
++ memcpy(&state->sndbuf[1], wbuf, wlen);
++
++ ret = (wo) ? dvb_usbv2_generic_write(d, state->sndbuf, 1+wlen) :
++ dvb_usbv2_generic_rw(d, state->sndbuf, 1+wlen, state->rcvbuf,
++ rlen);
+
+- sndbuf[0] = cmd;
+- memcpy(&sndbuf[1], wbuf, wlen);
++ memcpy(rbuf, state->rcvbuf, rlen);
++ mutex_unlock(&state->msg_lock);
+
+- ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) :
+- dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen);
+ mxl_fail(ret);
+
+ return ret;
+@@ -92,7 +96,7 @@ int mxl111sf_read_reg(struct mxl111sf_st
+ u8 buf[2];
+ int ret;
+
+- ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
++ ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+ if (mxl_fail(ret)) {
+ mxl_debug("error reading reg: 0x%02x", addr);
+ goto fail;
+@@ -118,7 +122,7 @@ int mxl111sf_write_reg(struct mxl111sf_s
+
+ pr_debug("W: (0x%02x, 0x%02x)\n", addr, data);
+
+- ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
++ ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+ if (mxl_fail(ret))
+ pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
+ return ret;
+@@ -922,6 +926,8 @@ static int mxl111sf_init(struct dvb_usb_
+ static u8 eeprom[256];
+ struct i2c_client c;
+
++ mutex_init(&state->msg_lock);
++
+ ret = get_chip_info(state);
+ if (mxl_fail(ret))
+ pr_err("failed to get chip info during probe");
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
+@@ -19,6 +19,9 @@
+ #include <media/tveeprom.h>
+ #include <media/media-entity.h>
+
++/* Max transfer size done by I2C transfer functions */
++#define MXL_MAX_XFER_SIZE 64
++
+ #define MXL_EP1_REG_READ 1
+ #define MXL_EP2_REG_WRITE 2
+ #define MXL_EP3_INTERRUPT 3
+@@ -86,6 +89,9 @@ struct mxl111sf_state {
+ struct mutex fe_lock;
+ u8 num_frontends;
+ struct mxl111sf_adap_state adap_state[3];
++ u8 sndbuf[MXL_MAX_XFER_SIZE];
++ u8 rcvbuf[MXL_MAX_XFER_SIZE];
++ struct mutex msg_lock;
+ #ifdef CONFIG_MEDIA_CONTROLLER_DVB
+ struct media_entity tuner;
+ struct media_pad tuner_pads[2];
+@@ -108,7 +114,7 @@ int mxl111sf_ctrl_program_regs(struct mx
+
+ /* needed for hardware i2c functions in mxl111sf-i2c.c:
+ * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
+-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
++int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
+ u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
+
+ #define mxl_printk(kern, fmt, arg...) \
--- /dev/null
+From e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 Mon Sep 17 00:00:00 2001
+From: Chen Yu <yu.c.chen@intel.com>
+Date: Thu, 25 May 2017 16:49:07 +0800
+Subject: PCI/PM: Restore the status of PCI devices across hibernation
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+commit e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 upstream.
+
+Currently we saw a lot of "No irq handler" errors during hibernation, which
+caused the system hang finally:
+
+ ata4.00: qc timeout (cmd 0xec)
+ ata4.00: failed to IDENTIFY (I/O error, err_mask=0x4)
+ ata4.00: revalidation failed (errno=-5)
+ ata4: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
+ do_IRQ: 31.151 No irq handler for vector
+
+According to above logs, there is an interrupt triggered and it is
+dispatched to CPU31 with a vector number 151, but there is no handler for
+it, thus this IRQ will not get acked and will cause an IRQ flood which
+kills the system. To be more specific, the 31.151 is an interrupt from the
+AHCI host controller.
+
+After some investigation, the reason why this issue is triggered is because
+the thaw_noirq() function does not restore the MSI/MSI-X settings across
+hibernation.
+
+The scenario is illustrated below:
+
+ 1. Before hibernation, IRQ 34 is the handler for the AHCI device, which
+ is bound to CPU31.
+
+ 2. Hibernation starts, the AHCI device is put into low power state.
+
+ 3. All the nonboot CPUs are put offline, so IRQ 34 has to be migrated to
+ the last alive one - CPU0.
+
+ 4. After the snapshot has been created, all the nonboot CPUs are brought
+ up again; IRQ 34 remains bound to CPU0.
+
+ 5. AHCI devices are put into D0.
+
+ 6. The snapshot is written to the disk.
+
+The issue is triggered in step 6. The AHCI interrupt should be delivered
+to CPU0, however it is delivered to the original CPU31 instead, which
+causes the "No irq handler" issue.
+
+Ying Huang has provided a clue that, in step 3 it is possible that writing
+to the register might not take effect as the PCI devices have been
+suspended.
+
+In step 3, the IRQ 34 affinity should be modified from CPU31 to CPU0, but
+in fact it is not. In __pci_write_msi_msg(), if the device is already in
+low power state, the low level MSI message entry will not be updated but
+cached. During the device restore process after a normal suspend/resume,
+pci_restore_msi_state() writes the cached MSI back to the hardware.
+
+But this is not the case for hibernation. pci_restore_msi_state() is not
+currently called in pci_pm_thaw_noirq(), although pci_save_state() has
+saved the necessary PCI cached information in pci_pm_freeze_noirq().
+
+Restore the PCI status for the device during hibernation. Otherwise the
+status might be lost across hibernation (for example, settings for MSI,
+MSI-X, ATS, ACS, IOV, etc.), which might cause problems during hibernation.
+
+Suggested-by: Ying Huang <ying.huang@intel.com>
+Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+[bhelgaas: changelog]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Len Brown <len.brown@intel.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Rui Zhang <rui.zhang@intel.com>
+Cc: Ying Huang <ying.huang@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci-driver.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -954,6 +954,7 @@ static int pci_pm_thaw_noirq(struct devi
+ return pci_legacy_resume_early(dev);
+
+ pci_update_current_state(pci_dev, PCI_D0);
++ pci_restore_state(pci_dev);
+
+ if (drv && drv->pm && drv->pm->thaw_noirq)
+ error = drv->pm->thaw_noirq(dev);
--- /dev/null
+From dc8cca5ef25ac4cb0dfc37467521a759767ff361 Mon Sep 17 00:00:00 2001
+From: Shawn Lin <shawn.lin@rock-chips.com>
+Date: Mon, 3 Jul 2017 17:21:02 +0800
+Subject: PCI: rockchip: Use normal register bank for config accessors
+
+From: Shawn Lin <shawn.lin@rock-chips.com>
+
+commit dc8cca5ef25ac4cb0dfc37467521a759767ff361 upstream.
+
+Rockchip's RC has two banks of registers for the root port: a normal bank
+that is strictly compatible with the PCIe spec, and a privileged bank that
+can be used to change RO bits of root port registers.
+
+When probing the RC driver, we use the privileged bank to do some basic
+setup work as some RO bits are hw-inited to wrong value. But we didn't
+change to the normal bank after probing the driver.
+
+This leads to a serious problem when the PME code tries to clear the PME
+status by writing PCI_EXP_RTSTA_PME to the register of PCI_EXP_RTSTA. Per
+PCIe 3.0 spec, section 7.8.14, the PME status bit is RW1C. So the PME code
+is doing the right thing to clear the PME status but we find the RC doesn't
+clear it but actually setting it to one. So finally the system trap in
+pcie_pme_work_fn() as PCI_EXP_RTSTA_PME is true now forever. This issue
+can be reproduced by booting kernel with pci=nomsi.
+
+Use the normal register bank for the PCI config accessors. The privileged
+bank is used only internally by this driver.
+
+Fixes: e77f847d ("PCI: rockchip: Add Rockchip PCIe controller support")
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Jeffy Chen <jeffy.chen@rock-chips.com>
+Cc: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/host/pcie-rockchip.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/host/pcie-rockchip.c
++++ b/drivers/pci/host/pcie-rockchip.c
+@@ -131,6 +131,7 @@
+ PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
+ PCIE_CORE_INT_MMVC)
+
++#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000
+ #define PCIE_RC_CONFIG_BASE 0xa00000
+ #define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00)
+ #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
+@@ -267,7 +268,9 @@ static int rockchip_pcie_valid_device(st
+ static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
+ int where, int size, u32 *val)
+ {
+- void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where;
++ void __iomem *addr;
++
++ addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + where;
+
+ if (!IS_ALIGNED((uintptr_t)addr, size)) {
+ *val = 0;
+@@ -291,11 +294,13 @@ static int rockchip_pcie_wr_own_conf(str
+ int where, int size, u32 val)
+ {
+ u32 mask, tmp, offset;
++ void __iomem *addr;
+
+ offset = where & ~0x3;
++ addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offset;
+
+ if (size == 4) {
+- writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
++ writel(val, addr);
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+@@ -306,9 +311,9 @@ static int rockchip_pcie_wr_own_conf(str
+ * corrupt RW1C bits in adjacent registers. But the hardware
+ * doesn't support smaller writes.
+ */
+- tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
++ tmp = readl(addr) & mask;
+ tmp |= val << ((where & 0x3) * 8);
+- writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
++ writel(tmp, addr);
+
+ return PCIBIOS_SUCCESSFUL;
+ }
--- /dev/null
+From 13cfc732160f7bc7e596128ce34cda361c556966 Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Fri, 19 Aug 2016 16:30:25 +0800
+Subject: PCI: Work around poweroff & suspend-to-RAM issue on Macbook Pro 11
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+commit 13cfc732160f7bc7e596128ce34cda361c556966 upstream.
+
+Neither soft poweroff (transition to ACPI power state S5) nor
+suspend-to-RAM (transition to state S3) works on the Macbook Pro 11,4 and
+11,5.
+
+The problem is related to the [mem 0x7fa00000-0x7fbfffff] space. When we
+use that space, e.g., by assigning it to the 00:1c.0 Root Port, the ACPI
+Power Management 1 Control Register (PM1_CNT) at [io 0x1804] doesn't work
+anymore.
+
+Linux does a soft poweroff (transition to S5) by writing to PM1_CNT. The
+theory about why this doesn't work is:
+
+ - The write to PM1_CNT causes an SMI
+ - The BIOS SMI handler depends on something in
+ [mem 0x7fa00000-0x7fbfffff]
+ - When Linux assigns [mem 0x7fa00000-0x7fbfffff] to the 00:1c.0 Port, it
+ covers up whatever the SMI handler uses, so the SMI handler no longer
+ works correctly
+
+Reserve the [mem 0x7fa00000-0x7fbfffff] space so we don't assign it to
+anything.
+
+This is voodoo programming, since we don't know what the real conflict is,
+but we've failed to find the root cause.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=103211
+Tested-by: thejoe@gmail.com
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Rafael J. Wysocki <rafael@kernel.org>
+Cc: Lukas Wunner <lukas@wunner.de>
+Cc: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/pci/fixup.c | 32 ++++++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -571,3 +571,35 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IN
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar);
++
++/*
++ * Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff]
++ *
++ * Using the [mem 0x7fa00000-0x7fbfffff] region, e.g., by assigning it to
++ * the 00:1c.0 Root Port, causes a conflict with [io 0x1804], which is used
++ * for soft poweroff and suspend-to-RAM.
++ *
++ * As far as we know, this is related to the address space, not to the Root
++ * Port itself. Attaching the quirk to the Root Port is a convenience, but
++ * it could probably also be a standalone DMI quirk.
++ *
++ * https://bugzilla.kernel.org/show_bug.cgi?id=103211
++ */
++static void quirk_apple_mbp_poweroff(struct pci_dev *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct resource *res;
++
++ if ((!dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,4") &&
++ !dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,5")) ||
++ pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x1c, 0))
++ return;
++
++ res = request_mem_region(0x7fa00000, 0x200000,
++ "MacBook Pro poweroff workaround");
++ if (res)
++ dev_info(dev, "claimed %s %pR\n", res->name, res);
++ else
++ dev_info(dev, "can't work around MacBook Pro poweroff issue\n");
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff);
powerpc-fix-emulation-of-mfocrf-in-emulate_step.patch
powerpc-asm-mark-cr0-as-clobbered-in-mftb.patch
powerpc-mm-radix-properly-clear-process-table-entry.patch
+af_key-fix-sadb_x_ipsecrequest-parsing.patch
+pci-work-around-poweroff-suspend-to-ram-issue-on-macbook-pro-11.patch
+pci-rockchip-use-normal-register-bank-for-config-accessors.patch
+pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch
+ipvs-snat-packet-replies-only-for-nated-connections.patch
+xhci-fix-20000ms-port-resume-timeout.patch
+xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch
+xhci-bad-ethernet-performance-plugged-in-asm1042a-host.patch
+mxl111sf-fix-driver-to-use-heap-allocate-buffers-for-usb-messages.patch
+usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch
+usb-cdc-acm-add-device-id-for-quirky-printer.patch
+usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch
+usb-renesas_usbhs-gadget-disable-all-eps-when-the-driver-stops.patch
+md-don-t-use-flush_signals-in-userspace-processes.patch
--- /dev/null
+From fe855789d605590e57f9cd968d85ecce46f5c3fd Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Wed, 12 Jul 2017 15:08:39 +0200
+Subject: USB: cdc-acm: add device-id for quirky printer
+
+From: Johan Hovold <johan@kernel.org>
+
+commit fe855789d605590e57f9cd968d85ecce46f5c3fd upstream.
+
+Add device-id entry for DATECS FP-2000 fiscal printer needing the
+NO_UNION_NORMAL quirk.
+
+Reported-by: Anton Avramov <lukav@lukav.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1770,6 +1770,9 @@ static const struct usb_device_id acm_id
+ { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */
+ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
+ },
++ { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
++ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
++ },
+
+ { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
+ .driver_info = CLEAR_HALT_CONDITIONS,
--- /dev/null
+From 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Wed, 19 Jul 2017 16:16:54 +0900
+Subject: usb: renesas_usbhs: fix usbhsc_resume() for !USBHSF_RUNTIME_PWCTRL
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+commit 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce upstream.
+
+This patch fixes an issue that some registers may be not initialized
+after resume if the USBHSF_RUNTIME_PWCTRL is not set. Otherwise,
+if a cable is not connected, the driver will not enable INTENB0.VBSE
+after resume. And then, the driver cannot detect the VBUS.
+
+Fixes: ca8a282a5373 ("usb: gadget: renesas_usbhs: add suspend/resume support")
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/renesas_usbhs/common.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/renesas_usbhs/common.c
++++ b/drivers/usb/renesas_usbhs/common.c
+@@ -752,8 +752,10 @@ static int usbhsc_resume(struct device *
+ struct usbhs_priv *priv = dev_get_drvdata(dev);
+ struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+
+- if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
++ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
+ usbhsc_power_ctrl(priv, 1);
++ usbhs_mod_autonomy_mode(priv);
++ }
+
+ usbhs_platform_call(priv, phy_reset, pdev);
+
--- /dev/null
+From b8b9c974afee685789fcbb191b52d1790be3608c Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Wed, 19 Jul 2017 16:16:55 +0900
+Subject: usb: renesas_usbhs: gadget: disable all eps when the driver stops
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+commit b8b9c974afee685789fcbb191b52d1790be3608c upstream.
+
+A gadget driver will not disable eps immediately when ->disconnect()
+is called. But, since this driver assumes all eps stop after
+the ->disconnect(), unexpected behavior happens (especially in system
+suspend).
+So, this patch disables all eps in usbhsg_try_stop(). After disabling
+eps by renesas_usbhs driver, since some functions will be called by
+both a gadget and renesas_usbhs driver, renesas_usbhs driver should
+protect uep->pipe. To protect uep->pipe easily, this patch adds a new
+lock in struct usbhsg_uep.
+
+Fixes: 2f98382dc ("usb: renesas_usbhs: Add Renesas USBHS Gadget")
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/renesas_usbhs/mod_gadget.c | 31 ++++++++++++++++++++++++-------
+ 1 file changed, 24 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/renesas_usbhs/mod_gadget.c
++++ b/drivers/usb/renesas_usbhs/mod_gadget.c
+@@ -37,6 +37,7 @@ struct usbhsg_gpriv;
+ struct usbhsg_uep {
+ struct usb_ep ep;
+ struct usbhs_pipe *pipe;
++ spinlock_t lock; /* protect the pipe */
+
+ char ep_name[EP_NAME_SIZE];
+
+@@ -636,10 +637,16 @@ usbhsg_ep_enable_end:
+ static int usbhsg_ep_disable(struct usb_ep *ep)
+ {
+ struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
++ struct usbhs_pipe *pipe;
++ unsigned long flags;
++ int ret = 0;
+
+- if (!pipe)
+- return -EINVAL;
++ spin_lock_irqsave(&uep->lock, flags);
++ pipe = usbhsg_uep_to_pipe(uep);
++ if (!pipe) {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ usbhsg_pipe_disable(uep);
+ usbhs_pipe_free(pipe);
+@@ -647,6 +654,9 @@ static int usbhsg_ep_disable(struct usb_
+ uep->pipe->mod_private = NULL;
+ uep->pipe = NULL;
+
++out:
++ spin_unlock_irqrestore(&uep->lock, flags);
++
+ return 0;
+ }
+
+@@ -696,8 +706,11 @@ static int usbhsg_ep_dequeue(struct usb_
+ {
+ struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+ struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
+- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
++ struct usbhs_pipe *pipe;
++ unsigned long flags;
+
++ spin_lock_irqsave(&uep->lock, flags);
++ pipe = usbhsg_uep_to_pipe(uep);
+ if (pipe)
+ usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
+
+@@ -706,6 +719,7 @@ static int usbhsg_ep_dequeue(struct usb_
+ * even if the pipe is NULL.
+ */
+ usbhsg_queue_pop(uep, ureq, -ECONNRESET);
++ spin_unlock_irqrestore(&uep->lock, flags);
+
+ return 0;
+ }
+@@ -852,10 +866,10 @@ static int usbhsg_try_stop(struct usbhs_
+ {
+ struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
+ struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+- struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
++ struct usbhsg_uep *uep;
+ struct device *dev = usbhs_priv_to_dev(priv);
+ unsigned long flags;
+- int ret = 0;
++ int ret = 0, i;
+
+ /******************** spin lock ********************/
+ usbhs_lock(priv, flags);
+@@ -887,7 +901,9 @@ static int usbhsg_try_stop(struct usbhs_
+ usbhs_sys_set_test_mode(priv, 0);
+ usbhs_sys_function_ctrl(priv, 0);
+
+- usbhsg_ep_disable(&dcp->ep);
++ /* disable all eps */
++ usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
++ usbhsg_ep_disable(&uep->ep);
+
+ dev_dbg(dev, "stop gadget\n");
+
+@@ -1069,6 +1085,7 @@ int usbhs_mod_gadget_probe(struct usbhs_
+ ret = -ENOMEM;
+ goto usbhs_mod_gadget_probe_err_gpriv;
+ }
++ spin_lock_init(&uep->lock);
+
+ gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
+ dev_info(dev, "%stransceiver found\n",
--- /dev/null
+From 446230f52a5bef593554510302465eabab45a372 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Thu, 6 Jul 2017 16:06:32 +0100
+Subject: usb: storage: return on error to avoid a null pointer dereference
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit 446230f52a5bef593554510302465eabab45a372 upstream.
+
+When us->extra is null the driver is not initialized, however, a
+later call to osd200_scsi_to_ata is made that dereferences
+us->extra, causing a null pointer dereference. The code
+currently detects and reports that the driver is not initialized;
+add a return to avoid the subsequent dereference issue in this
+check.
+
+Thanks to Alan Stern for pointing out that srb->result needs setting
+to DID_ERROR << 16
+
+Detected by CoverityScan, CID#100308 ("Dereference after null check")
+
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/storage/isd200.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/storage/isd200.c
++++ b/drivers/usb/storage/isd200.c
+@@ -1529,8 +1529,11 @@ static void isd200_ata_command(struct sc
+
+ /* Make sure driver was initialized */
+
+- if (us->extra == NULL)
++ if (us->extra == NULL) {
+ usb_stor_dbg(us, "ERROR Driver not initialized\n");
++ srb->result = DID_ERROR << 16;
++ return;
++ }
+
+ scsi_set_resid(srb, 0);
+ /* scsi_bufflen might change in protocol translation to ata */
--- /dev/null
+From 9da5a1092b13468839b1a864b126cacfb72ad016 Mon Sep 17 00:00:00 2001
+From: Jiahau Chang <jiahau@gmail.com>
+Date: Thu, 20 Jul 2017 14:48:27 +0300
+Subject: xhci: Bad Ethernet performance plugged in ASM1042A host
+
+From: Jiahau Chang <jiahau@gmail.com>
+
+commit 9da5a1092b13468839b1a864b126cacfb72ad016 upstream.
+
+When USB Ethernet is plugged in ASMEDIA ASM1042A xHCI host, bad
+performance was manifesting in Web browser use (like download
+large file such as ISO image). It is known limitation of
+ASM1042A that is not compatible with driver scheduling,
+As a workaround we can modify flow control handling of ASM1042A.
+The register we modify is changes the behavior
+
+[use quirk bit 28, usleep_range 40-60us, empty non-pci function -Mathias]
+Signed-off-by: Jiahau Chang <Lars_chang@asmedia.com.tw>
+Signed-off-by: Ian Pilcher <arequipeno@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/pci-quirks.c | 54 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/pci-quirks.h | 2 +
+ drivers/usb/host/xhci-pci.c | 6 ++++
+ drivers/usb/host/xhci.c | 6 ++++
+ drivers/usb/host/xhci.h | 1
+ 5 files changed, 69 insertions(+)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -77,6 +77,16 @@
+ #define USB_INTEL_USB3_PSSEN 0xD8
+ #define USB_INTEL_USB3PRM 0xDC
+
++/* ASMEDIA quirk use */
++#define ASMT_DATA_WRITE0_REG 0xF8
++#define ASMT_DATA_WRITE1_REG 0xFC
++#define ASMT_CONTROL_REG 0xE0
++#define ASMT_CONTROL_WRITE_BIT 0x02
++#define ASMT_WRITEREG_CMD 0x10423
++#define ASMT_FLOWCTL_ADDR 0xFA30
++#define ASMT_FLOWCTL_DATA 0xBA
++#define ASMT_PSEUDO_DATA 0
++
+ /*
+ * amd_chipset_gen values represent AMD different chipset generations
+ */
+@@ -412,6 +422,50 @@ void usb_amd_quirk_pll_disable(void)
+ }
+ EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
+
++static int usb_asmedia_wait_write(struct pci_dev *pdev)
++{
++ unsigned long retry_count;
++ unsigned char value;
++
++ for (retry_count = 1000; retry_count > 0; --retry_count) {
++
++ pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
++
++ if (value == 0xff) {
++ dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
++ return -EIO;
++ }
++
++ if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
++ return 0;
++
++ usleep_range(40, 60);
++ }
++
++ dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
++ return -ETIMEDOUT;
++}
++
++void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
++{
++ if (usb_asmedia_wait_write(pdev) != 0)
++ return;
++
++ /* send command and address to device */
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
++ pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
++
++ if (usb_asmedia_wait_write(pdev) != 0)
++ return;
++
++ /* send data to device */
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
++ pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
++}
++EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
++
+ void usb_amd_quirk_pll_enable(void)
+ {
+ usb_amd_quirk_pll(0);
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -11,6 +11,7 @@ bool usb_amd_prefetch_quirk(void);
+ void usb_amd_dev_put(void);
+ void usb_amd_quirk_pll_disable(void);
+ void usb_amd_quirk_pll_enable(void);
++void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
+ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
+ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+ void sb800_prefetch(struct device *dev, int on);
+@@ -18,6 +19,7 @@ void sb800_prefetch(struct device *dev,
+ struct pci_dev;
+ static inline void usb_amd_quirk_pll_disable(void) {}
+ static inline void usb_amd_quirk_pll_enable(void) {}
++static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
+ static inline void usb_amd_dev_put(void) {}
+ static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
+ static inline void sb800_prefetch(struct device *dev, int on) {}
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -59,6 +59,8 @@
+ #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
+ #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
+
++#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
++
+ static const char hcd_name[] = "xhci_hcd";
+
+ static struct hc_driver __read_mostly xhci_pci_hc_driver;
+@@ -217,6 +219,10 @@ static void xhci_pci_quirks(struct devic
+ pdev->device == 0x1142)
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+
++ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
++ pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI)
++ xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL;
++
+ if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
+ xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -192,6 +192,9 @@ int xhci_reset(struct xhci_hcd *xhci)
+ if (ret)
+ return ret;
+
++ if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
++ usb_asmedia_modifyflowcontrol(to_pci_dev(xhci_to_hcd(xhci)->self.controller));
++
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+ "Wait for controller to be ready for doorbell rings");
+ /*
+@@ -1122,6 +1125,9 @@ int xhci_resume(struct xhci_hcd *xhci, b
+ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running)
+ compliance_mode_recovery_timer_init(xhci);
+
++ if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
++ usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
++
+ /* Re-enable port polling. */
+ xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+ set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1661,6 +1661,7 @@ struct xhci_hcd {
+ #define XHCI_BROKEN_PORT_PED (1 << 25)
+ #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
+ #define XHCI_U2_DISABLE_WAKE (1 << 27)
++#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28)
+
+ unsigned int num_active_eps;
+ unsigned int limit_active_eps;
--- /dev/null
+From a54408d0a004757789863d74e29c2297edae0b4d Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 20 Jul 2017 14:48:29 +0300
+Subject: xhci: fix 20000ms port resume timeout
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit a54408d0a004757789863d74e29c2297edae0b4d upstream.
+
+A uncleared PLC (port link change) bit will prevent furuther port event
+interrupts for that port. Leaving it uncleared caused get_port_status()
+to timeout after 20000ms while waiting to get the final port event
+interrupt for resume -> U0 state change.
+
+This is a targeted fix for a specific case where we get a port resume event
+racing with xhci resume. The port event interrupt handler notices xHC is
+not yet running and bails out early, leaving PLC uncleared.
+
+The whole xhci port resuming needs more attention, but while working on it
+it anyways makes sense to always ensure PLC is cleared in get_port_status
+before setting a new link state and waiting for its completion.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-hub.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -783,6 +783,9 @@ static u32 xhci_get_port_status(struct u
+ clear_bit(wIndex, &bus_state->resuming_ports);
+
+ set_bit(wIndex, &bus_state->rexit_ports);
++
++ xhci_test_and_clear_bit(xhci, port_array, wIndex,
++ PORT_PLC);
+ xhci_set_link_state(xhci, port_array, wIndex,
+ XDEV_U0);
+
--- /dev/null
+From 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 20 Jul 2017 14:48:26 +0300
+Subject: xhci: Fix NULL pointer dereference when cleaning up streams for removed host
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 upstream.
+
+This off by one in stream_id indexing caused NULL pointer dereference and
+soft lockup on machines with USB attached SCSI devices connected to a
+hotpluggable xhci controller.
+
+The code that cleans up pending URBs for dead hosts tried to dereference
+a stream ring at the invalid stream_id 0.
+ep->stream_info->stream_rings[0] doesn't point to a ring.
+
+Start looping stream_id from 1 like in all the other places in the driver,
+and check that the ring exists before trying to kill URBs on it.
+
+Reported-by: rocko r <rockorequin@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -860,13 +860,16 @@ static void xhci_kill_endpoint_urbs(stru
+ (ep->ep_state & EP_GETTING_NO_STREAMS)) {
+ int stream_id;
+
+- for (stream_id = 0; stream_id < ep->stream_info->num_streams;
++ for (stream_id = 1; stream_id < ep->stream_info->num_streams;
+ stream_id++) {
++ ring = ep->stream_info->stream_rings[stream_id];
++ if (!ring)
++ continue;
++
+ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+ "Killing URBs for slot ID %u, ep index %u, stream %u",
+- slot_id, ep_index, stream_id + 1);
+- xhci_kill_ring_urbs(xhci,
+- ep->stream_info->stream_rings[stream_id]);
++ slot_id, ep_index, stream_id);
++ xhci_kill_ring_urbs(xhci, ring);
+ }
+ } else {
+ ring = ep->ring;