--- /dev/null
+From a1068045883ed4a18363a4ebad0c3d55e473b716 Mon Sep 17 00:00:00 2001
+From: Vinod Koul <vinod.koul@intel.com>
+Date: Thu, 7 Jan 2016 21:48:14 +0530
+Subject: ASoC: compress: Fix compress device direction check
+
+From: Vinod Koul <vinod.koul@intel.com>
+
+commit a1068045883ed4a18363a4ebad0c3d55e473b716 upstream.
+
+The detection of direction for compress was only taking into account codec
+capabilities and not CPU ones. Fix this by checking the CPU side capabilities
+as well
+
+Tested-by: Ashish Panwar <ashish.panwar@intel.com>
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/soc-compress.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+--- a/sound/soc/soc-compress.c
++++ b/sound/soc/soc-compress.c
+@@ -630,6 +630,7 @@ int snd_soc_new_compress(struct snd_soc_
+ struct snd_pcm *be_pcm;
+ char new_name[64];
+ int ret = 0, direction = 0;
++ int playback = 0, capture = 0;
+
+ if (rtd->num_codecs > 1) {
+ dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
+@@ -641,11 +642,27 @@ int snd_soc_new_compress(struct snd_soc_
+ rtd->dai_link->stream_name, codec_dai->name, num);
+
+ if (codec_dai->driver->playback.channels_min)
++ playback = 1;
++ if (codec_dai->driver->capture.channels_min)
++ capture = 1;
++
++ capture = capture && cpu_dai->driver->capture.channels_min;
++ playback = playback && cpu_dai->driver->playback.channels_min;
++
++ /*
++ * Compress devices are unidirectional so only one of the directions
++ * should be set, check for that (xor)
++ */
++ if (playback + capture != 1) {
++ dev_err(rtd->card->dev, "Invalid direction for compress P %d, C %d\n",
++ playback, capture);
++ return -EINVAL;
++ }
++
++ if(playback)
+ direction = SND_COMPRESS_PLAYBACK;
+- else if (codec_dai->driver->capture.channels_min)
+- direction = SND_COMPRESS_CAPTURE;
+ else
+- return -EINVAL;
++ direction = SND_COMPRESS_CAPTURE;
+
+ compr = kzalloc(sizeof(*compr), GFP_KERNEL);
+ if (compr == NULL) {
--- /dev/null
+From bf5ce5bf3cc7136fd7fe5e8999a580bc93a9c8f6 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Sat, 14 Nov 2015 16:26:32 +0800
+Subject: usb: core: lpm: fix usb3_hardware_lpm sysfs node
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit bf5ce5bf3cc7136fd7fe5e8999a580bc93a9c8f6 upstream.
+
+Commit 655fe4effe0f ("usbcore: add sysfs support to xHCI usb3
+hardware LPM") introduced usb3_hardware_lpm sysfs node. This
+doesn't show the correct status of USB3 U1 and U2 LPM status.
+
+This patch fixes this by replacing usb3_hardware_lpm with two
+nodes, usb3_hardware_lpm_u1 (for U1) and usb3_hardware_lpm_u2
+(for U2), and recording the U1/U2 LPM status in right places.
+
+This patch should be back-ported to kernels as old as 4.3,
+that contains Commit 655fe4effe0f ("usbcore: add sysfs support
+to xHCI usb3 hardware LPM").
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/ABI/testing/sysfs-bus-usb | 16 +++++++------
+ Documentation/usb/power-management.txt | 11 ++++-----
+ drivers/usb/core/hub.c | 39 ++++++++++++++++++++++++--------
+ drivers/usb/core/sysfs.c | 31 +++++++++++++++++++++----
+ include/linux/usb.h | 4 +++
+ 5 files changed, 75 insertions(+), 26 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -134,19 +134,21 @@ Description:
+ enabled for the device. Developer can write y/Y/1 or n/N/0 to
+ the file to enable/disable the feature.
+
+-What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm
+-Date: June 2015
++What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm_u1
++ /sys/bus/usb/devices/.../power/usb3_hardware_lpm_u2
++Date: November 2015
+ Contact: Kevin Strasser <kevin.strasser@linux.intel.com>
++ Lu Baolu <baolu.lu@linux.intel.com>
+ Description:
+ If CONFIG_PM is set and a USB 3.0 lpm-capable device is plugged
+ in to a xHCI host which supports link PM, it will check if U1
+ and U2 exit latencies have been set in the BOS descriptor; if
+- the check is is passed and the host supports USB3 hardware LPM,
++ the check is passed and the host supports USB3 hardware LPM,
+ USB3 hardware LPM will be enabled for the device and the USB
+- device directory will contain a file named
+- power/usb3_hardware_lpm. The file holds a string value (enable
+- or disable) indicating whether or not USB3 hardware LPM is
+- enabled for the device.
++ device directory will contain two files named
++ power/usb3_hardware_lpm_u1 and power/usb3_hardware_lpm_u2. These
++ files hold a string value (enable or disable) indicating whether
++ or not USB3 hardware LPM U1 or U2 is enabled for the device.
+
+ What: /sys/bus/usb/devices/.../removable
+ Date: February 2012
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -537,17 +537,18 @@ relevant attribute files are usb2_hardwa
+ can write y/Y/1 or n/N/0 to the file to enable/disable
+ USB2 hardware LPM manually. This is for test purpose mainly.
+
+- power/usb3_hardware_lpm
++ power/usb3_hardware_lpm_u1
++ power/usb3_hardware_lpm_u2
+
+ When a USB 3.0 lpm-capable device is plugged in to a
+ xHCI host which supports link PM, it will check if U1
+ and U2 exit latencies have been set in the BOS
+ descriptor; if the check is is passed and the host
+ supports USB3 hardware LPM, USB3 hardware LPM will be
+- enabled for the device and this file will be created.
+- The file holds a string value (enable or disable)
+- indicating whether or not USB3 hardware LPM is
+- enabled for the device.
++ enabled for the device and these files will be created.
++ The files hold a string value (enable or disable)
++ indicating whether or not USB3 hardware LPM U1 or U2
++ is enabled for the device.
+
+ USB Port Power Control
+ ----------------------
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3895,17 +3895,30 @@ static void usb_enable_link_state(struct
+ return;
+ }
+
+- if (usb_set_lpm_timeout(udev, state, timeout))
++ if (usb_set_lpm_timeout(udev, state, timeout)) {
+ /* If we can't set the parent hub U1/U2 timeout,
+ * device-initiated LPM won't be allowed either, so let the xHCI
+ * host know that this link state won't be enabled.
+ */
+ hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
++ } else {
++ /* Only a configured device will accept the Set Feature
++ * U1/U2_ENABLE
++ */
++ if (udev->actconfig)
++ usb_set_device_initiated_lpm(udev, state, true);
+
+- /* Only a configured device will accept the Set Feature U1/U2_ENABLE */
+- else if (udev->actconfig)
+- usb_set_device_initiated_lpm(udev, state, true);
+-
++ /* As soon as usb_set_lpm_timeout(timeout) returns 0, the
++ * hub-initiated LPM is enabled. Thus, LPM is enabled no
++ * matter the result of usb_set_device_initiated_lpm().
++ * The only difference is whether device is able to initiate
++ * LPM.
++ */
++ if (state == USB3_LPM_U1)
++ udev->usb3_lpm_u1_enabled = 1;
++ else if (state == USB3_LPM_U2)
++ udev->usb3_lpm_u2_enabled = 1;
++ }
+ }
+
+ /*
+@@ -3945,6 +3958,18 @@ static int usb_disable_link_state(struct
+ dev_warn(&udev->dev, "Could not disable xHCI %s timeout, "
+ "bus schedule bandwidth may be impacted.\n",
+ usb3_lpm_names[state]);
++
++ /* As soon as usb_set_lpm_timeout(0) return 0, hub initiated LPM
++ * is disabled. Hub will disallows link to enter U1/U2 as well,
++ * even device is initiating LPM. Hence LPM is disabled if hub LPM
++ * timeout set to 0, no matter device-initiated LPM is disabled or
++ * not.
++ */
++ if (state == USB3_LPM_U1)
++ udev->usb3_lpm_u1_enabled = 0;
++ else if (state == USB3_LPM_U2)
++ udev->usb3_lpm_u2_enabled = 0;
++
+ return 0;
+ }
+
+@@ -3979,8 +4004,6 @@ int usb_disable_lpm(struct usb_device *u
+ if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
+ goto enable_lpm;
+
+- udev->usb3_lpm_enabled = 0;
+-
+ return 0;
+
+ enable_lpm:
+@@ -4038,8 +4061,6 @@ void usb_enable_lpm(struct usb_device *u
+
+ usb_enable_link_state(hcd, udev, USB3_LPM_U1);
+ usb_enable_link_state(hcd, udev, USB3_LPM_U2);
+-
+- udev->usb3_lpm_enabled = 1;
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_lpm);
+
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -531,7 +531,7 @@ static ssize_t usb2_lpm_besl_store(struc
+ }
+ static DEVICE_ATTR_RW(usb2_lpm_besl);
+
+-static ssize_t usb3_hardware_lpm_show(struct device *dev,
++static ssize_t usb3_hardware_lpm_u1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct usb_device *udev = to_usb_device(dev);
+@@ -539,7 +539,7 @@ static ssize_t usb3_hardware_lpm_show(st
+
+ usb_lock_device(udev);
+
+- if (udev->usb3_lpm_enabled)
++ if (udev->usb3_lpm_u1_enabled)
+ p = "enabled";
+ else
+ p = "disabled";
+@@ -548,7 +548,26 @@ static ssize_t usb3_hardware_lpm_show(st
+
+ return sprintf(buf, "%s\n", p);
+ }
+-static DEVICE_ATTR_RO(usb3_hardware_lpm);
++static DEVICE_ATTR_RO(usb3_hardware_lpm_u1);
++
++static ssize_t usb3_hardware_lpm_u2_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct usb_device *udev = to_usb_device(dev);
++ const char *p;
++
++ usb_lock_device(udev);
++
++ if (udev->usb3_lpm_u2_enabled)
++ p = "enabled";
++ else
++ p = "disabled";
++
++ usb_unlock_device(udev);
++
++ return sprintf(buf, "%s\n", p);
++}
++static DEVICE_ATTR_RO(usb3_hardware_lpm_u2);
+
+ static struct attribute *usb2_hardware_lpm_attr[] = {
+ &dev_attr_usb2_hardware_lpm.attr,
+@@ -562,7 +581,8 @@ static struct attribute_group usb2_hardw
+ };
+
+ static struct attribute *usb3_hardware_lpm_attr[] = {
+- &dev_attr_usb3_hardware_lpm.attr,
++ &dev_attr_usb3_hardware_lpm_u1.attr,
++ &dev_attr_usb3_hardware_lpm_u2.attr,
+ NULL,
+ };
+ static struct attribute_group usb3_hardware_lpm_attr_group = {
+@@ -592,7 +612,8 @@ static int add_power_attributes(struct d
+ if (udev->usb2_hw_lpm_capable == 1)
+ rc = sysfs_merge_group(&dev->kobj,
+ &usb2_hardware_lpm_attr_group);
+- if (udev->lpm_capable == 1)
++ if (udev->speed == USB_SPEED_SUPER &&
++ udev->lpm_capable == 1)
+ rc = sysfs_merge_group(&dev->kobj,
+ &usb3_hardware_lpm_attr_group);
+ }
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -511,6 +511,8 @@ struct usb3_lpm_parameters {
+ * @usb2_hw_lpm_enabled: USB2 hardware LPM is enabled
+ * @usb2_hw_lpm_allowed: Userspace allows USB 2.0 LPM to be enabled
+ * @usb3_lpm_enabled: USB3 hardware LPM enabled
++ * @usb3_lpm_u1_enabled: USB3 hardware U1 LPM enabled
++ * @usb3_lpm_u2_enabled: USB3 hardware U2 LPM enabled
+ * @string_langid: language ID for strings
+ * @product: iProduct string, if present (static)
+ * @manufacturer: iManufacturer string, if present (static)
+@@ -584,6 +586,8 @@ struct usb_device {
+ unsigned usb2_hw_lpm_enabled:1;
+ unsigned usb2_hw_lpm_allowed:1;
+ unsigned usb3_lpm_enabled:1;
++ unsigned usb3_lpm_u1_enabled:1;
++ unsigned usb3_lpm_u2_enabled:1;
+ int string_langid;
+
+ /* static strings from the device */