]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Apr 2017 16:05:55 +0000 (18:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Apr 2017 16:05:55 +0000 (18:05 +0200)
added patches:
acpi-button-change-default-behavior-to-lid_init_state-open.patch
acpi-save-nvs-memory-for-lenovo-g50-45.patch
acpi-sysfs-provide-quirk-mechanism-to-prevent-gpe-flooding.patch
alsa-usb-audio-add-implicit-fb-quirk-for-axe-fx-ii.patch
alsa-usb-audio-add-native-dsd-support-for-teac-501-503-dac.patch
amd-xgbe-prepare-for-working-with-more-than-one-type-of-phy.patch
arm-davinci-add-skeleton-for-pdata-quirks.patch
arm-davinci-pm-support-da8xx-dt-platforms.patch
arm-dts-stih407-family-set-snps-dis_u3_susphy_quirk.patch
arm-kernel-add-smc-structure-parameter.patch
arm-omap2-fix-init-for-multiple-quirks-for-the-same-soc.patch
arm-smccc-update-hvc-comment-to-describe-new-quirk-parameter.patch
arm64-dts-hisi-fix-hip06-sas-am-max-trans-quirk.patch
arm64-pci-add-local-struct-device-pointers.patch
arm64-pci-manage-controller-specific-data-on-per-controller-basis.patch
arm64-pci-search-acpi-namespace-to-ensure-ecam-space-is-reserved.patch
asoc-codecs-rt5670-add-quirk-for-lenovo-thinkpad-10.patch
asoc-intel-baytrail-add-quirk-for-lenovo-thinkpad-10.patch
asoc-intel-bytcr_rt5640-quirks-for-insyde-devices.patch
asoc-intel-bytct_rt5640-change-default-capture-settings.patch
asoc-intel-cht_bsw_rt5645-add-baytrail-mclk-support.patch
asoc-intel-cht_bsw_rt5645-harden-acpi-device-detection.patch
asoc-rt5670-add-missing-10ec5072-acpi-id.patch
asoc-sun4i-i2s-add-quirks-to-handle-a31-compatible.patch
can-flexcan-add-quirk-flexcan_quirk_enable_eacen_rrs.patch
clocksource-drivers-arm_arch_timer-don-t-assume-clock-runs-in-suspend.patch
drm-edid-constify-edid-quirk-list.patch
drm-i915-actually-drive-the-bdw-reserved-ids.patch
drm-i915-fix-intel_bdw_ids-definition.patch
drm-i915-more-.is_mobile-cleanups-for-bdw.patch
drm-mga-remove-device_is_agp-callback.patch
drm-msm-adreno-move-function-declarations-to-header-file.patch
firmware-qcom-scm-fix-interrupted-scm-calls.patch
hid-asus-add-i2c-touchpad-support.patch
hid-asus-fix-keyboard-support.patch
hid-microsoft-add-surface-4-type-cover-pro-4-not-jp-versions.patch
hid-multitouch-do-not-retrieve-all-reports-for-all-devices.patch
hid-multitouch-enable-the-surface-3-type-cover-to-report-multitouch-data.patch
hid-multitouch-enable-the-surface-4-type-cover-pro-jp-to-report-multitouch-data.patch
hid-sensor-hub-add-quirk-for-microchip-mm7150.patch
hid-sensor-hub-add-quirk-for-microsoft-surface-3.patch
hid-usbhid-add-quirk-for-mayflash-dragonrise-dolphinbar.patch
hid-usbhid-add-quirk-for-the-futaba-tosd-5711bb-vfd.patch
hid-wacom-don-t-apply-generic-settings-to-old-devices.patch
input-gpio_keys-add-support-for-gpio-descriptors.patch
mmc-sdhci-msm-enable-few-quirks.patch
mmc-sdhci-of-esdhc-remove-default-broken-cd-for-arm.patch
net-mlx4_core-use-device-id-defines.patch
nvme-simplify-stripe-quirk.patch
pci-acpi-check-for-platform-specific-mcfg-quirks.patch
pci-acpi-extend-pci_mcfg_lookup-to-return-ecam-config-accessors.patch
pci-add-acs-quirk-for-intel-union-point.patch
pci-add-acs-quirk-for-qualcomm-qdf2400-and-qdf2432.patch
pci-add-broadcom-northstar2-paxc-quirk-for-device-class-and-mpss.patch
pci-add-mcfg-quirks-for-cavium-thunderx-pass1.x-host-controller.patch
pci-add-mcfg-quirks-for-cavium-thunderx-pass2.x-host-controller.patch
pci-add-mcfg-quirks-for-hisilicon-hip05-06-07-host-controllers.patch
pci-add-mcfg-quirks-for-qualcomm-qdf2432-host-controller.patch
pci-add-mcfg-quirks-for-x-gene-host-controller.patch
pci-disable-msi-for-hisilicon-hip06-hip07-root-ports.patch
pci-expand-vpd-access-disabled-quirk-message.patch
pci-explain-arm64-acpi-mcfg-quirk-kconfig-and-build-strategy.patch
pci-sort-the-list-of-devices-with-d3-delay-quirk-by-id.patch
pci-thunder-pem-factor-out-resource-lookup.patch
pci-xgene-fix-double-free-on-init-error.patch
platform-x86-acer-wmi-only-supports-amw0_guid1-on-acer-family.patch
platform-x86-asus-wmi-detect-quirk_no_rfkill-from-the-dsdt.patch
platform-x86-asus-wmi-set-specified-xusb2pr-value-for-x550lb.patch
rx51-broken-build.patch
sata-ahci-da850-implement-a-workaround-for-the-softreset-quirk.patch
scsi-ufs-add-quirk-to-increase-host-pa_saveconfigtime.patch
scsi-ufs-ensure-that-host-pa_tactivate-is-higher-than-device.patch
scsi-ufs-introduce-a-new-ufshcd_statea-ufshcd_state_eh_scheduled.patch
scsi-ufs-introduce-ufshcd_quirk_prdt_byte_gran-quirk.patch
scsi-ufs-issue-link-starup-2-times-if-device-isn-t-active.patch
scsi-ufs-refactor-device-descriptor-reading.patch
serial-8250_omap-add-omap_dma_tx_kick-quirk-for-am437x.patch
svcauth_gss-close-connection-when-dropping-an-incoming-message.patch
tools-power-turbostat-decode-baytrail-cc6-and-mc6-demotion-configuration.patch
tools-power-turbostat-dump-atom-p-states-correctly.patch
usb-chipidea-msm-rely-on-core-to-override-ahbburst.patch
usb-dwc3-host-pass-quirk-broken-port-ped-property-for-known-broken-revisions.patch
usb-host-xhci-plat-enable-broken_ped-quirk-if-platform-requested.patch
usb-musb-da8xx-fix-host-mode-suspend.patch
usb-storage-add-ignore-residue-quirk-for-initio-inic-3619.patch
usb-xhci-add-quirk-flag-for-broken-ped-bits.patch
watchdog-s3c2410-fix-infinite-interrupt-in-soft-mode.patch
x86-intel_idle-add-cpu-model-0x4a-atom-z34xx-series.patch
x86-reboot-quirks-add-asus-eeebook-x205ta-reboot-quirk.patch
x86-reboot-quirks-add-asus-eeebook-x205ta-w-reboot-quirk.patch
x86-reboot-quirks-fix-typo-in-asus-eeebook-x205ta-reboot-quirk.patch

93 files changed:
queue-4.9/acpi-button-change-default-behavior-to-lid_init_state-open.patch [new file with mode: 0644]
queue-4.9/acpi-save-nvs-memory-for-lenovo-g50-45.patch [new file with mode: 0644]
queue-4.9/acpi-sysfs-provide-quirk-mechanism-to-prevent-gpe-flooding.patch [new file with mode: 0644]
queue-4.9/alsa-usb-audio-add-implicit-fb-quirk-for-axe-fx-ii.patch [new file with mode: 0644]
queue-4.9/alsa-usb-audio-add-native-dsd-support-for-teac-501-503-dac.patch [new file with mode: 0644]
queue-4.9/amd-xgbe-prepare-for-working-with-more-than-one-type-of-phy.patch [new file with mode: 0644]
queue-4.9/arm-davinci-add-skeleton-for-pdata-quirks.patch [new file with mode: 0644]
queue-4.9/arm-davinci-pm-support-da8xx-dt-platforms.patch [new file with mode: 0644]
queue-4.9/arm-dts-stih407-family-set-snps-dis_u3_susphy_quirk.patch [new file with mode: 0644]
queue-4.9/arm-kernel-add-smc-structure-parameter.patch [new file with mode: 0644]
queue-4.9/arm-omap2-fix-init-for-multiple-quirks-for-the-same-soc.patch [new file with mode: 0644]
queue-4.9/arm-smccc-update-hvc-comment-to-describe-new-quirk-parameter.patch [new file with mode: 0644]
queue-4.9/arm64-dts-hisi-fix-hip06-sas-am-max-trans-quirk.patch [new file with mode: 0644]
queue-4.9/arm64-pci-add-local-struct-device-pointers.patch [new file with mode: 0644]
queue-4.9/arm64-pci-manage-controller-specific-data-on-per-controller-basis.patch [new file with mode: 0644]
queue-4.9/arm64-pci-search-acpi-namespace-to-ensure-ecam-space-is-reserved.patch [new file with mode: 0644]
queue-4.9/asoc-codecs-rt5670-add-quirk-for-lenovo-thinkpad-10.patch [new file with mode: 0644]
queue-4.9/asoc-intel-baytrail-add-quirk-for-lenovo-thinkpad-10.patch [new file with mode: 0644]
queue-4.9/asoc-intel-bytcr_rt5640-quirks-for-insyde-devices.patch [new file with mode: 0644]
queue-4.9/asoc-intel-bytct_rt5640-change-default-capture-settings.patch [new file with mode: 0644]
queue-4.9/asoc-intel-cht_bsw_rt5645-add-baytrail-mclk-support.patch [new file with mode: 0644]
queue-4.9/asoc-intel-cht_bsw_rt5645-harden-acpi-device-detection.patch [new file with mode: 0644]
queue-4.9/asoc-rt5670-add-missing-10ec5072-acpi-id.patch [new file with mode: 0644]
queue-4.9/asoc-sun4i-i2s-add-quirks-to-handle-a31-compatible.patch [new file with mode: 0644]
queue-4.9/can-flexcan-add-quirk-flexcan_quirk_enable_eacen_rrs.patch [new file with mode: 0644]
queue-4.9/clocksource-drivers-arm_arch_timer-don-t-assume-clock-runs-in-suspend.patch [new file with mode: 0644]
queue-4.9/drm-edid-constify-edid-quirk-list.patch [new file with mode: 0644]
queue-4.9/drm-i915-actually-drive-the-bdw-reserved-ids.patch [new file with mode: 0644]
queue-4.9/drm-i915-fix-intel_bdw_ids-definition.patch [new file with mode: 0644]
queue-4.9/drm-i915-more-.is_mobile-cleanups-for-bdw.patch [new file with mode: 0644]
queue-4.9/drm-mga-remove-device_is_agp-callback.patch [new file with mode: 0644]
queue-4.9/drm-msm-adreno-move-function-declarations-to-header-file.patch [new file with mode: 0644]
queue-4.9/firmware-qcom-scm-fix-interrupted-scm-calls.patch [new file with mode: 0644]
queue-4.9/hid-asus-add-i2c-touchpad-support.patch [new file with mode: 0644]
queue-4.9/hid-asus-fix-keyboard-support.patch [new file with mode: 0644]
queue-4.9/hid-i2c-hid-add-a-simple-quirk-to-fix-device-defects.patch
queue-4.9/hid-microsoft-add-surface-4-type-cover-pro-4-not-jp-versions.patch [new file with mode: 0644]
queue-4.9/hid-multitouch-do-not-retrieve-all-reports-for-all-devices.patch [new file with mode: 0644]
queue-4.9/hid-multitouch-enable-the-surface-3-type-cover-to-report-multitouch-data.patch [new file with mode: 0644]
queue-4.9/hid-multitouch-enable-the-surface-4-type-cover-pro-jp-to-report-multitouch-data.patch [new file with mode: 0644]
queue-4.9/hid-sensor-hub-add-quirk-for-microchip-mm7150.patch [new file with mode: 0644]
queue-4.9/hid-sensor-hub-add-quirk-for-microsoft-surface-3.patch [new file with mode: 0644]
queue-4.9/hid-usbhid-add-quirk-for-mayflash-dragonrise-dolphinbar.patch [new file with mode: 0644]
queue-4.9/hid-usbhid-add-quirk-for-the-futaba-tosd-5711bb-vfd.patch [new file with mode: 0644]
queue-4.9/hid-wacom-don-t-apply-generic-settings-to-old-devices.patch [new file with mode: 0644]
queue-4.9/input-gpio_keys-add-support-for-gpio-descriptors.patch [new file with mode: 0644]
queue-4.9/mmc-sdhci-msm-enable-few-quirks.patch [new file with mode: 0644]
queue-4.9/mmc-sdhci-of-esdhc-remove-default-broken-cd-for-arm.patch [new file with mode: 0644]
queue-4.9/net-mlx4_core-use-device-id-defines.patch [new file with mode: 0644]
queue-4.9/nvme-simplify-stripe-quirk.patch [new file with mode: 0644]
queue-4.9/pci-acpi-check-for-platform-specific-mcfg-quirks.patch [new file with mode: 0644]
queue-4.9/pci-acpi-extend-pci_mcfg_lookup-to-return-ecam-config-accessors.patch [new file with mode: 0644]
queue-4.9/pci-add-acs-quirk-for-intel-union-point.patch [new file with mode: 0644]
queue-4.9/pci-add-acs-quirk-for-qualcomm-qdf2400-and-qdf2432.patch [new file with mode: 0644]
queue-4.9/pci-add-broadcom-northstar2-paxc-quirk-for-device-class-and-mpss.patch [new file with mode: 0644]
queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass1.x-host-controller.patch [new file with mode: 0644]
queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass2.x-host-controller.patch [new file with mode: 0644]
queue-4.9/pci-add-mcfg-quirks-for-hisilicon-hip05-06-07-host-controllers.patch [new file with mode: 0644]
queue-4.9/pci-add-mcfg-quirks-for-qualcomm-qdf2432-host-controller.patch [new file with mode: 0644]
queue-4.9/pci-add-mcfg-quirks-for-x-gene-host-controller.patch [new file with mode: 0644]
queue-4.9/pci-disable-msi-for-hisilicon-hip06-hip07-root-ports.patch [new file with mode: 0644]
queue-4.9/pci-expand-vpd-access-disabled-quirk-message.patch [new file with mode: 0644]
queue-4.9/pci-explain-arm64-acpi-mcfg-quirk-kconfig-and-build-strategy.patch [new file with mode: 0644]
queue-4.9/pci-sort-the-list-of-devices-with-d3-delay-quirk-by-id.patch [new file with mode: 0644]
queue-4.9/pci-thunder-pem-factor-out-resource-lookup.patch [new file with mode: 0644]
queue-4.9/pci-xgene-fix-double-free-on-init-error.patch [new file with mode: 0644]
queue-4.9/platform-x86-acer-wmi-only-supports-amw0_guid1-on-acer-family.patch [new file with mode: 0644]
queue-4.9/platform-x86-asus-wmi-detect-quirk_no_rfkill-from-the-dsdt.patch [new file with mode: 0644]
queue-4.9/platform-x86-asus-wmi-set-specified-xusb2pr-value-for-x550lb.patch [new file with mode: 0644]
queue-4.9/rx51-broken-build.patch [new file with mode: 0644]
queue-4.9/sata-ahci-da850-implement-a-workaround-for-the-softreset-quirk.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-add-quirk-to-increase-host-pa_saveconfigtime.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-ensure-that-host-pa_tactivate-is-higher-than-device.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-introduce-a-new-ufshcd_statea-ufshcd_state_eh_scheduled.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-introduce-ufshcd_quirk_prdt_byte_gran-quirk.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-issue-link-starup-2-times-if-device-isn-t-active.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-refactor-device-descriptor-reading.patch [new file with mode: 0644]
queue-4.9/serial-8250_omap-add-omap_dma_tx_kick-quirk-for-am437x.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/svcauth_gss-close-connection-when-dropping-an-incoming-message.patch [new file with mode: 0644]
queue-4.9/tools-power-turbostat-decode-baytrail-cc6-and-mc6-demotion-configuration.patch [new file with mode: 0644]
queue-4.9/tools-power-turbostat-dump-atom-p-states-correctly.patch [new file with mode: 0644]
queue-4.9/usb-chipidea-msm-rely-on-core-to-override-ahbburst.patch [new file with mode: 0644]
queue-4.9/usb-dwc3-host-pass-quirk-broken-port-ped-property-for-known-broken-revisions.patch [new file with mode: 0644]
queue-4.9/usb-host-xhci-plat-enable-broken_ped-quirk-if-platform-requested.patch [new file with mode: 0644]
queue-4.9/usb-musb-da8xx-fix-host-mode-suspend.patch [new file with mode: 0644]
queue-4.9/usb-storage-add-ignore-residue-quirk-for-initio-inic-3619.patch [new file with mode: 0644]
queue-4.9/usb-xhci-add-quirk-flag-for-broken-ped-bits.patch [new file with mode: 0644]
queue-4.9/watchdog-s3c2410-fix-infinite-interrupt-in-soft-mode.patch [new file with mode: 0644]
queue-4.9/x86-intel_idle-add-cpu-model-0x4a-atom-z34xx-series.patch [new file with mode: 0644]
queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-reboot-quirk.patch [new file with mode: 0644]
queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-w-reboot-quirk.patch [new file with mode: 0644]
queue-4.9/x86-reboot-quirks-fix-typo-in-asus-eeebook-x205ta-reboot-quirk.patch [new file with mode: 0644]

diff --git a/queue-4.9/acpi-button-change-default-behavior-to-lid_init_state-open.patch b/queue-4.9/acpi-button-change-default-behavior-to-lid_init_state-open.patch
new file mode 100644 (file)
index 0000000..d0ea575
--- /dev/null
@@ -0,0 +1,122 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:27 +0000
+Subject: ACPI / button: Change default behavior to lid_init_state=open
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-69-alexander.levin@verizon.com>
+
+From: Lv Zheng <lv.zheng@intel.com>
+
+[ Upstream commit 77e9a4aa9de10cc1418bf9a892366988802a8025 ]
+
+More and more platforms need the button.lid_init_state=open quirk. This
+patch sets it the default behavior.
+
+If a platform doesn't send lid open event or lid open event is lost due to
+the underlying system problems, then we can compare various combinations:
+1. systemd/acpid is used to suspend system or not, systemd has a special
+   logic forcing open event after resuming;
+2. _LID returns a cached value or not.
+
+The result is as follows:
+
+ 1. lid_init_state=method
+   1. cached
+      1. resumed by lid:
+         (x) event=close
+         (x) systemd=suspends again
+         (x) acpid=suspends again
+         (x) state=close
+      2. resumed by other:
+         (o) event=close
+         (x) systemd=suspends again
+         (x) acpid=suspends again
+         (o) state=close
+   2. non-cached
+      1. resumed by lid:
+         (o) event=open
+         (o) systemd=resumes
+         (o) acpid=resumes
+         (o) state=open
+      2. resumed by other:
+         (o) event=close
+         (x) systemd=suspends again
+         (x) acpid=suspends again
+         (o) state=close
+ 2. lid_init_state=open
+   1. cached
+      1. resumed by lid:
+         (o) event=open
+         (o) systemd=resumes
+         (o) acpid=resumes
+         (x) state=close
+      2. resumed by other:
+         (x) event=open
+         (o) systemd=resumes
+         (o) acpid=resumes
+         (o) state=close
+   2. non-cached
+      1. resumed by lid:
+         (o) event=open
+         (o) systemd=resumes
+         (o) acpid=resumes
+         (o) state=open
+      2. resumed by other:
+         (x) event=open
+         (o) systemd=resumes
+         (o) acpid=resumes
+         (o) state=close
+ 3. lid_init_state=ignore
+   1. cached
+      1. resumed by lid:
+         (o) event=none
+         (x) systemd=suspends again
+         (o) acpid=resumes
+         (x) state=close
+      2. resumed by other:
+         (o) event=none
+         (x) systemd=suspends again
+         (o) acpid=resumes
+         (o) state=close
+   2. non-cached
+      1. resumed by lid:
+         (o) event=none
+         (x) systemd=suspends again
+         (o) acpid=resumes
+         (o) state=open
+      2. resumed by other:
+         (o) event=none
+         (x) systemd=suspends again
+         (o) acpid=resumes
+         (o) state=close
+
+As a conclusion:
+ 1. With systemd changed, lid_init_state=ignore has only one problem and the
+    problem comes from an underlying issue, not userspace and kernel lid
+    handling.
+ 2. Without systemd changed, lid_init_state=open can be the default
+    behavior as the pass ratio is not much worse than lid_init_state=ignore.
+ 3. lid_init_state=method is buggy, we can have a separate patch to make it
+    deprectated.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=187271
+Signed-off-by: Lv Zheng <lv.zheng@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/button.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -113,7 +113,7 @@ struct acpi_button {
+ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
+ static struct acpi_device *lid_device;
+-static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
++static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
+ static unsigned long lid_report_interval __read_mostly = 500;
+ module_param(lid_report_interval, ulong, 0644);
diff --git a/queue-4.9/acpi-save-nvs-memory-for-lenovo-g50-45.patch b/queue-4.9/acpi-save-nvs-memory-for-lenovo-g50-45.patch
new file mode 100644 (file)
index 0000000..dba79cc
--- /dev/null
@@ -0,0 +1,66 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:29 +0000
+Subject: ACPI: save NVS memory for Lenovo G50-45
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-75-alexander.levin@verizon.com>
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit cbc00c1310d34139a63946482b40a6b261a03fb9 ]
+
+In commit 821d6f0359b0 (ACPI / sleep: Do not save NVS for new machines to
+accelerate S3), to optimize S3 suspend/resume speed, code is introduced
+to ignore NVS memory saving during S3 for all the platforms later than
+2012.
+
+But, Lenovo G50-45, a platform released in 2015, still needs NVS memory
+saving during S3. A quirk is introduced for this platform.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=189431
+Tested-by: Przemek <soprwa@gmail.com>
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+[ rjw: Drop unnecessary code ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/sleep.c |   19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/drivers/acpi/sleep.c
++++ b/drivers/acpi/sleep.c
+@@ -130,6 +130,12 @@ void __init acpi_nvs_nosave_s3(void)
+       nvs_nosave_s3 = true;
+ }
++static int __init init_nvs_save_s3(const struct dmi_system_id *d)
++{
++      nvs_nosave_s3 = false;
++      return 0;
++}
++
+ /*
+  * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
+  * user to request that behavior by using the 'acpi_old_suspend_ordering'
+@@ -324,6 +330,19 @@ static struct dmi_system_id acpisleep_dm
+               DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
+               },
+       },
++      /*
++       * https://bugzilla.kernel.org/show_bug.cgi?id=189431
++       * Lenovo G50-45 is a platform later than 2012, but needs nvs memory
++       * saving during S3.
++       */
++      {
++      .callback = init_nvs_save_s3,
++      .ident = "Lenovo G50-45",
++      .matches = {
++              DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++              DMI_MATCH(DMI_PRODUCT_NAME, "80E3"),
++              },
++      },
+       {},
+ };
diff --git a/queue-4.9/acpi-sysfs-provide-quirk-mechanism-to-prevent-gpe-flooding.patch b/queue-4.9/acpi-sysfs-provide-quirk-mechanism-to-prevent-gpe-flooding.patch
new file mode 100644 (file)
index 0000000..3344b41
--- /dev/null
@@ -0,0 +1,150 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:17 +0000
+Subject: ACPI / sysfs: Provide quirk mechanism to prevent GPE flooding
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-41-alexander.levin@verizon.com>
+
+From: Lv Zheng <lv.zheng@intel.com>
+
+[ Upstream commit 9c4aa1eecb48cfac18ed5e3aca9d9ae58fbafc11 ]
+
+Sometimes, the users may require a quirk to be provided from ACPI subsystem
+core to prevent a GPE from flooding.
+Normally, if a GPE cannot be dispatched, ACPICA core automatically prevents
+the GPE from firing. But there are cases the GPE is dispatched by _Lxx/_Exx
+provided via AML table, and OSPM is lacking of the knowledge to get
+_Lxx/_Exx correctly executed to handle the GPE, thus the GPE flooding may
+still occur.
+
+The existing quirk mechanism can be enabled/disabled using the following
+commands to prevent such kind of GPE flooding during runtime:
+ # echo mask > /sys/firmware/acpi/interrupts/gpe00
+ # echo unmask > /sys/firmware/acpi/interrupts/gpe00
+To avoid GPE flooding during boot, we need a boot stage mechanism.
+
+This patch provides such a boot stage quirk mechanism to stop this kind of
+GPE flooding. This patch doesn't fix any feature gap but since the new
+feature gaps could be found in the future endlessly, and can disappear if
+the feature gaps are filled, providing a boot parameter rather than a DMI
+table should suffice.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=53071
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=117481
+Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/887793
+Signed-off-by: Lv Zheng <lv.zheng@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/kernel-parameters.txt |   10 ++++++
+ drivers/acpi/internal.h             |    1 
+ drivers/acpi/scan.c                 |    1 
+ drivers/acpi/sysfs.c                |   56 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 68 insertions(+)
+
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -305,6 +305,16 @@ bytes respectively. Such letter suffixes
+                       use by PCI
+                       Format: <irq>,<irq>...
++      acpi_mask_gpe=  [HW,ACPI]
++                      Due to the existence of _Lxx/_Exx, some GPEs triggered
++                      by unsupported hardware/firmware features can result in
++                        GPE floodings that cannot be automatically disabled by
++                        the GPE dispatcher.
++                      This facility can be used to prevent such uncontrolled
++                      GPE floodings.
++                      Format: <int>
++                      Support masking of GPEs numbered from 0x00 to 0x7f.
++
+       acpi_no_auto_serialize  [HW,ACPI]
+                       Disable auto-serialization of AML methods
+                       AML control methods that contain the opcodes to create
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -37,6 +37,7 @@ void acpi_amba_init(void);
+ static inline void acpi_amba_init(void) {}
+ #endif
+ int acpi_sysfs_init(void);
++void acpi_gpe_apply_masked_gpes(void);
+ void acpi_container_init(void);
+ void acpi_memory_hotplug_init(void);
+ #ifdef        CONFIG_ACPI_HOTPLUG_IOAPIC
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -2044,6 +2044,7 @@ int __init acpi_scan_init(void)
+               }
+       }
++      acpi_gpe_apply_masked_gpes();
+       acpi_update_all_gpes();
+       acpi_ec_ecdt_start();
+--- a/drivers/acpi/sysfs.c
++++ b/drivers/acpi/sysfs.c
+@@ -708,6 +708,62 @@ end:
+       return result ? result : size;
+ }
++/*
++ * A Quirk Mechanism for GPE Flooding Prevention:
++ *
++ * Quirks may be needed to prevent GPE flooding on a specific GPE. The
++ * flooding typically cannot be detected and automatically prevented by
++ * ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
++ * the AML tables. This normally indicates a feature gap in Linux, thus
++ * instead of providing endless quirk tables, we provide a boot parameter
++ * for those who want this quirk. For example, if the users want to prevent
++ * the GPE flooding for GPE 00, they need to specify the following boot
++ * parameter:
++ *   acpi_mask_gpe=0x00
++ * The masking status can be modified by the following runtime controlling
++ * interface:
++ *   echo unmask > /sys/firmware/acpi/interrupts/gpe00
++ */
++
++/*
++ * Currently, the GPE flooding prevention only supports to mask the GPEs
++ * numbered from 00 to 7f.
++ */
++#define ACPI_MASKABLE_GPE_MAX 0x80
++
++static u64 __initdata acpi_masked_gpes;
++
++static int __init acpi_gpe_set_masked_gpes(char *val)
++{
++      u8 gpe;
++
++      if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
++              return -EINVAL;
++      acpi_masked_gpes |= ((u64)1<<gpe);
++
++      return 1;
++}
++__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
++
++void __init acpi_gpe_apply_masked_gpes(void)
++{
++      acpi_handle handle;
++      acpi_status status;
++      u8 gpe;
++
++      for (gpe = 0;
++           gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
++           gpe++) {
++              if (acpi_masked_gpes & ((u64)1<<gpe)) {
++                      status = acpi_get_gpe_device(gpe, &handle);
++                      if (ACPI_SUCCESS(status)) {
++                              pr_info("Masking GPE 0x%x.\n", gpe);
++                              (void)acpi_mask_gpe(handle, gpe, TRUE);
++                      }
++              }
++      }
++}
++
+ void acpi_irq_stats_init(void)
+ {
+       acpi_status status;
diff --git a/queue-4.9/alsa-usb-audio-add-implicit-fb-quirk-for-axe-fx-ii.patch b/queue-4.9/alsa-usb-audio-add-implicit-fb-quirk-for-axe-fx-ii.patch
new file mode 100644 (file)
index 0000000..ebfb4fe
--- /dev/null
@@ -0,0 +1,43 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:13 +0000
+Subject: ALSA: usb-audio: add implicit fb quirk for Axe-Fx II
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-32-alexander.levin@verizon.com>
+
+From: Alberto Aguirre <albaguirre@gmail.com>
+
+[ Upstream commit 17f08b0d9aafccdb10038ab6dbd9ddb6433c13e2 ]
+
+The Axe-Fx II implicit feedback end point and the data sync endpoint
+are in different interface descriptors. Add quirk to ensure a sync
+endpoint is properly configured.
+
+Signed-off-by: Alberto Aguirre <albaguirre@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/pcm.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -348,6 +348,16 @@ static int set_sync_ep_implicit_fb_quirk
+               alts = &iface->altsetting[1];
+               goto add_sync_ep;
++      case USB_ID(0x2466, 0x8003):
++              ep = 0x86;
++              iface = usb_ifnum_to_if(dev, 2);
++
++              if (!iface || iface->num_altsetting == 0)
++                      return -EINVAL;
++
++              alts = &iface->altsetting[1];
++              goto add_sync_ep;
++
+       }
+       if (attr == USB_ENDPOINT_SYNC_ASYNC &&
+           altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
diff --git a/queue-4.9/alsa-usb-audio-add-native-dsd-support-for-teac-501-503-dac.patch b/queue-4.9/alsa-usb-audio-add-native-dsd-support-for-teac-501-503-dac.patch
new file mode 100644 (file)
index 0000000..fcfd664
--- /dev/null
@@ -0,0 +1,90 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:14 +0000
+Subject: ALSA: usb-audio: Add native DSD support for TEAC 501/503 DAC
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-34-alexander.levin@verizon.com>
+
+From: Nobutaka Okabe <nob77413@gmail.com>
+
+[ Upstream commit 7f38ca047b0cb54df7f6d9e4110e292e45dba6ad ]
+
+This patch adds native DSD support for the following devices.
+
+- TEAC NT-503
+- TEAC UD-503
+- TEAC UD-501
+
+(1) Add quirks for native DSD support for TEAC devices.
+(2) A specific vendor command is needed to switch between PCM/DOP and
+    DSD mode, same as Denon/Marantz devices.
+
+Signed-off-by: Nobutaka Okabe <nob77413@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/quirks.c |   38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1166,6 +1166,18 @@ static bool is_marantz_denon_dac(unsigne
+       return false;
+ }
++/* TEAC UD-501/UD-503/NT-503 USB DACs need a vendor cmd to switch
++ * between PCM/DOP and native DSD mode
++ */
++static bool is_teac_50X_dac(unsigned int id)
++{
++      switch (id) {
++      case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */
++              return true;
++      }
++      return false;
++}
++
+ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
+                             struct audioformat *fmt)
+ {
+@@ -1193,6 +1205,26 @@ int snd_usb_select_mode_quirk(struct snd
+                       break;
+               }
+               mdelay(20);
++      } else if (is_teac_50X_dac(subs->stream->chip->usb_id)) {
++              /* Vendor mode switch cmd is required. */
++              switch (fmt->altsetting) {
++              case 3: /* DSD mode (DSD_U32) requested */
++                      err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0,
++                                            USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
++                                            1, 1, NULL, 0);
++                      if (err < 0)
++                              return err;
++                      break;
++
++              case 2: /* PCM or DOP mode (S32) requested */
++              case 1: /* PCM mode (S16) requested */
++                      err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0,
++                                            USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
++                                            0, 1, NULL, 0);
++                      if (err < 0)
++                              return err;
++                      break;
++              }
+       }
+       return 0;
+ }
+@@ -1338,5 +1370,11 @@ u64 snd_usb_interface_dsd_format_quirks(
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+       }
++      /* TEAC devices with USB DAC functionality */
++      if (is_teac_50X_dac(chip->usb_id)) {
++              if (fp->altsetting == 3)
++                      return SNDRV_PCM_FMTBIT_DSD_U32_BE;
++      }
++
+       return 0;
+ }
diff --git a/queue-4.9/amd-xgbe-prepare-for-working-with-more-than-one-type-of-phy.patch b/queue-4.9/amd-xgbe-prepare-for-working-with-more-than-one-type-of-phy.patch
new file mode 100644 (file)
index 0000000..cfc0ad0
--- /dev/null
@@ -0,0 +1,2330 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:23 +0000
+Subject: amd-xgbe: Prepare for working with more than one type of phy
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-57-alexander.levin@verizon.com>
+
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+
+[ Upstream commit e57f7a3feaef0e9e196801f1625bca1337405421 ]
+
+Prepare the code to be able to work with more than one type of phy by
+adding additional callable functions into the phy interface and removing
+phy specific settings/functions from non-phy related files.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/amd/xgbe/Makefile       |    3 
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c     |   58 -
+ drivers/net/ethernet/amd/xgbe/xgbe-drv.c     |    6 
+ drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   19 
+ drivers/net/ethernet/amd/xgbe/xgbe-main.c    |  214 ++-----
+ drivers/net/ethernet/amd/xgbe/xgbe-mdio.c    |  543 +++++------------
+ drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c  |  821 +++++++++++++++++++++++++++
+ drivers/net/ethernet/amd/xgbe/xgbe.h         |  130 ++--
+ 8 files changed, 1137 insertions(+), 657 deletions(-)
+ create mode 100644 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
+
+--- a/drivers/net/ethernet/amd/xgbe/Makefile
++++ b/drivers/net/ethernet/amd/xgbe/Makefile
+@@ -2,7 +2,8 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o
+ amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \
+                xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \
+-               xgbe-ptp.o
++               xgbe-ptp.o \
++               xgbe-phy-v1.o
+ amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o
+ amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -704,32 +704,26 @@ static void xgbe_enable_mac_interrupts(s
+       XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
+ }
+-static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
++static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed)
+ {
+-      if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3)
+-              return 0;
+-
+-      XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3);
+-
+-      return 0;
+-}
+-
+-static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata)
+-{
+-      if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2)
+-              return 0;
++      unsigned int ss;
+-      XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2);
+-
+-      return 0;
+-}
+-
+-static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata)
+-{
+-      if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0)
+-              return 0;
++      switch (speed) {
++      case SPEED_1000:
++              ss = 0x03;
++              break;
++      case SPEED_2500:
++              ss = 0x02;
++              break;
++      case SPEED_10000:
++              ss = 0x00;
++              break;
++      default:
++              return -EINVAL;
++      }
+-      XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0);
++      if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss)
++              XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss);
+       return 0;
+ }
+@@ -2177,19 +2171,7 @@ static void xgbe_config_jumbo_enable(str
+ static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata)
+ {
+-      switch (pdata->phy_speed) {
+-      case SPEED_10000:
+-              xgbe_set_xgmii_speed(pdata);
+-              break;
+-
+-      case SPEED_2500:
+-              xgbe_set_gmii_2500_speed(pdata);
+-              break;
+-
+-      case SPEED_1000:
+-              xgbe_set_gmii_speed(pdata);
+-              break;
+-      }
++      xgbe_set_speed(pdata, pdata->phy_speed);
+ }
+ static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata)
+@@ -2905,9 +2887,7 @@ void xgbe_init_function_ptrs_dev(struct
+       hw_if->read_mmd_regs = xgbe_read_mmd_regs;
+       hw_if->write_mmd_regs = xgbe_write_mmd_regs;
+-      hw_if->set_gmii_speed = xgbe_set_gmii_speed;
+-      hw_if->set_gmii_2500_speed = xgbe_set_gmii_2500_speed;
+-      hw_if->set_xgmii_speed = xgbe_set_xgmii_speed;
++      hw_if->set_speed = xgbe_set_speed;
+       hw_if->enable_tx = xgbe_enable_tx;
+       hw_if->disable_tx = xgbe_disable_tx;
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+@@ -783,7 +783,7 @@ static void xgbe_free_rx_data(struct xgb
+       DBGPR("<--xgbe_free_rx_data\n");
+ }
+-static int xgbe_phy_init(struct xgbe_prv_data *pdata)
++static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
+ {
+       pdata->phy_link = -1;
+       pdata->phy_speed = SPEED_UNKNOWN;
+@@ -1297,8 +1297,8 @@ static int xgbe_open(struct net_device *
+       DBGPR("-->xgbe_open\n");
+-      /* Initialize the phy */
+-      ret = xgbe_phy_init(pdata);
++      /* Reset the phy settings */
++      ret = xgbe_phy_reset(pdata);
+       if (ret)
+               return ret;
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+@@ -316,24 +316,7 @@ static int xgbe_set_settings(struct net_
+       }
+       if (cmd->autoneg == AUTONEG_DISABLE) {
+-              switch (speed) {
+-              case SPEED_10000:
+-                      break;
+-              case SPEED_2500:
+-                      if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) {
+-                              netdev_err(netdev, "unsupported speed %u\n",
+-                                         speed);
+-                              return -EINVAL;
+-                      }
+-                      break;
+-              case SPEED_1000:
+-                      if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) {
+-                              netdev_err(netdev, "unsupported speed %u\n",
+-                                         speed);
+-                              return -EINVAL;
+-                      }
+-                      break;
+-              default:
++              if (!pdata->phy_if.phy_valid_speed(pdata, speed)) {
+                       netdev_err(netdev, "unsupported speed %u\n", speed);
+                       return -EINVAL;
+               }
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+@@ -125,6 +125,7 @@
+ #include <linux/of_net.h>
+ #include <linux/of_address.h>
+ #include <linux/of_platform.h>
++#include <linux/of_device.h>
+ #include <linux/clk.h>
+ #include <linux/property.h>
+ #include <linux/acpi.h>
+@@ -145,42 +146,6 @@ MODULE_PARM_DESC(debug, " Network interf
+ static const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
+                                     NETIF_MSG_IFUP);
+-static const u32 xgbe_serdes_blwc[] = {
+-      XGBE_SPEED_1000_BLWC,
+-      XGBE_SPEED_2500_BLWC,
+-      XGBE_SPEED_10000_BLWC,
+-};
+-
+-static const u32 xgbe_serdes_cdr_rate[] = {
+-      XGBE_SPEED_1000_CDR,
+-      XGBE_SPEED_2500_CDR,
+-      XGBE_SPEED_10000_CDR,
+-};
+-
+-static const u32 xgbe_serdes_pq_skew[] = {
+-      XGBE_SPEED_1000_PQ,
+-      XGBE_SPEED_2500_PQ,
+-      XGBE_SPEED_10000_PQ,
+-};
+-
+-static const u32 xgbe_serdes_tx_amp[] = {
+-      XGBE_SPEED_1000_TXAMP,
+-      XGBE_SPEED_2500_TXAMP,
+-      XGBE_SPEED_10000_TXAMP,
+-};
+-
+-static const u32 xgbe_serdes_dfe_tap_cfg[] = {
+-      XGBE_SPEED_1000_DFE_TAP_CONFIG,
+-      XGBE_SPEED_2500_DFE_TAP_CONFIG,
+-      XGBE_SPEED_10000_DFE_TAP_CONFIG,
+-};
+-
+-static const u32 xgbe_serdes_dfe_tap_ena[] = {
+-      XGBE_SPEED_1000_DFE_TAP_ENABLE,
+-      XGBE_SPEED_2500_DFE_TAP_ENABLE,
+-      XGBE_SPEED_10000_DFE_TAP_ENABLE,
+-};
+-
+ static void xgbe_default_config(struct xgbe_prv_data *pdata)
+ {
+       DBGPR("-->xgbe_default_config\n");
+@@ -207,9 +172,22 @@ static void xgbe_init_all_fptrs(struct x
+       xgbe_init_function_ptrs_dev(&pdata->hw_if);
+       xgbe_init_function_ptrs_phy(&pdata->phy_if);
+       xgbe_init_function_ptrs_desc(&pdata->desc_if);
++
++      pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if);
+ }
+ #ifdef CONFIG_ACPI
++static const struct acpi_device_id xgbe_acpi_match[];
++
++static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
++{
++      const struct acpi_device_id *id;
++
++      id = acpi_match_device(xgbe_acpi_match, pdata->dev);
++
++      return id ? (struct xgbe_version_data *)id->driver_data : NULL;
++}
++
+ static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
+ {
+       struct device *dev = pdata->dev;
+@@ -237,6 +215,11 @@ static int xgbe_acpi_support(struct xgbe
+       return 0;
+ }
+ #else   /* CONFIG_ACPI */
++static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
++{
++      return NULL;
++}
++
+ static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
+ {
+       return -EINVAL;
+@@ -244,6 +227,17 @@ static int xgbe_acpi_support(struct xgbe
+ #endif  /* CONFIG_ACPI */
+ #ifdef CONFIG_OF
++static const struct of_device_id xgbe_of_match[];
++
++static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
++{
++      const struct of_device_id *id;
++
++      id = of_match_device(xgbe_of_match, pdata->dev);
++
++      return id ? (struct xgbe_version_data *)id->data : NULL;
++}
++
+ static int xgbe_of_support(struct xgbe_prv_data *pdata)
+ {
+       struct device *dev = pdata->dev;
+@@ -292,6 +286,11 @@ static struct platform_device *xgbe_of_g
+       return phy_pdev;
+ }
+ #else   /* CONFIG_OF */
++static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
++{
++      return NULL;
++}
++
+ static int xgbe_of_support(struct xgbe_prv_data *pdata)
+ {
+       return -EINVAL;
+@@ -333,11 +332,17 @@ static struct platform_device *xgbe_get_
+       return phy_pdev;
+ }
++static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata)
++{
++      return pdata->use_acpi ? xgbe_acpi_vdata(pdata)
++                             : xgbe_of_vdata(pdata);
++}
++
+ static int xgbe_probe(struct platform_device *pdev)
+ {
+       struct xgbe_prv_data *pdata;
+       struct net_device *netdev;
+-      struct device *dev = &pdev->dev, *phy_dev;
++      struct device *dev = &pdev->dev;
+       struct platform_device *phy_pdev;
+       struct resource *res;
+       const char *phy_mode;
+@@ -374,13 +379,17 @@ static int xgbe_probe(struct platform_de
+       /* Check if we should use ACPI or DT */
+       pdata->use_acpi = dev->of_node ? 0 : 1;
++      /* Get the version data */
++      pdata->vdata = xgbe_get_vdata(pdata);
++
+       phy_pdev = xgbe_get_phy_pdev(pdata);
+       if (!phy_pdev) {
+               dev_err(dev, "unable to obtain phy device\n");
+               ret = -EINVAL;
+               goto err_phydev;
+       }
+-      phy_dev = &phy_pdev->dev;
++      pdata->phy_pdev = phy_pdev;
++      pdata->phy_dev = &phy_pdev->dev;
+       if (pdev == phy_pdev) {
+               /* New style device tree or ACPI:
+@@ -492,115 +501,6 @@ static int xgbe_probe(struct platform_de
+       if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY))
+               pdata->per_channel_irq = 1;
+-      /* Retrieve the PHY speedset */
+-      ret = device_property_read_u32(phy_dev, XGBE_SPEEDSET_PROPERTY,
+-                                     &pdata->speed_set);
+-      if (ret) {
+-              dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
+-              goto err_io;
+-      }
+-
+-      switch (pdata->speed_set) {
+-      case XGBE_SPEEDSET_1000_10000:
+-      case XGBE_SPEEDSET_2500_10000:
+-              break;
+-      default:
+-              dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
+-              ret = -EINVAL;
+-              goto err_io;
+-      }
+-
+-      /* Retrieve the PHY configuration properties */
+-      if (device_property_present(phy_dev, XGBE_BLWC_PROPERTY)) {
+-              ret = device_property_read_u32_array(phy_dev,
+-                                                   XGBE_BLWC_PROPERTY,
+-                                                   pdata->serdes_blwc,
+-                                                   XGBE_SPEEDS);
+-              if (ret) {
+-                      dev_err(dev, "invalid %s property\n",
+-                              XGBE_BLWC_PROPERTY);
+-                      goto err_io;
+-              }
+-      } else {
+-              memcpy(pdata->serdes_blwc, xgbe_serdes_blwc,
+-                     sizeof(pdata->serdes_blwc));
+-      }
+-
+-      if (device_property_present(phy_dev, XGBE_CDR_RATE_PROPERTY)) {
+-              ret = device_property_read_u32_array(phy_dev,
+-                                                   XGBE_CDR_RATE_PROPERTY,
+-                                                   pdata->serdes_cdr_rate,
+-                                                   XGBE_SPEEDS);
+-              if (ret) {
+-                      dev_err(dev, "invalid %s property\n",
+-                              XGBE_CDR_RATE_PROPERTY);
+-                      goto err_io;
+-              }
+-      } else {
+-              memcpy(pdata->serdes_cdr_rate, xgbe_serdes_cdr_rate,
+-                     sizeof(pdata->serdes_cdr_rate));
+-      }
+-
+-      if (device_property_present(phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
+-              ret = device_property_read_u32_array(phy_dev,
+-                                                   XGBE_PQ_SKEW_PROPERTY,
+-                                                   pdata->serdes_pq_skew,
+-                                                   XGBE_SPEEDS);
+-              if (ret) {
+-                      dev_err(dev, "invalid %s property\n",
+-                              XGBE_PQ_SKEW_PROPERTY);
+-                      goto err_io;
+-              }
+-      } else {
+-              memcpy(pdata->serdes_pq_skew, xgbe_serdes_pq_skew,
+-                     sizeof(pdata->serdes_pq_skew));
+-      }
+-
+-      if (device_property_present(phy_dev, XGBE_TX_AMP_PROPERTY)) {
+-              ret = device_property_read_u32_array(phy_dev,
+-                                                   XGBE_TX_AMP_PROPERTY,
+-                                                   pdata->serdes_tx_amp,
+-                                                   XGBE_SPEEDS);
+-              if (ret) {
+-                      dev_err(dev, "invalid %s property\n",
+-                              XGBE_TX_AMP_PROPERTY);
+-                      goto err_io;
+-              }
+-      } else {
+-              memcpy(pdata->serdes_tx_amp, xgbe_serdes_tx_amp,
+-                     sizeof(pdata->serdes_tx_amp));
+-      }
+-
+-      if (device_property_present(phy_dev, XGBE_DFE_CFG_PROPERTY)) {
+-              ret = device_property_read_u32_array(phy_dev,
+-                                                   XGBE_DFE_CFG_PROPERTY,
+-                                                   pdata->serdes_dfe_tap_cfg,
+-                                                   XGBE_SPEEDS);
+-              if (ret) {
+-                      dev_err(dev, "invalid %s property\n",
+-                              XGBE_DFE_CFG_PROPERTY);
+-                      goto err_io;
+-              }
+-      } else {
+-              memcpy(pdata->serdes_dfe_tap_cfg, xgbe_serdes_dfe_tap_cfg,
+-                     sizeof(pdata->serdes_dfe_tap_cfg));
+-      }
+-
+-      if (device_property_present(phy_dev, XGBE_DFE_ENA_PROPERTY)) {
+-              ret = device_property_read_u32_array(phy_dev,
+-                                                   XGBE_DFE_ENA_PROPERTY,
+-                                                   pdata->serdes_dfe_tap_ena,
+-                                                   XGBE_SPEEDS);
+-              if (ret) {
+-                      dev_err(dev, "invalid %s property\n",
+-                              XGBE_DFE_ENA_PROPERTY);
+-                      goto err_io;
+-              }
+-      } else {
+-              memcpy(pdata->serdes_dfe_tap_ena, xgbe_serdes_dfe_tap_ena,
+-                     sizeof(pdata->serdes_dfe_tap_ena));
+-      }
+-
+       /* Obtain device settings unique to ACPI/OF */
+       if (pdata->use_acpi)
+               ret = xgbe_acpi_support(pdata);
+@@ -704,7 +604,9 @@ static int xgbe_probe(struct platform_de
+       XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
+       /* Call MDIO/PHY initialization routine */
+-      pdata->phy_if.phy_init(pdata);
++      ret = pdata->phy_if.phy_init(pdata);
++      if (ret)
++              goto err_io;
+       /* Set device operations */
+       netdev->netdev_ops = xgbe_get_netdev_ops();
+@@ -777,8 +679,6 @@ static int xgbe_probe(struct platform_de
+       xgbe_debugfs_init(pdata);
+-      platform_device_put(phy_pdev);
+-
+       netdev_notice(netdev, "net device enabled\n");
+       DBGPR("<-- xgbe_probe\n");
+@@ -814,6 +714,8 @@ static int xgbe_remove(struct platform_d
+       xgbe_ptp_unregister(pdata);
++      pdata->phy_if.phy_exit(pdata);
++
+       flush_workqueue(pdata->an_workqueue);
+       destroy_workqueue(pdata->an_workqueue);
+@@ -822,6 +724,8 @@ static int xgbe_remove(struct platform_d
+       unregister_netdev(netdev);
++      platform_device_put(pdata->phy_pdev);
++
+       free_netdev(netdev);
+       DBGPR("<--xgbe_remove\n");
+@@ -876,9 +780,14 @@ static int xgbe_resume(struct device *de
+ }
+ #endif /* CONFIG_PM_SLEEP */
++static const struct xgbe_version_data xgbe_v1 = {
++      .init_function_ptrs_phy_impl    = xgbe_init_function_ptrs_phy_v1,
++};
++
+ #ifdef CONFIG_ACPI
+ static const struct acpi_device_id xgbe_acpi_match[] = {
+-      { "AMDI8001", 0 },
++      { .id = "AMDI8001",
++        .driver_data = (kernel_ulong_t)&xgbe_v1 },
+       {},
+ };
+@@ -887,7 +796,8 @@ MODULE_DEVICE_TABLE(acpi, xgbe_acpi_matc
+ #ifdef CONFIG_OF
+ static const struct of_device_id xgbe_of_match[] = {
+-      { .compatible = "amd,xgbe-seattle-v1a", },
++      { .compatible = "amd,xgbe-seattle-v1a",
++        .data = &xgbe_v1 },
+       {},
+ };
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+@@ -145,280 +145,91 @@ static void xgbe_an_disable_kr_training(
+       XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+ }
+-static void xgbe_pcs_power_cycle(struct xgbe_prv_data *pdata)
++static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int reg;
+-
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+-
+-      reg |= MDIO_CTRL1_LPOWER;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+-
+-      usleep_range(75, 100);
+-
+-      reg &= ~MDIO_CTRL1_LPOWER;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+-}
+-
+-static void xgbe_serdes_start_ratechange(struct xgbe_prv_data *pdata)
+-{
+-      /* Assert Rx and Tx ratechange */
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
+-}
+-
+-static void xgbe_serdes_complete_ratechange(struct xgbe_prv_data *pdata)
+-{
+-      unsigned int wait;
+-      u16 status;
+-
+-      /* Release Rx and Tx ratechange */
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
+-
+-      /* Wait for Rx and Tx ready */
+-      wait = XGBE_RATECHANGE_COUNT;
+-      while (wait--) {
+-              usleep_range(50, 75);
+-
+-              status = XSIR0_IOREAD(pdata, SIR0_STATUS);
+-              if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
+-                  XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
+-                      goto rx_reset;
+-      }
+-
+-      netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
+-                status);
+-
+-rx_reset:
+-      /* Perform Rx reset for the DFE changes */
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
+-}
+-
+-static void xgbe_xgmii_mode(struct xgbe_prv_data *pdata)
+-{
+-      unsigned int reg;
+-
+       /* Enable KR training */
+       xgbe_an_enable_kr_training(pdata);
+       /* Set MAC to 10G speed */
+-      pdata->hw_if.set_xgmii_speed(pdata);
+-
+-      /* Set PCS to KR/10G speed */
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+-      reg &= ~MDIO_PCS_CTRL2_TYPE;
+-      reg |= MDIO_PCS_CTRL2_10GBR;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+-
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+-      reg &= ~MDIO_CTRL1_SPEEDSEL;
+-      reg |= MDIO_CTRL1_SPEED10G;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+-
+-      xgbe_pcs_power_cycle(pdata);
+-
+-      /* Set SerDes to 10G speed */
+-      xgbe_serdes_start_ratechange(pdata);
+-
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
+-
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+-                         pdata->serdes_cdr_rate[XGBE_SPEED_10000]);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+-                         pdata->serdes_tx_amp[XGBE_SPEED_10000]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+-                         pdata->serdes_blwc[XGBE_SPEED_10000]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+-                         pdata->serdes_pq_skew[XGBE_SPEED_10000]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+-                         pdata->serdes_dfe_tap_cfg[XGBE_SPEED_10000]);
+-      XRXTX_IOWRITE(pdata, RXTX_REG22,
+-                    pdata->serdes_dfe_tap_ena[XGBE_SPEED_10000]);
+-
+-      xgbe_serdes_complete_ratechange(pdata);
++      pdata->hw_if.set_speed(pdata, SPEED_10000);
+-      netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
++      /* Call PHY implementation support to complete rate change */
++      pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
+ }
+-static void xgbe_gmii_2500_mode(struct xgbe_prv_data *pdata)
++static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int reg;
+-
+       /* Disable KR training */
+       xgbe_an_disable_kr_training(pdata);
+       /* Set MAC to 2.5G speed */
+-      pdata->hw_if.set_gmii_2500_speed(pdata);
+-
+-      /* Set PCS to KX/1G speed */
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+-      reg &= ~MDIO_PCS_CTRL2_TYPE;
+-      reg |= MDIO_PCS_CTRL2_10GBX;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+-
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+-      reg &= ~MDIO_CTRL1_SPEEDSEL;
+-      reg |= MDIO_CTRL1_SPEED1G;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+-
+-      xgbe_pcs_power_cycle(pdata);
+-
+-      /* Set SerDes to 2.5G speed */
+-      xgbe_serdes_start_ratechange(pdata);
+-
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
+-
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+-                         pdata->serdes_cdr_rate[XGBE_SPEED_2500]);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+-                         pdata->serdes_tx_amp[XGBE_SPEED_2500]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+-                         pdata->serdes_blwc[XGBE_SPEED_2500]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+-                         pdata->serdes_pq_skew[XGBE_SPEED_2500]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+-                         pdata->serdes_dfe_tap_cfg[XGBE_SPEED_2500]);
+-      XRXTX_IOWRITE(pdata, RXTX_REG22,
+-                    pdata->serdes_dfe_tap_ena[XGBE_SPEED_2500]);
+-
+-      xgbe_serdes_complete_ratechange(pdata);
++      pdata->hw_if.set_speed(pdata, SPEED_2500);
+-      netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
++      /* Call PHY implementation support to complete rate change */
++      pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
+ }
+-static void xgbe_gmii_mode(struct xgbe_prv_data *pdata)
++static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int reg;
+-
+       /* Disable KR training */
+       xgbe_an_disable_kr_training(pdata);
+       /* Set MAC to 1G speed */
+-      pdata->hw_if.set_gmii_speed(pdata);
+-
+-      /* Set PCS to KX/1G speed */
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+-      reg &= ~MDIO_PCS_CTRL2_TYPE;
+-      reg |= MDIO_PCS_CTRL2_10GBX;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+-
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+-      reg &= ~MDIO_CTRL1_SPEEDSEL;
+-      reg |= MDIO_CTRL1_SPEED1G;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+-
+-      xgbe_pcs_power_cycle(pdata);
+-
+-      /* Set SerDes to 1G speed */
+-      xgbe_serdes_start_ratechange(pdata);
+-
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
+-
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+-                         pdata->serdes_cdr_rate[XGBE_SPEED_1000]);
+-      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+-                         pdata->serdes_tx_amp[XGBE_SPEED_1000]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+-                         pdata->serdes_blwc[XGBE_SPEED_1000]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+-                         pdata->serdes_pq_skew[XGBE_SPEED_1000]);
+-      XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+-                         pdata->serdes_dfe_tap_cfg[XGBE_SPEED_1000]);
+-      XRXTX_IOWRITE(pdata, RXTX_REG22,
+-                    pdata->serdes_dfe_tap_ena[XGBE_SPEED_1000]);
++      pdata->hw_if.set_speed(pdata, SPEED_1000);
+-      xgbe_serdes_complete_ratechange(pdata);
+-
+-      netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
++      /* Call PHY implementation support to complete rate change */
++      pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
+ }
+-static void xgbe_cur_mode(struct xgbe_prv_data *pdata,
+-                        enum xgbe_mode *mode)
++static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int reg;
+-
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+-      if ((reg & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
+-              *mode = XGBE_MODE_KR;
+-      else
+-              *mode = XGBE_MODE_KX;
++      return pdata->phy_if.phy_impl.cur_mode(pdata);
+ }
+ static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
+ {
+-      enum xgbe_mode mode;
+-
+-      xgbe_cur_mode(pdata, &mode);
+-
+-      return (mode == XGBE_MODE_KR);
++      return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
+ }
+-static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
++static void xgbe_change_mode(struct xgbe_prv_data *pdata,
++                           enum xgbe_mode mode)
+ {
+-      /* If we are in KR switch to KX, and vice-versa */
+-      if (xgbe_in_kr_mode(pdata)) {
+-              if (pdata->speed_set == XGBE_SPEEDSET_1000_10000)
+-                      xgbe_gmii_mode(pdata);
+-              else
+-                      xgbe_gmii_2500_mode(pdata);
+-      } else {
+-              xgbe_xgmii_mode(pdata);
++      switch (mode) {
++      case XGBE_MODE_KX_1000:
++              xgbe_kx_1000_mode(pdata);
++              break;
++      case XGBE_MODE_KX_2500:
++              xgbe_kx_2500_mode(pdata);
++              break;
++      case XGBE_MODE_KR:
++              xgbe_kr_mode(pdata);
++              break;
++      case XGBE_MODE_UNKNOWN:
++              break;
++      default:
++              netif_dbg(pdata, link, pdata->netdev,
++                        "invalid operation mode requested (%u)\n", mode);
+       }
+ }
+-static void xgbe_set_mode(struct xgbe_prv_data *pdata,
+-                        enum xgbe_mode mode)
+-{
+-      enum xgbe_mode cur_mode;
+-
+-      xgbe_cur_mode(pdata, &cur_mode);
+-      if (mode != cur_mode)
+-              xgbe_switch_mode(pdata);
+-}
+-
+-static bool xgbe_use_xgmii_mode(struct xgbe_prv_data *pdata)
++static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
+ {
+-      if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+-              if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
+-                      return true;
+-      } else {
+-              if (pdata->phy.speed == SPEED_10000)
+-                      return true;
+-      }
+-
+-      return false;
++      xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
+ }
+-static bool xgbe_use_gmii_2500_mode(struct xgbe_prv_data *pdata)
++static void xgbe_set_mode(struct xgbe_prv_data *pdata,
++                        enum xgbe_mode mode)
+ {
+-      if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+-              if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
+-                      return true;
+-      } else {
+-              if (pdata->phy.speed == SPEED_2500)
+-                      return true;
+-      }
++      if (mode == xgbe_cur_mode(pdata))
++              return;
+-      return false;
++      xgbe_change_mode(pdata, mode);
+ }
+-static bool xgbe_use_gmii_mode(struct xgbe_prv_data *pdata)
++static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
++                        enum xgbe_mode mode)
+ {
+-      if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+-              if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
+-                      return true;
+-      } else {
+-              if (pdata->phy.speed == SPEED_1000)
+-                      return true;
+-      }
+-
+-      return false;
++      return pdata->phy_if.phy_impl.use_mode(pdata, mode);
+ }
+ static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart)
+@@ -476,13 +287,15 @@ static enum xgbe_an xgbe_an_tx_training(
+       /* Start KR training */
+       reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+       if (reg & XGBE_KR_TRAINING_ENABLE) {
+-              XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
++              if (pdata->phy_if.phy_impl.kr_training_pre)
++                      pdata->phy_if.phy_impl.kr_training_pre(pdata);
+               reg |= XGBE_KR_TRAINING_START;
+               XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
+                           reg);
+-              XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
++              if (pdata->phy_if.phy_impl.kr_training_post)
++                      pdata->phy_if.phy_impl.kr_training_post(pdata);
+               netif_dbg(pdata, link, pdata->netdev,
+                         "KR training initiated\n");
+@@ -571,7 +384,7 @@ static enum xgbe_an xgbe_an_page_receive
+       }
+       state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
+-                                         : &pdata->kx_state;
++                                     : &pdata->kx_state;
+       switch (*state) {
+       case XGBE_RX_BPA:
+@@ -907,24 +720,28 @@ static void xgbe_phy_adjust_link(struct
+               xgbe_phy_print_status(pdata);
+ }
++static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
++{
++      return pdata->phy_if.phy_impl.valid_speed(pdata, speed);
++}
++
+ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
+ {
++      enum xgbe_mode mode;
++
+       netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n");
+       /* Disable auto-negotiation */
+       xgbe_disable_an(pdata);
+-      /* Validate/Set specified speed */
+-      switch (pdata->phy.speed) {
+-      case SPEED_10000:
+-              xgbe_set_mode(pdata, XGBE_MODE_KR);
+-              break;
+-
+-      case SPEED_2500:
+-      case SPEED_1000:
+-              xgbe_set_mode(pdata, XGBE_MODE_KX);
++      /* Set specified mode for specified speed */
++      mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
++      switch (mode) {
++      case XGBE_MODE_KX_1000:
++      case XGBE_MODE_KX_2500:
++      case XGBE_MODE_KR:
+               break;
+-
++      case XGBE_MODE_UNKNOWN:
+       default:
+               return -EINVAL;
+       }
+@@ -933,6 +750,8 @@ static int xgbe_phy_config_fixed(struct
+       if (pdata->phy.duplex != DUPLEX_FULL)
+               return -EINVAL;
++      xgbe_set_mode(pdata, mode);
++
+       return 0;
+ }
+@@ -950,11 +769,12 @@ static int __xgbe_phy_config_aneg(struct
+       disable_irq(pdata->an_irq);
+       /* Start auto-negotiation in a supported mode */
+-      if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) {
++      if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
+               xgbe_set_mode(pdata, XGBE_MODE_KR);
+-      } else if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
+-                 (pdata->phy.advertising & ADVERTISED_2500baseX_Full)) {
+-              xgbe_set_mode(pdata, XGBE_MODE_KX);
++      } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
++              xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
++      } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
++              xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
+       } else {
+               enable_irq(pdata->an_irq);
+               return -EINVAL;
+@@ -1016,108 +836,45 @@ static void xgbe_check_link_timeout(stru
+       }
+ }
+-static void xgbe_phy_status_force(struct xgbe_prv_data *pdata)
++static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
+ {
+-      if (xgbe_in_kr_mode(pdata)) {
+-              pdata->phy.speed = SPEED_10000;
+-      } else {
+-              switch (pdata->speed_set) {
+-              case XGBE_SPEEDSET_1000_10000:
+-                      pdata->phy.speed = SPEED_1000;
+-                      break;
+-
+-              case XGBE_SPEEDSET_2500_10000:
+-                      pdata->phy.speed = SPEED_2500;
+-                      break;
+-              }
+-      }
+-      pdata->phy.duplex = DUPLEX_FULL;
++      return pdata->phy_if.phy_impl.an_outcome(pdata);
+ }
+-static void xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
++static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int ad_reg, lp_reg;
++      enum xgbe_mode mode;
+       pdata->phy.lp_advertising = 0;
+       if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
+-              return xgbe_phy_status_force(pdata);
+-
+-      pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+-      pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+-
+-      /* Compare Advertisement and Link Partner register 1 */
+-      ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
+-      lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
+-      if (lp_reg & 0x400)
+-              pdata->phy.lp_advertising |= ADVERTISED_Pause;
+-      if (lp_reg & 0x800)
+-              pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+-
+-      if (pdata->phy.pause_autoneg) {
+-              /* Set flow control based on auto-negotiation result */
+-              pdata->phy.tx_pause = 0;
+-              pdata->phy.rx_pause = 0;
+-
+-              if (ad_reg & lp_reg & 0x400) {
+-                      pdata->phy.tx_pause = 1;
+-                      pdata->phy.rx_pause = 1;
+-              } else if (ad_reg & lp_reg & 0x800) {
+-                      if (ad_reg & 0x400)
+-                              pdata->phy.rx_pause = 1;
+-                      else if (lp_reg & 0x400)
+-                              pdata->phy.tx_pause = 1;
+-              }
+-      }
+-
+-      /* Compare Advertisement and Link Partner register 2 */
+-      ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+-      lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+-      if (lp_reg & 0x80)
+-              pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+-      if (lp_reg & 0x20) {
+-              switch (pdata->speed_set) {
+-              case XGBE_SPEEDSET_1000_10000:
+-                      pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+-                      break;
+-              case XGBE_SPEEDSET_2500_10000:
+-                      pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
+-                      break;
+-              }
+-      }
++              mode = xgbe_cur_mode(pdata);
++      else
++              mode = xgbe_phy_status_aneg(pdata);
+-      ad_reg &= lp_reg;
+-      if (ad_reg & 0x80) {
++      switch (mode) {
++      case XGBE_MODE_KX_1000:
++              pdata->phy.speed = SPEED_1000;
++              break;
++      case XGBE_MODE_KX_2500:
++              pdata->phy.speed = SPEED_2500;
++              break;
++      case XGBE_MODE_KR:
+               pdata->phy.speed = SPEED_10000;
+-              xgbe_set_mode(pdata, XGBE_MODE_KR);
+-      } else if (ad_reg & 0x20) {
+-              switch (pdata->speed_set) {
+-              case XGBE_SPEEDSET_1000_10000:
+-                      pdata->phy.speed = SPEED_1000;
+-                      break;
+-
+-              case XGBE_SPEEDSET_2500_10000:
+-                      pdata->phy.speed = SPEED_2500;
+-                      break;
+-              }
+-
+-              xgbe_set_mode(pdata, XGBE_MODE_KX);
+-      } else {
++              break;
++      case XGBE_MODE_UNKNOWN:
++      default:
+               pdata->phy.speed = SPEED_UNKNOWN;
+       }
+-      /* Compare Advertisement and Link Partner register 3 */
+-      ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+-      lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+-      if (lp_reg & 0xc000)
+-              pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+-
+       pdata->phy.duplex = DUPLEX_FULL;
++
++      xgbe_set_mode(pdata, mode);
+ }
+ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int reg, link_aneg;
++      unsigned int link_aneg;
+       if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
+               netif_carrier_off(pdata->netdev);
+@@ -1128,20 +885,14 @@ static void xgbe_phy_status(struct xgbe_
+       link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
+-      /* Get the link status. Link status is latched low, so read
+-       * once to clear and then read again to get current state
+-       */
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+-      pdata->phy.link = (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
+-
++      pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata);
+       if (pdata->phy.link) {
+               if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
+                       xgbe_check_link_timeout(pdata);
+                       return;
+               }
+-              xgbe_phy_status_aneg(pdata);
++              xgbe_phy_status_result(pdata);
+               if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
+                       clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
+@@ -1155,7 +906,7 @@ static void xgbe_phy_status(struct xgbe_
+                               return;
+               }
+-              xgbe_phy_status_aneg(pdata);
++              xgbe_phy_status_result(pdata);
+               netif_carrier_off(pdata->netdev);
+       }
+@@ -1168,6 +919,12 @@ static void xgbe_phy_stop(struct xgbe_pr
+ {
+       netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n");
++      if (!pdata->phy_started)
++              return;
++
++      /* Indicate the PHY is down */
++      pdata->phy_started = 0;
++
+       /* Disable auto-negotiation */
+       xgbe_disable_an(pdata);
+@@ -1176,6 +933,8 @@ static void xgbe_phy_stop(struct xgbe_pr
+       devm_free_irq(pdata->dev, pdata->an_irq, pdata);
++      pdata->phy_if.phy_impl.stop(pdata);
++
+       pdata->phy.link = 0;
+       netif_carrier_off(pdata->netdev);
+@@ -1189,28 +948,35 @@ static int xgbe_phy_start(struct xgbe_pr
+       netif_dbg(pdata, link, pdata->netdev, "starting PHY\n");
++      ret = pdata->phy_if.phy_impl.start(pdata);
++      if (ret)
++              return ret;
++
+       ret = devm_request_irq(pdata->dev, pdata->an_irq,
+                              xgbe_an_isr, 0, pdata->an_name,
+                              pdata);
+       if (ret) {
+               netdev_err(netdev, "phy irq request failed\n");
+-              return ret;
++              goto err_stop;
+       }
+       /* Set initial mode - call the mode setting routines
+        * directly to insure we are properly configured
+        */
+-      if (xgbe_use_xgmii_mode(pdata)) {
+-              xgbe_xgmii_mode(pdata);
+-      } else if (xgbe_use_gmii_mode(pdata)) {
+-              xgbe_gmii_mode(pdata);
+-      } else if (xgbe_use_gmii_2500_mode(pdata)) {
+-              xgbe_gmii_2500_mode(pdata);
++      if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
++              xgbe_kr_mode(pdata);
++      } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
++              xgbe_kx_2500_mode(pdata);
++      } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
++              xgbe_kx_1000_mode(pdata);
+       } else {
+               ret = -EINVAL;
+               goto err_irq;
+       }
++      /* Indicate the PHY is up and running */
++      pdata->phy_started = 1;
++
+       /* Set up advertisement registers based on current settings */
+       xgbe_an_init(pdata);
+@@ -1222,25 +988,19 @@ static int xgbe_phy_start(struct xgbe_pr
+ err_irq:
+       devm_free_irq(pdata->dev, pdata->an_irq, pdata);
++err_stop:
++      pdata->phy_if.phy_impl.stop(pdata);
++
+       return ret;
+ }
+ static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
+ {
+-      unsigned int count, reg;
+-
+-      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+-      reg |= MDIO_CTRL1_RESET;
+-      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+-
+-      count = 50;
+-      do {
+-              msleep(20);
+-              reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+-      } while ((reg & MDIO_CTRL1_RESET) && --count);
++      int ret;
+-      if (reg & MDIO_CTRL1_RESET)
+-              return -ETIMEDOUT;
++      ret = pdata->phy_if.phy_impl.reset(pdata);
++      if (ret)
++              return ret;
+       /* Disable auto-negotiation for now */
+       xgbe_disable_an(pdata);
+@@ -1290,41 +1050,57 @@ static void xgbe_dump_phy_registers(stru
+       dev_dbg(dev, "\n*************************************************\n");
+ }
+-static void xgbe_phy_init(struct xgbe_prv_data *pdata)
++static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
++{
++      if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
++              return SPEED_10000;
++      else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
++              return SPEED_2500;
++      else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
++              return SPEED_1000;
++
++      return SPEED_UNKNOWN;
++}
++
++static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+ {
++      xgbe_phy_stop(pdata);
++
++      pdata->phy_if.phy_impl.exit(pdata);
++}
++
++static int xgbe_phy_init(struct xgbe_prv_data *pdata)
++{
++      int ret;
++
+       mutex_init(&pdata->an_mutex);
+       INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work);
+       INIT_WORK(&pdata->an_work, xgbe_an_state_machine);
+       pdata->mdio_mmd = MDIO_MMD_PCS;
+-      /* Initialize supported features */
+-      pdata->phy.supported = SUPPORTED_Autoneg;
+-      pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+-      pdata->phy.supported |= SUPPORTED_Backplane;
+-      pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
+-      switch (pdata->speed_set) {
+-      case XGBE_SPEEDSET_1000_10000:
+-              pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
+-              break;
+-      case XGBE_SPEEDSET_2500_10000:
+-              pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+-              break;
+-      }
+-
++      /* Check for FEC support */
+       pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
+                                       MDIO_PMA_10GBR_FECABLE);
+       pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
+                              MDIO_PMA_10GBR_FECABLE_ERRABLE);
+-      if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+-              pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
++      /* Setup the phy (including supported features) */
++      ret = pdata->phy_if.phy_impl.init(pdata);
++      if (ret)
++              return ret;
+       pdata->phy.advertising = pdata->phy.supported;
+       pdata->phy.address = 0;
+-      pdata->phy.autoneg = AUTONEG_ENABLE;
+-      pdata->phy.speed = SPEED_UNKNOWN;
+-      pdata->phy.duplex = DUPLEX_UNKNOWN;
++      if (pdata->phy.advertising & ADVERTISED_Autoneg) {
++              pdata->phy.autoneg = AUTONEG_ENABLE;
++              pdata->phy.speed = SPEED_UNKNOWN;
++              pdata->phy.duplex = DUPLEX_UNKNOWN;
++      } else {
++              pdata->phy.autoneg = AUTONEG_DISABLE;
++              pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
++              pdata->phy.duplex = DUPLEX_FULL;
++      }
+       pdata->phy.link = 0;
+@@ -1346,11 +1122,14 @@ static void xgbe_phy_init(struct xgbe_pr
+       if (netif_msg_drv(pdata))
+               xgbe_dump_phy_registers(pdata);
++
++      return 0;
+ }
+ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
+ {
+       phy_if->phy_init        = xgbe_phy_init;
++      phy_if->phy_exit        = xgbe_phy_exit;
+       phy_if->phy_reset       = xgbe_phy_reset;
+       phy_if->phy_start       = xgbe_phy_start;
+@@ -1358,4 +1137,6 @@ void xgbe_init_function_ptrs_phy(struct
+       phy_if->phy_status      = xgbe_phy_status;
+       phy_if->phy_config_aneg = xgbe_phy_config_aneg;
++
++      phy_if->phy_valid_speed = xgbe_phy_valid_speed;
+ }
+--- /dev/null
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
+@@ -0,0 +1,821 @@
++/*
++ * AMD 10Gb Ethernet driver
++ *
++ * This file is available to you under your choice of the following two
++ * licenses:
++ *
++ * License 1: GPLv2
++ *
++ * Copyright (c) 2016 Advanced Micro Devices, Inc.
++ *
++ * This file is free software; you may copy, redistribute and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 2 of the License, or (at
++ * your option) any later version.
++ *
++ * This file is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ *
++ * This file incorporates work covered by the following copyright and
++ * permission notice:
++ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
++ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
++ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
++ *     and you.
++ *
++ *     The Software IS NOT an item of Licensed Software or Licensed Product
++ *     under any End User Software License Agreement or Agreement for Licensed
++ *     Product with Synopsys or any supplement thereto.  Permission is hereby
++ *     granted, free of charge, to any person obtaining a copy of this software
++ *     annotated with this license and the Software, to deal in the Software
++ *     without restriction, including without limitation the rights to use,
++ *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
++ *     of the Software, and to permit persons to whom the Software is furnished
++ *     to do so, subject to the following conditions:
++ *
++ *     The above copyright notice and this permission notice shall be included
++ *     in all copies or substantial portions of the Software.
++ *
++ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
++ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
++ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
++ *     THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *
++ * License 2: Modified BSD
++ *
++ * Copyright (c) 2016 Advanced Micro Devices, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *     * Redistributions of source code must retain the above copyright
++ *       notice, this list of conditions and the following disclaimer.
++ *     * Redistributions in binary form must reproduce the above copyright
++ *       notice, this list of conditions and the following disclaimer in the
++ *       documentation and/or other materials provided with the distribution.
++ *     * Neither the name of Advanced Micro Devices, Inc. nor the
++ *       names of its contributors may be used to endorse or promote products
++ *       derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file incorporates work covered by the following copyright and
++ * permission notice:
++ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
++ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
++ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
++ *     and you.
++ *
++ *     The Software IS NOT an item of Licensed Software or Licensed Product
++ *     under any End User Software License Agreement or Agreement for Licensed
++ *     Product with Synopsys or any supplement thereto.  Permission is hereby
++ *     granted, free of charge, to any person obtaining a copy of this software
++ *     annotated with this license and the Software, to deal in the Software
++ *     without restriction, including without limitation the rights to use,
++ *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
++ *     of the Software, and to permit persons to whom the Software is furnished
++ *     to do so, subject to the following conditions:
++ *
++ *     The above copyright notice and this permission notice shall be included
++ *     in all copies or substantial portions of the Software.
++ *
++ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
++ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
++ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
++ *     THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <linux/module.h>
++#include <linux/kmod.h>
++#include <linux/device.h>
++#include <linux/property.h>
++#include <linux/mdio.h>
++#include <linux/phy.h>
++
++#include "xgbe.h"
++#include "xgbe-common.h"
++
++#define XGBE_BLWC_PROPERTY            "amd,serdes-blwc"
++#define XGBE_CDR_RATE_PROPERTY                "amd,serdes-cdr-rate"
++#define XGBE_PQ_SKEW_PROPERTY         "amd,serdes-pq-skew"
++#define XGBE_TX_AMP_PROPERTY          "amd,serdes-tx-amp"
++#define XGBE_DFE_CFG_PROPERTY         "amd,serdes-dfe-tap-config"
++#define XGBE_DFE_ENA_PROPERTY         "amd,serdes-dfe-tap-enable"
++
++/* Default SerDes settings */
++#define XGBE_SPEED_1000_BLWC          1
++#define XGBE_SPEED_1000_CDR           0x2
++#define XGBE_SPEED_1000_PLL           0x0
++#define XGBE_SPEED_1000_PQ            0xa
++#define XGBE_SPEED_1000_RATE          0x3
++#define XGBE_SPEED_1000_TXAMP         0xf
++#define XGBE_SPEED_1000_WORD          0x1
++#define XGBE_SPEED_1000_DFE_TAP_CONFIG        0x3
++#define XGBE_SPEED_1000_DFE_TAP_ENABLE        0x0
++
++#define XGBE_SPEED_2500_BLWC          1
++#define XGBE_SPEED_2500_CDR           0x2
++#define XGBE_SPEED_2500_PLL           0x0
++#define XGBE_SPEED_2500_PQ            0xa
++#define XGBE_SPEED_2500_RATE          0x1
++#define XGBE_SPEED_2500_TXAMP         0xf
++#define XGBE_SPEED_2500_WORD          0x1
++#define XGBE_SPEED_2500_DFE_TAP_CONFIG        0x3
++#define XGBE_SPEED_2500_DFE_TAP_ENABLE        0x0
++
++#define XGBE_SPEED_10000_BLWC         0
++#define XGBE_SPEED_10000_CDR          0x7
++#define XGBE_SPEED_10000_PLL          0x1
++#define XGBE_SPEED_10000_PQ           0x12
++#define XGBE_SPEED_10000_RATE         0x0
++#define XGBE_SPEED_10000_TXAMP                0xa
++#define XGBE_SPEED_10000_WORD         0x7
++#define XGBE_SPEED_10000_DFE_TAP_CONFIG       0x1
++#define XGBE_SPEED_10000_DFE_TAP_ENABLE       0x7f
++
++/* Rate-change complete wait/retry count */
++#define XGBE_RATECHANGE_COUNT         500
++
++static const u32 xgbe_phy_blwc[] = {
++      XGBE_SPEED_1000_BLWC,
++      XGBE_SPEED_2500_BLWC,
++      XGBE_SPEED_10000_BLWC,
++};
++
++static const u32 xgbe_phy_cdr_rate[] = {
++      XGBE_SPEED_1000_CDR,
++      XGBE_SPEED_2500_CDR,
++      XGBE_SPEED_10000_CDR,
++};
++
++static const u32 xgbe_phy_pq_skew[] = {
++      XGBE_SPEED_1000_PQ,
++      XGBE_SPEED_2500_PQ,
++      XGBE_SPEED_10000_PQ,
++};
++
++static const u32 xgbe_phy_tx_amp[] = {
++      XGBE_SPEED_1000_TXAMP,
++      XGBE_SPEED_2500_TXAMP,
++      XGBE_SPEED_10000_TXAMP,
++};
++
++static const u32 xgbe_phy_dfe_tap_cfg[] = {
++      XGBE_SPEED_1000_DFE_TAP_CONFIG,
++      XGBE_SPEED_2500_DFE_TAP_CONFIG,
++      XGBE_SPEED_10000_DFE_TAP_CONFIG,
++};
++
++static const u32 xgbe_phy_dfe_tap_ena[] = {
++      XGBE_SPEED_1000_DFE_TAP_ENABLE,
++      XGBE_SPEED_2500_DFE_TAP_ENABLE,
++      XGBE_SPEED_10000_DFE_TAP_ENABLE,
++};
++
++struct xgbe_phy_data {
++      /* 1000/10000 vs 2500/10000 indicator */
++      unsigned int speed_set;
++
++      /* SerDes UEFI configurable settings.
++       *   Switching between modes/speeds requires new values for some
++       *   SerDes settings.  The values can be supplied as device
++       *   properties in array format.  The first array entry is for
++       *   1GbE, second for 2.5GbE and third for 10GbE
++       */
++      u32 blwc[XGBE_SPEEDS];
++      u32 cdr_rate[XGBE_SPEEDS];
++      u32 pq_skew[XGBE_SPEEDS];
++      u32 tx_amp[XGBE_SPEEDS];
++      u32 dfe_tap_cfg[XGBE_SPEEDS];
++      u32 dfe_tap_ena[XGBE_SPEEDS];
++};
++
++static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
++{
++              XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
++}
++
++static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
++{
++              XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
++}
++
++static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++      enum xgbe_mode mode;
++      unsigned int ad_reg, lp_reg;
++
++      pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
++      pdata->phy.lp_advertising |= ADVERTISED_Backplane;
++
++      /* Compare Advertisement and Link Partner register 1 */
++      ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
++      lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
++      if (lp_reg & 0x400)
++              pdata->phy.lp_advertising |= ADVERTISED_Pause;
++      if (lp_reg & 0x800)
++              pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
++
++      if (pdata->phy.pause_autoneg) {
++              /* Set flow control based on auto-negotiation result */
++              pdata->phy.tx_pause = 0;
++              pdata->phy.rx_pause = 0;
++
++              if (ad_reg & lp_reg & 0x400) {
++                      pdata->phy.tx_pause = 1;
++                      pdata->phy.rx_pause = 1;
++              } else if (ad_reg & lp_reg & 0x800) {
++                      if (ad_reg & 0x400)
++                              pdata->phy.rx_pause = 1;
++                      else if (lp_reg & 0x400)
++                              pdata->phy.tx_pause = 1;
++              }
++      }
++
++      /* Compare Advertisement and Link Partner register 2 */
++      ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
++      lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
++      if (lp_reg & 0x80)
++              pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
++      if (lp_reg & 0x20) {
++              if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
++                      pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
++              else
++                      pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
++      }
++
++      ad_reg &= lp_reg;
++      if (ad_reg & 0x80) {
++              mode = XGBE_MODE_KR;
++      } else if (ad_reg & 0x20) {
++              if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
++                      mode = XGBE_MODE_KX_2500;
++              else
++                      mode = XGBE_MODE_KX_1000;
++      } else {
++              mode = XGBE_MODE_UNKNOWN;
++      }
++
++      /* Compare Advertisement and Link Partner register 3 */
++      ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
++      lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
++      if (lp_reg & 0xc000)
++              pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
++
++      return mode;
++}
++
++static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
++{
++      unsigned int reg;
++
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
++
++      reg |= MDIO_CTRL1_LPOWER;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
++
++      usleep_range(75, 100);
++
++      reg &= ~MDIO_CTRL1_LPOWER;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
++}
++
++static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
++{
++      /* Assert Rx and Tx ratechange */
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
++}
++
++static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
++{
++      unsigned int wait;
++      u16 status;
++
++      /* Release Rx and Tx ratechange */
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
++
++      /* Wait for Rx and Tx ready */
++      wait = XGBE_RATECHANGE_COUNT;
++      while (wait--) {
++              usleep_range(50, 75);
++
++              status = XSIR0_IOREAD(pdata, SIR0_STATUS);
++              if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
++                  XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
++                      goto rx_reset;
++      }
++
++      netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
++                status);
++
++rx_reset:
++      /* Perform Rx reset for the DFE changes */
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
++}
++
++static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++      unsigned int reg;
++
++      /* Set PCS to KR/10G speed */
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
++      reg &= ~MDIO_PCS_CTRL2_TYPE;
++      reg |= MDIO_PCS_CTRL2_10GBR;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
++
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
++      reg &= ~MDIO_CTRL1_SPEEDSEL;
++      reg |= MDIO_CTRL1_SPEED10G;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
++
++      xgbe_phy_pcs_power_cycle(pdata);
++
++      /* Set SerDes to 10G speed */
++      xgbe_phy_start_ratechange(pdata);
++
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
++
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
++                         phy_data->cdr_rate[XGBE_SPEED_10000]);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
++                         phy_data->tx_amp[XGBE_SPEED_10000]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
++                         phy_data->blwc[XGBE_SPEED_10000]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
++                         phy_data->pq_skew[XGBE_SPEED_10000]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
++                         phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
++      XRXTX_IOWRITE(pdata, RXTX_REG22,
++                    phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
++
++      xgbe_phy_complete_ratechange(pdata);
++
++      netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
++}
++
++static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++      unsigned int reg;
++
++      /* Set PCS to KX/1G speed */
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
++      reg &= ~MDIO_PCS_CTRL2_TYPE;
++      reg |= MDIO_PCS_CTRL2_10GBX;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
++
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
++      reg &= ~MDIO_CTRL1_SPEEDSEL;
++      reg |= MDIO_CTRL1_SPEED1G;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
++
++      xgbe_phy_pcs_power_cycle(pdata);
++
++      /* Set SerDes to 2.5G speed */
++      xgbe_phy_start_ratechange(pdata);
++
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
++
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
++                         phy_data->cdr_rate[XGBE_SPEED_2500]);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
++                         phy_data->tx_amp[XGBE_SPEED_2500]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
++                         phy_data->blwc[XGBE_SPEED_2500]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
++                         phy_data->pq_skew[XGBE_SPEED_2500]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
++                         phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
++      XRXTX_IOWRITE(pdata, RXTX_REG22,
++                    phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
++
++      xgbe_phy_complete_ratechange(pdata);
++
++      netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
++}
++
++static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++      unsigned int reg;
++
++      /* Set PCS to KX/1G speed */
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
++      reg &= ~MDIO_PCS_CTRL2_TYPE;
++      reg |= MDIO_PCS_CTRL2_10GBX;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
++
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
++      reg &= ~MDIO_CTRL1_SPEEDSEL;
++      reg |= MDIO_CTRL1_SPEED1G;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
++
++      xgbe_phy_pcs_power_cycle(pdata);
++
++      /* Set SerDes to 1G speed */
++      xgbe_phy_start_ratechange(pdata);
++
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
++
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
++                         phy_data->cdr_rate[XGBE_SPEED_1000]);
++      XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
++                         phy_data->tx_amp[XGBE_SPEED_1000]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
++                         phy_data->blwc[XGBE_SPEED_1000]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
++                         phy_data->pq_skew[XGBE_SPEED_1000]);
++      XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
++                         phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
++      XRXTX_IOWRITE(pdata, RXTX_REG22,
++                    phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
++
++      xgbe_phy_complete_ratechange(pdata);
++
++      netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
++}
++
++static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++      enum xgbe_mode mode;
++      unsigned int reg;
++
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
++      reg &= MDIO_PCS_CTRL2_TYPE;
++
++      if (reg == MDIO_PCS_CTRL2_10GBR) {
++              mode = XGBE_MODE_KR;
++      } else {
++              if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
++                      mode = XGBE_MODE_KX_2500;
++              else
++                      mode = XGBE_MODE_KX_1000;
++      }
++
++      return mode;
++}
++
++static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++      enum xgbe_mode mode;
++
++      /* If we are in KR switch to KX, and vice-versa */
++      if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
++              if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
++                      mode = XGBE_MODE_KX_2500;
++              else
++                      mode = XGBE_MODE_KX_1000;
++      } else {
++              mode = XGBE_MODE_KR;
++      }
++
++      return mode;
++}
++
++static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
++                                      int speed)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++
++      switch (speed) {
++      case SPEED_1000:
++              return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
++                      ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;
++      case SPEED_2500:
++              return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
++                      ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;
++      case SPEED_10000:
++              return XGBE_MODE_KR;
++      default:
++              return XGBE_MODE_UNKNOWN;
++      }
++}
++
++static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
++{
++      switch (mode) {
++      case XGBE_MODE_KX_1000:
++              xgbe_phy_kx_1000_mode(pdata);
++              break;
++      case XGBE_MODE_KX_2500:
++              xgbe_phy_kx_2500_mode(pdata);
++              break;
++      case XGBE_MODE_KR:
++              xgbe_phy_kr_mode(pdata);
++              break;
++      default:
++              break;
++      }
++}
++
++static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
++                              enum xgbe_mode mode, u32 advert)
++{
++      if (pdata->phy.autoneg == AUTONEG_ENABLE) {
++              if (pdata->phy.advertising & advert)
++                      return true;
++      } else {
++              enum xgbe_mode cur_mode;
++
++              cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
++              if (cur_mode == mode)
++                      return true;
++      }
++
++      return false;
++}
++
++static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
++{
++      switch (mode) {
++      case XGBE_MODE_KX_1000:
++              return xgbe_phy_check_mode(pdata, mode,
++                                         ADVERTISED_1000baseKX_Full);
++      case XGBE_MODE_KX_2500:
++              return xgbe_phy_check_mode(pdata, mode,
++                                         ADVERTISED_2500baseX_Full);
++      case XGBE_MODE_KR:
++              return xgbe_phy_check_mode(pdata, mode,
++                                         ADVERTISED_10000baseKR_Full);
++      default:
++              return false;
++      }
++}
++
++static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
++{
++      struct xgbe_phy_data *phy_data = pdata->phy_data;
++
++      switch (speed) {
++      case SPEED_1000:
++              if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
++                      return false;
++              return true;
++      case SPEED_2500:
++              if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
++                      return false;
++              return true;
++      case SPEED_10000:
++              return true;
++      default:
++              return false;
++      }
++}
++
++static int xgbe_phy_link_status(struct xgbe_prv_data *pdata)
++{
++      unsigned int reg;
++
++      /* Link status is latched low, so read once to clear
++       * and then read again to get current state
++       */
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
++
++      return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
++}
++
++static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
++{
++      /* Nothing uniquely required for stop */
++}
++
++static int xgbe_phy_start(struct xgbe_prv_data *pdata)
++{
++      /* Nothing uniquely required for start */
++      return 0;
++}
++
++static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
++{
++      unsigned int reg, count;
++
++      /* Perform a software reset of the PCS */
++      reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
++      reg |= MDIO_CTRL1_RESET;
++      XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
++
++      count = 50;
++      do {
++              msleep(20);
++              reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
++      } while ((reg & MDIO_CTRL1_RESET) && --count);
++
++      if (reg & MDIO_CTRL1_RESET)
++              return -ETIMEDOUT;
++
++      return 0;
++}
++
++static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
++{
++      /* Nothing uniquely required for exit */
++}
++
++static int xgbe_phy_init(struct xgbe_prv_data *pdata)
++{
++      struct xgbe_phy_data *phy_data;
++      int ret;
++
++      phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
++      if (!phy_data)
++              return -ENOMEM;
++
++      /* Retrieve the PHY speedset */
++      ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,
++                                     &phy_data->speed_set);
++      if (ret) {
++              dev_err(pdata->dev, "invalid %s property\n",
++                      XGBE_SPEEDSET_PROPERTY);
++              return ret;
++      }
++
++      switch (phy_data->speed_set) {
++      case XGBE_SPEEDSET_1000_10000:
++      case XGBE_SPEEDSET_2500_10000:
++              break;
++      default:
++              dev_err(pdata->dev, "invalid %s property\n",
++                      XGBE_SPEEDSET_PROPERTY);
++              return -EINVAL;
++      }
++
++      /* Retrieve the PHY configuration properties */
++      if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
++              ret = device_property_read_u32_array(pdata->phy_dev,
++                                                   XGBE_BLWC_PROPERTY,
++                                                   phy_data->blwc,
++                                                   XGBE_SPEEDS);
++              if (ret) {
++                      dev_err(pdata->dev, "invalid %s property\n",
++                              XGBE_BLWC_PROPERTY);
++                      return ret;
++              }
++      } else {
++              memcpy(phy_data->blwc, xgbe_phy_blwc,
++                     sizeof(phy_data->blwc));
++      }
++
++      if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {
++              ret = device_property_read_u32_array(pdata->phy_dev,
++                                                   XGBE_CDR_RATE_PROPERTY,
++                                                   phy_data->cdr_rate,
++                                                   XGBE_SPEEDS);
++              if (ret) {
++                      dev_err(pdata->dev, "invalid %s property\n",
++                              XGBE_CDR_RATE_PROPERTY);
++                      return ret;
++              }
++      } else {
++              memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,
++                     sizeof(phy_data->cdr_rate));
++      }
++
++      if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
++              ret = device_property_read_u32_array(pdata->phy_dev,
++                                                   XGBE_PQ_SKEW_PROPERTY,
++                                                   phy_data->pq_skew,
++                                                   XGBE_SPEEDS);
++              if (ret) {
++                      dev_err(pdata->dev, "invalid %s property\n",
++                              XGBE_PQ_SKEW_PROPERTY);
++                      return ret;
++              }
++      } else {
++              memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,
++                     sizeof(phy_data->pq_skew));
++      }
++
++      if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {
++              ret = device_property_read_u32_array(pdata->phy_dev,
++                                                   XGBE_TX_AMP_PROPERTY,
++                                                   phy_data->tx_amp,
++                                                   XGBE_SPEEDS);
++              if (ret) {
++                      dev_err(pdata->dev, "invalid %s property\n",
++                              XGBE_TX_AMP_PROPERTY);
++                      return ret;
++              }
++      } else {
++              memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,
++                     sizeof(phy_data->tx_amp));
++      }
++
++      if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {
++              ret = device_property_read_u32_array(pdata->phy_dev,
++                                                   XGBE_DFE_CFG_PROPERTY,
++                                                   phy_data->dfe_tap_cfg,
++                                                   XGBE_SPEEDS);
++              if (ret) {
++                      dev_err(pdata->dev, "invalid %s property\n",
++                              XGBE_DFE_CFG_PROPERTY);
++                      return ret;
++              }
++      } else {
++              memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,
++                     sizeof(phy_data->dfe_tap_cfg));
++      }
++
++      if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {
++              ret = device_property_read_u32_array(pdata->phy_dev,
++                                                   XGBE_DFE_ENA_PROPERTY,
++                                                   phy_data->dfe_tap_ena,
++                                                   XGBE_SPEEDS);
++              if (ret) {
++                      dev_err(pdata->dev, "invalid %s property\n",
++                              XGBE_DFE_ENA_PROPERTY);
++                      return ret;
++              }
++      } else {
++              memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,
++                     sizeof(phy_data->dfe_tap_ena));
++      }
++
++      /* Initialize supported features */
++      pdata->phy.supported = SUPPORTED_Autoneg;
++      pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
++      pdata->phy.supported |= SUPPORTED_Backplane;
++      pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
++      switch (phy_data->speed_set) {
++      case XGBE_SPEEDSET_1000_10000:
++              pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
++              break;
++      case XGBE_SPEEDSET_2500_10000:
++              pdata->phy.supported |= SUPPORTED_2500baseX_Full;
++              break;
++      }
++
++      if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
++              pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
++
++      pdata->phy_data = phy_data;
++
++      return 0;
++}
++
++void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
++{
++      struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
++
++      phy_impl->init                  = xgbe_phy_init;
++      phy_impl->exit                  = xgbe_phy_exit;
++
++      phy_impl->reset                 = xgbe_phy_reset;
++      phy_impl->start                 = xgbe_phy_start;
++      phy_impl->stop                  = xgbe_phy_stop;
++
++      phy_impl->link_status           = xgbe_phy_link_status;
++
++      phy_impl->valid_speed           = xgbe_phy_valid_speed;
++
++      phy_impl->use_mode              = xgbe_phy_use_mode;
++      phy_impl->set_mode              = xgbe_phy_set_mode;
++      phy_impl->get_mode              = xgbe_phy_get_mode;
++      phy_impl->switch_mode           = xgbe_phy_switch_mode;
++      phy_impl->cur_mode              = xgbe_phy_cur_mode;
++
++      phy_impl->an_outcome            = xgbe_phy_an_outcome;
++
++      phy_impl->kr_training_pre       = xgbe_phy_kr_training_pre;
++      phy_impl->kr_training_post      = xgbe_phy_kr_training_post;
++}
+--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
+@@ -129,7 +129,7 @@
+ #include <net/dcbnl.h>
+ #define XGBE_DRV_NAME         "amd-xgbe"
+-#define XGBE_DRV_VERSION      "1.0.2"
++#define XGBE_DRV_VERSION      "1.0.3"
+ #define XGBE_DRV_DESC         "AMD 10 Gigabit Ethernet Driver"
+ /* Descriptor related defines */
+@@ -183,12 +183,6 @@
+ #define XGBE_PHY_MODE_PROPERTY        "phy-mode"
+ #define XGBE_DMA_IRQS_PROPERTY        "amd,per-channel-interrupt"
+ #define XGBE_SPEEDSET_PROPERTY        "amd,speed-set"
+-#define XGBE_BLWC_PROPERTY    "amd,serdes-blwc"
+-#define XGBE_CDR_RATE_PROPERTY        "amd,serdes-cdr-rate"
+-#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew"
+-#define XGBE_TX_AMP_PROPERTY  "amd,serdes-tx-amp"
+-#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config"
+-#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable"
+ /* Device-tree clock names */
+ #define XGBE_DMA_CLOCK                "dma_clk"
+@@ -251,40 +245,6 @@
+ #define XGBE_AN_PG_RCV                        0x04
+ #define XGBE_AN_INT_MASK              0x07
+-/* Rate-change complete wait/retry count */
+-#define XGBE_RATECHANGE_COUNT         500
+-
+-/* Default SerDes settings */
+-#define XGBE_SPEED_10000_BLWC         0
+-#define XGBE_SPEED_10000_CDR          0x7
+-#define XGBE_SPEED_10000_PLL          0x1
+-#define XGBE_SPEED_10000_PQ           0x12
+-#define XGBE_SPEED_10000_RATE         0x0
+-#define XGBE_SPEED_10000_TXAMP                0xa
+-#define XGBE_SPEED_10000_WORD         0x7
+-#define XGBE_SPEED_10000_DFE_TAP_CONFIG       0x1
+-#define XGBE_SPEED_10000_DFE_TAP_ENABLE       0x7f
+-
+-#define XGBE_SPEED_2500_BLWC          1
+-#define XGBE_SPEED_2500_CDR           0x2
+-#define XGBE_SPEED_2500_PLL           0x0
+-#define XGBE_SPEED_2500_PQ            0xa
+-#define XGBE_SPEED_2500_RATE          0x1
+-#define XGBE_SPEED_2500_TXAMP         0xf
+-#define XGBE_SPEED_2500_WORD          0x1
+-#define XGBE_SPEED_2500_DFE_TAP_CONFIG        0x3
+-#define XGBE_SPEED_2500_DFE_TAP_ENABLE        0x0
+-
+-#define XGBE_SPEED_1000_BLWC          1
+-#define XGBE_SPEED_1000_CDR           0x2
+-#define XGBE_SPEED_1000_PLL           0x0
+-#define XGBE_SPEED_1000_PQ            0xa
+-#define XGBE_SPEED_1000_RATE          0x3
+-#define XGBE_SPEED_1000_TXAMP         0xf
+-#define XGBE_SPEED_1000_WORD          0x1
+-#define XGBE_SPEED_1000_DFE_TAP_CONFIG        0x3
+-#define XGBE_SPEED_1000_DFE_TAP_ENABLE        0x0
+-
+ struct xgbe_prv_data;
+ struct xgbe_packet_data {
+@@ -504,8 +464,10 @@ enum xgbe_rx {
+ };
+ enum xgbe_mode {
+-      XGBE_MODE_KR = 0,
+-      XGBE_MODE_KX,
++      XGBE_MODE_KX_1000 = 0,
++      XGBE_MODE_KX_2500,
++      XGBE_MODE_KR,
++      XGBE_MODE_UNKNOWN,
+ };
+ enum xgbe_speedset {
+@@ -601,9 +563,7 @@ struct xgbe_hw_if {
+       int (*read_mmd_regs)(struct xgbe_prv_data *, int, int);
+       void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int);
+-      int (*set_gmii_speed)(struct xgbe_prv_data *);
+-      int (*set_gmii_2500_speed)(struct xgbe_prv_data *);
+-      int (*set_xgmii_speed)(struct xgbe_prv_data *);
++      int (*set_speed)(struct xgbe_prv_data *, int);
+       void (*enable_tx)(struct xgbe_prv_data *);
+       void (*disable_tx)(struct xgbe_prv_data *);
+@@ -684,9 +644,50 @@ struct xgbe_hw_if {
+       int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *);
+ };
++/* This structure represents implementation specific routines for an
++ * implementation of a PHY. All routines are required unless noted below.
++ *   Optional routines:
++ *     kr_training_pre, kr_training_post
++ */
++struct xgbe_phy_impl_if {
++      /* Perform Setup/teardown actions */
++      int (*init)(struct xgbe_prv_data *);
++      void (*exit)(struct xgbe_prv_data *);
++
++      /* Perform start/stop specific actions */
++      int (*reset)(struct xgbe_prv_data *);
++      int (*start)(struct xgbe_prv_data *);
++      void (*stop)(struct xgbe_prv_data *);
++
++      /* Return the link status */
++      int (*link_status)(struct xgbe_prv_data *);
++
++      /* Indicate if a particular speed is valid */
++      bool (*valid_speed)(struct xgbe_prv_data *, int);
++
++      /* Check if the specified mode can/should be used */
++      bool (*use_mode)(struct xgbe_prv_data *, enum xgbe_mode);
++      /* Switch the PHY into various modes */
++      void (*set_mode)(struct xgbe_prv_data *, enum xgbe_mode);
++      /* Retrieve mode needed for a specific speed */
++      enum xgbe_mode (*get_mode)(struct xgbe_prv_data *, int);
++      /* Retrieve new/next mode when trying to auto-negotiate */
++      enum xgbe_mode (*switch_mode)(struct xgbe_prv_data *);
++      /* Retrieve current mode */
++      enum xgbe_mode (*cur_mode)(struct xgbe_prv_data *);
++
++      /* Process results of auto-negotiation */
++      enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);
++
++      /* Pre/Post KR training enablement support */
++      void (*kr_training_pre)(struct xgbe_prv_data *);
++      void (*kr_training_post)(struct xgbe_prv_data *);
++};
++
+ struct xgbe_phy_if {
+-      /* For initial PHY setup */
+-      void (*phy_init)(struct xgbe_prv_data *);
++      /* For PHY setup/teardown */
++      int (*phy_init)(struct xgbe_prv_data *);
++      void (*phy_exit)(struct xgbe_prv_data *);
+       /* For PHY support when setting device up/down */
+       int (*phy_reset)(struct xgbe_prv_data *);
+@@ -696,6 +697,12 @@ struct xgbe_phy_if {
+       /* For PHY support while device is up */
+       void (*phy_status)(struct xgbe_prv_data *);
+       int (*phy_config_aneg)(struct xgbe_prv_data *);
++
++      /* For PHY settings validation */
++      bool (*phy_valid_speed)(struct xgbe_prv_data *, int);
++
++      /* PHY implementation specific services */
++      struct xgbe_phy_impl_if phy_impl;
+ };
+ struct xgbe_desc_if {
+@@ -755,11 +762,20 @@ struct xgbe_hw_features {
+       unsigned int aux_snap_num;      /* Number of Aux snapshot inputs */
+ };
++struct xgbe_version_data {
++      void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
++};
++
+ struct xgbe_prv_data {
+       struct net_device *netdev;
+       struct platform_device *pdev;
+       struct acpi_device *adev;
+       struct device *dev;
++      struct platform_device *phy_pdev;
++      struct device *phy_dev;
++
++      /* Version related data */
++      struct xgbe_version_data *vdata;
+       /* ACPI or DT flag */
+       unsigned int use_acpi;
+@@ -901,6 +917,8 @@ struct xgbe_prv_data {
+       int phy_speed;
+       /* MDIO/PHY related settings */
++      unsigned int phy_started;
++      void *phy_data;
+       struct xgbe_phy phy;
+       int mdio_mmd;
+       unsigned long link_check;
+@@ -911,21 +929,6 @@ struct xgbe_prv_data {
+       int an_irq;
+       struct work_struct an_irq_work;
+-      unsigned int speed_set;
+-
+-      /* SerDes UEFI configurable settings.
+-       *   Switching between modes/speeds requires new values for some
+-       *   SerDes settings.  The values can be supplied as device
+-       *   properties in array format.  The first array entry is for
+-       *   1GbE, second for 2.5GbE and third for 10GbE
+-       */
+-      u32 serdes_blwc[XGBE_SPEEDS];
+-      u32 serdes_cdr_rate[XGBE_SPEEDS];
+-      u32 serdes_pq_skew[XGBE_SPEEDS];
+-      u32 serdes_tx_amp[XGBE_SPEEDS];
+-      u32 serdes_dfe_tap_cfg[XGBE_SPEEDS];
+-      u32 serdes_dfe_tap_ena[XGBE_SPEEDS];
+-
+       /* Auto-negotiation state machine support */
+       unsigned int an_int;
+       struct mutex an_mutex;
+@@ -955,6 +958,7 @@ struct xgbe_prv_data {
+ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *);
+ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *);
++void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *);
+ void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
+ const struct net_device_ops *xgbe_get_netdev_ops(void);
+ const struct ethtool_ops *xgbe_get_ethtool_ops(void);
diff --git a/queue-4.9/arm-davinci-add-skeleton-for-pdata-quirks.patch b/queue-4.9/arm-davinci-add-skeleton-for-pdata-quirks.patch
new file mode 100644 (file)
index 0000000..697196c
--- /dev/null
@@ -0,0 +1,102 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:24 +0000
+Subject: ARM: davinci: add skeleton for pdata-quirks
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-59-alexander.levin@verizon.com>
+
+From: Kevin Hilman <khilman@baylibre.com>
+
+[ Upstream commit 9c9b1bc25291e275b04f758f2549c81e092954f5 ]
+
+Add skeleton pdata-quirks for davinci.
+
+Signed-off-by: Kevin Hilman <khilman@baylibre.com>
+[nsekhar@ti.com: move changes to build pdata-quirks.c and call
+                to pdata_quirks_init() to this patch]
+Signed-off-by: Sekhar Nori <nsekhar@ti.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/mach-davinci/Makefile              |    2 -
+ arch/arm/mach-davinci/da8xx-dt.c            |    1 
+ arch/arm/mach-davinci/include/mach/common.h |    2 +
+ arch/arm/mach-davinci/pdata-quirks.c        |   39 ++++++++++++++++++++++++++++
+ 4 files changed, 43 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/mach-davinci/pdata-quirks.c
+
+--- a/arch/arm/mach-davinci/Makefile
++++ b/arch/arm/mach-davinci/Makefile
+@@ -21,7 +21,7 @@ obj-$(CONFIG_AINTC)                  += irq.o
+ obj-$(CONFIG_CP_INTC)                 += cp_intc.o
+ # Board specific
+-obj-$(CONFIG_MACH_DA8XX_DT)           += da8xx-dt.o
++obj-$(CONFIG_MACH_DA8XX_DT)           += da8xx-dt.o pdata-quirks.o
+ obj-$(CONFIG_MACH_DAVINCI_EVM)        += board-dm644x-evm.o
+ obj-$(CONFIG_MACH_SFFSDR)             += board-sffsdr.o
+ obj-$(CONFIG_MACH_NEUROS_OSD2)                += board-neuros-osd2.o
+--- a/arch/arm/mach-davinci/da8xx-dt.c
++++ b/arch/arm/mach-davinci/da8xx-dt.c
+@@ -47,6 +47,7 @@ static void __init da850_init_machine(vo
+ {
+       of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
+       davinci_pm_init();
++      pdata_quirks_init();
+ }
+ static const char *const da850_boards_compat[] __initconst = {
+--- a/arch/arm/mach-davinci/include/mach/common.h
++++ b/arch/arm/mach-davinci/include/mach/common.h
+@@ -102,6 +102,8 @@ int davinci_pm_init(void);
+ static inline int davinci_pm_init(void) { return 0; }
+ #endif
++void __init pdata_quirks_init(void);
++
+ #define SRAM_SIZE     SZ_128K
+ #endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */
+--- /dev/null
++++ b/arch/arm/mach-davinci/pdata-quirks.c
+@@ -0,0 +1,39 @@
++/*
++ * Legacy platform_data quirks
++ *
++ * Copyright (C) 2016 BayLibre, Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/of_platform.h>
++
++#include <mach/common.h>
++
++struct pdata_init {
++      const char *compatible;
++      void (*fn)(void);
++};
++
++static void pdata_quirks_check(struct pdata_init *quirks)
++{
++      while (quirks->compatible) {
++              if (of_machine_is_compatible(quirks->compatible)) {
++                      if (quirks->fn)
++                              quirks->fn();
++                      break;
++              }
++              quirks++;
++      }
++}
++
++static struct pdata_init pdata_quirks[] __initdata = {
++      { /* sentinel */ },
++};
++
++void __init pdata_quirks_init(void)
++{
++      pdata_quirks_check(pdata_quirks);
++}
diff --git a/queue-4.9/arm-davinci-pm-support-da8xx-dt-platforms.patch b/queue-4.9/arm-davinci-pm-support-da8xx-dt-platforms.patch
new file mode 100644 (file)
index 0000000..101a6da
--- /dev/null
@@ -0,0 +1,32 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:23 +0000
+Subject: ARM: davinci: PM: support da8xx DT platforms
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-58-alexander.levin@verizon.com>
+
+From: Kevin Hilman <khilman@baylibre.com>
+
+[ Upstream commit 7e431af8fa0b9ed9d74378c99514856211cb9db8 ]
+
+Add PM support for DA850 device-tree boot.
+
+Signed-off-by: Kevin Hilman <khilman@baylibre.com>
+Signed-off-by: Sekhar Nori <nsekhar@ti.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/mach-davinci/da8xx-dt.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/mach-davinci/da8xx-dt.c
++++ b/arch/arm/mach-davinci/da8xx-dt.c
+@@ -46,6 +46,7 @@ static struct of_dev_auxdata da850_auxda
+ static void __init da850_init_machine(void)
+ {
+       of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
++      davinci_pm_init();
+ }
+ static const char *const da850_boards_compat[] __initconst = {
diff --git a/queue-4.9/arm-dts-stih407-family-set-snps-dis_u3_susphy_quirk.patch b/queue-4.9/arm-dts-stih407-family-set-snps-dis_u3_susphy_quirk.patch
new file mode 100644 (file)
index 0000000..3254577
--- /dev/null
@@ -0,0 +1,40 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:25 +0000
+Subject: ARM: dts: STiH407-family: set snps,dis_u3_susphy_quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-64-alexander.levin@verizon.com>
+
+From: Patrice Chotard <patrice.chotard@st.com>
+
+[ Upstream commit 8413299cb3933dade6186bbee8363f190032107e ]
+
+Since v4.10-rc1, the following logs appears in loop :
+[  801.953836] usb usb6-port1: Cannot enable. Maybe the USB cable is bad?
+[  801.960455] xhci-hcd xhci-hcd.0.auto: Cannot set link state.
+[  801.966611] usb usb6-port1: cannot disable (err = -32)
+[  806.083772] usb usb6-port1: Cannot enable. Maybe the USB cable is bad?
+[  806.090370] xhci-hcd xhci-hcd.0.auto: Cannot set link state.
+[  806.096494] usb usb6-port1: cannot disable (err = -32)
+
+After analysis, xhci try to set link in U3 and returns an error.
+Using snps,dis_u3_susphy_quirk fix this issue.
+
+Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/boot/dts/stih407-family.dtsi |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/stih407-family.dtsi
++++ b/arch/arm/boot/dts/stih407-family.dtsi
+@@ -680,6 +680,7 @@
+                               phy-names       = "usb2-phy", "usb3-phy";
+                               phys            = <&usb2_picophy0>,
+                                                 <&phy_port2 PHY_TYPE_USB3>;
++                              snps,dis_u3_susphy_quirk;
+                       };
+               };
diff --git a/queue-4.9/arm-kernel-add-smc-structure-parameter.patch b/queue-4.9/arm-kernel-add-smc-structure-parameter.patch
new file mode 100644 (file)
index 0000000..33461f9
--- /dev/null
@@ -0,0 +1,195 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:31 +0000
+Subject: arm: kernel: Add SMC structure parameter
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-79-alexander.levin@verizon.com>
+
+From: Andy Gross <andy.gross@linaro.org>
+
+[ Upstream commit 680a0873e193bae666439f4b5e32c758e68f114c ]
+
+This patch adds a quirk parameter to the arm_smccc_(smc/hvc) calls.
+The quirk structure allows for specialized SMC operations due to SoC
+specific requirements.  The current arm_smccc_(smc/hvc) is renamed and
+macros are used instead to specify the standard arm_smccc_(smc/hvc) or
+the arm_smccc_(smc/hvc)_quirk function.
+
+This patch and partial implementation was suggested by Will Deacon.
+
+Signed-off-by: Andy Gross <andy.gross@linaro.org>
+Reviewed-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/kernel/armksyms.c      |    4 ++--
+ arch/arm/kernel/smccc-call.S    |   14 ++++++++------
+ arch/arm64/kernel/arm64ksyms.c  |    4 ++--
+ arch/arm64/kernel/asm-offsets.c |    7 +++++--
+ arch/arm64/kernel/smccc-call.S  |   14 ++++++++------
+ include/linux/arm-smccc.h       |   40 ++++++++++++++++++++++++++++++++--------
+ 6 files changed, 57 insertions(+), 26 deletions(-)
+
+--- a/arch/arm/kernel/armksyms.c
++++ b/arch/arm/kernel/armksyms.c
+@@ -178,6 +178,6 @@ EXPORT_SYMBOL(__pv_offset);
+ #endif
+ #ifdef CONFIG_HAVE_ARM_SMCCC
+-EXPORT_SYMBOL(arm_smccc_smc);
+-EXPORT_SYMBOL(arm_smccc_hvc);
++EXPORT_SYMBOL(__arm_smccc_smc);
++EXPORT_SYMBOL(__arm_smccc_hvc);
+ #endif
+--- a/arch/arm/kernel/smccc-call.S
++++ b/arch/arm/kernel/smccc-call.S
+@@ -46,17 +46,19 @@ UNWIND(    .fnend)
+ /*
+  * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+  *              unsigned long a3, unsigned long a4, unsigned long a5,
+- *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
++ *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
++ *              struct arm_smccc_quirk *quirk)
+  */
+-ENTRY(arm_smccc_smc)
++ENTRY(__arm_smccc_smc)
+       SMCCC SMCCC_SMC
+-ENDPROC(arm_smccc_smc)
++ENDPROC(__arm_smccc_smc)
+ /*
+  * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
+  *              unsigned long a3, unsigned long a4, unsigned long a5,
+- *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
++ *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
++ *              struct arm_smccc_quirk *quirk)
+  */
+-ENTRY(arm_smccc_hvc)
++ENTRY(__arm_smccc_hvc)
+       SMCCC SMCCC_HVC
+-ENDPROC(arm_smccc_hvc)
++ENDPROC(__arm_smccc_hvc)
+--- a/arch/arm64/kernel/arm64ksyms.c
++++ b/arch/arm64/kernel/arm64ksyms.c
+@@ -73,5 +73,5 @@ NOKPROBE_SYMBOL(_mcount);
+ #endif
+       /* arm-smccc */
+-EXPORT_SYMBOL(arm_smccc_smc);
+-EXPORT_SYMBOL(arm_smccc_hvc);
++EXPORT_SYMBOL(__arm_smccc_smc);
++EXPORT_SYMBOL(__arm_smccc_hvc);
+--- a/arch/arm64/kernel/asm-offsets.c
++++ b/arch/arm64/kernel/asm-offsets.c
+@@ -140,8 +140,11 @@ int main(void)
+   DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS,        offsetof(struct sleep_stack_data, system_regs));
+   DEFINE(SLEEP_STACK_DATA_CALLEE_REGS,        offsetof(struct sleep_stack_data, callee_saved_regs));
+ #endif
+-  DEFINE(ARM_SMCCC_RES_X0_OFFS,       offsetof(struct arm_smccc_res, a0));
+-  DEFINE(ARM_SMCCC_RES_X2_OFFS,       offsetof(struct arm_smccc_res, a2));
++  DEFINE(ARM_SMCCC_RES_X0_OFFS,               offsetof(struct arm_smccc_res, a0));
++  DEFINE(ARM_SMCCC_RES_X2_OFFS,               offsetof(struct arm_smccc_res, a2));
++  DEFINE(ARM_SMCCC_QUIRK_ID_OFFS,     offsetof(struct arm_smccc_quirk, id));
++  DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS,  offsetof(struct arm_smccc_quirk, state));
++
+   BLANK();
+   DEFINE(HIBERN_PBE_ORIG,     offsetof(struct pbe, orig_address));
+   DEFINE(HIBERN_PBE_ADDR,     offsetof(struct pbe, address));
+--- a/arch/arm64/kernel/smccc-call.S
++++ b/arch/arm64/kernel/smccc-call.S
+@@ -27,17 +27,19 @@
+ /*
+  * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+  *              unsigned long a3, unsigned long a4, unsigned long a5,
+- *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
++ *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
++ *              struct arm_smccc_quirk *quirk)
+  */
+-ENTRY(arm_smccc_smc)
++ENTRY(__arm_smccc_smc)
+       SMCCC   smc
+-ENDPROC(arm_smccc_smc)
++ENDPROC(__arm_smccc_smc)
+ /*
+  * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
+  *              unsigned long a3, unsigned long a4, unsigned long a5,
+- *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
++ *              unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
++ *              struct arm_smccc_quirk *quirk)
+  */
+-ENTRY(arm_smccc_hvc)
++ENTRY(__arm_smccc_hvc)
+       SMCCC   hvc
+-ENDPROC(arm_smccc_hvc)
++ENDPROC(__arm_smccc_hvc)
+--- a/include/linux/arm-smccc.h
++++ b/include/linux/arm-smccc.h
+@@ -72,33 +72,57 @@ struct arm_smccc_res {
+ };
+ /**
+- * arm_smccc_smc() - make SMC calls
++ * struct arm_smccc_quirk - Contains quirk information
++ * @id: quirk identification
++ * @state: quirk specific information
++ * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
++ */
++struct arm_smccc_quirk {
++      int     id;
++      union {
++              unsigned long a6;
++      } state;
++};
++
++/**
++ * __arm_smccc_smc() - make SMC calls
+  * @a0-a7: arguments passed in registers 0 to 7
+  * @res: result values from registers 0 to 3
++ * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
+  *
+  * This function is used to make SMC calls following SMC Calling Convention.
+  * The content of the supplied param are copied to registers 0 to 7 prior
+  * to the SMC instruction. The return values are updated with the content
+- * from register 0 to 3 on return from the SMC instruction.
++ * from register 0 to 3 on return from the SMC instruction.  An optional
++ * quirk structure provides vendor specific behavior.
+  */
+-asmlinkage void arm_smccc_smc(unsigned long a0, unsigned long a1,
++asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
+                       unsigned long a2, unsigned long a3, unsigned long a4,
+                       unsigned long a5, unsigned long a6, unsigned long a7,
+-                      struct arm_smccc_res *res);
++                      struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
+ /**
+- * arm_smccc_hvc() - make HVC calls
++ * __arm_smccc_hvc() - make HVC calls
+  * @a0-a7: arguments passed in registers 0 to 7
+  * @res: result values from registers 0 to 3
+  *
+  * This function is used to make HVC calls following SMC Calling
+  * Convention.  The content of the supplied param are copied to registers 0
+  * to 7 prior to the HVC instruction. The return values are updated with
+- * the content from register 0 to 3 on return from the HVC instruction.
++ * the content from register 0 to 3 on return from the HVC instruction.  An
++ * optional quirk structure provides vendor specific behavior.
+  */
+-asmlinkage void arm_smccc_hvc(unsigned long a0, unsigned long a1,
++asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
+                       unsigned long a2, unsigned long a3, unsigned long a4,
+                       unsigned long a5, unsigned long a6, unsigned long a7,
+-                      struct arm_smccc_res *res);
++                      struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
++
++#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
++
++#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
++
++#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
++
++#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
+ #endif /*__LINUX_ARM_SMCCC_H*/
diff --git a/queue-4.9/arm-omap2-fix-init-for-multiple-quirks-for-the-same-soc.patch b/queue-4.9/arm-omap2-fix-init-for-multiple-quirks-for-the-same-soc.patch
new file mode 100644 (file)
index 0000000..e682940
--- /dev/null
@@ -0,0 +1,32 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:20 +0000
+Subject: ARM: OMAP2+: Fix init for multiple quirks for the same SoC
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-51-alexander.levin@verizon.com>
+
+From: Tony Lindgren <tony@atomide.com>
+
+[ Upstream commit 6e613ebf4405fc09e2a8c16ed193b47f80a3cbed ]
+
+It's possible that there are multiple quirks that need to be initialized
+for the same SoC. Fix the issue by not returning on the first match.
+
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/mach-omap2/pdata-quirks.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/arch/arm/mach-omap2/pdata-quirks.c
++++ b/arch/arm/mach-omap2/pdata-quirks.c
+@@ -600,7 +600,6 @@ static void pdata_quirks_check(struct pd
+               if (of_machine_is_compatible(quirks->compatible)) {
+                       if (quirks->fn)
+                               quirks->fn();
+-                      break;
+               }
+               quirks++;
+       }
diff --git a/queue-4.9/arm-smccc-update-hvc-comment-to-describe-new-quirk-parameter.patch b/queue-4.9/arm-smccc-update-hvc-comment-to-describe-new-quirk-parameter.patch
new file mode 100644 (file)
index 0000000..8cdb44e
--- /dev/null
@@ -0,0 +1,34 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:32 +0000
+Subject: ARM: smccc: Update HVC comment to describe new quirk parameter
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-82-alexander.levin@verizon.com>
+
+From: Will Deacon <will.deacon@arm.com>
+
+[ Upstream commit 3046ec674d441562c6bb3e4284cd866743042ef3 ]
+
+Commit 680a0873e193 ("arm: kernel: Add SMC structure parameter") added
+a new "quirk" parameter to the SMC and HVC SMCCC backends, but only
+updated the comment for the SMC version. This patch adds the new
+paramater to the comment describing the HVC version too.
+
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/arm-smccc.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/linux/arm-smccc.h
++++ b/include/linux/arm-smccc.h
+@@ -109,6 +109,7 @@ asmlinkage void __arm_smccc_smc(unsigned
+  * __arm_smccc_hvc() - make HVC calls
+  * @a0-a7: arguments passed in registers 0 to 7
+  * @res: result values from registers 0 to 3
++ * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
+  *
+  * This function is used to make HVC calls following SMC Calling
+  * Convention.  The content of the supplied param are copied to registers 0
diff --git a/queue-4.9/arm64-dts-hisi-fix-hip06-sas-am-max-trans-quirk.patch b/queue-4.9/arm64-dts-hisi-fix-hip06-sas-am-max-trans-quirk.patch
new file mode 100644 (file)
index 0000000..840205e
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Mon Apr 10 17:43:55 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:04 +0000
+Subject: arm64: dts: hisi: fix hip06 sas am-max-trans quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-7-alexander.levin@verizon.com>
+
+From: John Garry <john.garry@huawei.com>
+
+[ Upstream commit f65e786604b34d0b599b8c01ecca28be2d746290 ]
+
+The string for the am max transmissions quirk property
+is not correct -> fix it.
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: Wei Xu <xuwei5@hisilicon.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/hisilicon/hip06.dtsi |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi
++++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
+@@ -590,7 +590,7 @@
+                       reg = <0 0xa2000000 0 0x10000>;
+                       sas-addr = [50 01 88 20 16 00 00 00];
+                       hisilicon,sas-syscon = <&pcie_subctl>;
+-                      am-max-trans;
++                      hip06-sas-v2-quirk-amt;
+                       ctrl-reset-reg = <0xa18>;
+                       ctrl-reset-sts-reg = <0x5a0c>;
+                       ctrl-clock-ena-reg = <0x318>;
diff --git a/queue-4.9/arm64-pci-add-local-struct-device-pointers.patch b/queue-4.9/arm64-pci-add-local-struct-device-pointers.patch
new file mode 100644 (file)
index 0000000..a78a5c8
--- /dev/null
@@ -0,0 +1,58 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:09 +0000
+Subject: arm64: PCI: Add local struct device pointers
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-20-alexander.levin@verizon.com>
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit dfd1972c2b464c10fb585c4c60b594e09d181a01 ]
+
+Use a local "struct device *dev" for brevity.  No functional change
+intended.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/pci.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -121,6 +121,7 @@ int pcibios_root_bridge_prepare(struct p
+ static struct pci_config_window *
+ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
+ {
++      struct device *dev = &root->device->dev;
+       struct resource *bus_res = &root->secondary;
+       u16 seg = root->segment;
+       struct pci_config_window *cfg;
+@@ -132,8 +133,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_
+               root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
+       if (!root->mcfg_addr) {
+-              dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
+-                      seg, bus_res);
++              dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res);
+               return NULL;
+       }
+@@ -141,11 +141,10 @@ pci_acpi_setup_ecam_mapping(struct acpi_
+       cfgres.start = root->mcfg_addr + bus_res->start * bsz;
+       cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
+       cfgres.flags = IORESOURCE_MEM;
+-      cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
+-                            &pci_generic_ecam_ops);
++      cfg = pci_ecam_create(dev, &cfgres, bus_res, &pci_generic_ecam_ops);
+       if (IS_ERR(cfg)) {
+-              dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
+-                      seg, bus_res, PTR_ERR(cfg));
++              dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
++                      PTR_ERR(cfg));
+               return NULL;
+       }
diff --git a/queue-4.9/arm64-pci-manage-controller-specific-data-on-per-controller-basis.patch b/queue-4.9/arm64-pci-manage-controller-specific-data-on-per-controller-basis.patch
new file mode 100644 (file)
index 0000000..90b56f1
--- /dev/null
@@ -0,0 +1,83 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:08 +0000
+Subject: arm64: PCI: Manage controller-specific data on per-controller basis
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-19-alexander.levin@verizon.com>
+
+From: Tomasz Nowicki <tn@semihalf.com>
+
+[ Upstream commit 093d24a204425f71f4f106b7e62c8df4b456e1cc ]
+
+Currently we use one shared global acpi_pci_root_ops structure to keep
+controller-specific ops. We pass its pointer to acpi_pci_root_create() and
+associate it with a host bridge instance for good.  Such a design implies
+serious drawback. Any potential manipulation on the single system-wide
+acpi_pci_root_ops leads to kernel crash. The structure content is not
+really changing even across multiple host bridges creation; thus it was not
+an issue so far.
+
+In preparation for adding ECAM quirks mechanism (where controller-specific
+PCI ops may be different for each host bridge) allocate new
+acpi_pci_root_ops and fill in with data for each bridge. Now it is safe to
+have different controller-specific info. As a consequence free
+acpi_pci_root_ops when host bridge is released.
+
+No functional changes in this patch.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/pci.c |   17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -159,33 +159,36 @@ static void pci_acpi_generic_release_inf
+       ri = container_of(ci, struct acpi_pci_generic_root_info, common);
+       pci_ecam_free(ri->cfg);
++      kfree(ci->ops);
+       kfree(ri);
+ }
+-static struct acpi_pci_root_ops acpi_pci_root_ops = {
+-      .release_info = pci_acpi_generic_release_info,
+-};
+-
+ /* Interface called from ACPI code to setup PCI host controller */
+ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+ {
+       int node = acpi_get_node(root->device->handle);
+       struct acpi_pci_generic_root_info *ri;
+       struct pci_bus *bus, *child;
++      struct acpi_pci_root_ops *root_ops;
+       ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
+       if (!ri)
+               return NULL;
++      root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node);
++      if (!root_ops)
++              return NULL;
++
+       ri->cfg = pci_acpi_setup_ecam_mapping(root);
+       if (!ri->cfg) {
+               kfree(ri);
++              kfree(root_ops);
+               return NULL;
+       }
+-      acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
+-      bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
+-                                 ri->cfg);
++      root_ops->release_info = pci_acpi_generic_release_info;
++      root_ops->pci_ops = &ri->cfg->ops->pci_ops;
++      bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg);
+       if (!bus)
+               return NULL;
diff --git a/queue-4.9/arm64-pci-search-acpi-namespace-to-ensure-ecam-space-is-reserved.patch b/queue-4.9/arm64-pci-search-acpi-namespace-to-ensure-ecam-space-is-reserved.patch
new file mode 100644 (file)
index 0000000..cb35a06
--- /dev/null
@@ -0,0 +1,57 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:09 +0000
+Subject: arm64: PCI: Search ACPI namespace to ensure ECAM space is reserved
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-21-alexander.levin@verizon.com>
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit 08b1c19606b5fc7f895dae4d43d507b4da4a83bf ]
+
+The static MCFG table tells us the base of ECAM space, but it does not
+reserve the space -- the reservation should be done via a device in the
+ACPI namespace whose _CRS includes the ECAM region.
+
+Use acpi_resource_consumer() to check whether the ECAM space is reserved by
+an ACPI namespace device.  If it is, emit a message showing which device
+reserves it.  If not, emit a "[Firmware Bug]" warning.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/pci.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -124,8 +124,9 @@ pci_acpi_setup_ecam_mapping(struct acpi_
+       struct device *dev = &root->device->dev;
+       struct resource *bus_res = &root->secondary;
+       u16 seg = root->segment;
+-      struct pci_config_window *cfg;
+       struct resource cfgres;
++      struct acpi_device *adev;
++      struct pci_config_window *cfg;
+       unsigned int bsz;
+       /* Use address from _CBA if present, otherwise lookup MCFG */
+@@ -141,6 +142,15 @@ pci_acpi_setup_ecam_mapping(struct acpi_
+       cfgres.start = root->mcfg_addr + bus_res->start * bsz;
+       cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
+       cfgres.flags = IORESOURCE_MEM;
++
++      adev = acpi_resource_consumer(&cfgres);
++      if (adev)
++              dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres,
++                       dev_name(&adev->dev));
++      else
++              dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n",
++                       &cfgres);
++
+       cfg = pci_ecam_create(dev, &cfgres, bus_res, &pci_generic_ecam_ops);
+       if (IS_ERR(cfg)) {
+               dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
diff --git a/queue-4.9/asoc-codecs-rt5670-add-quirk-for-lenovo-thinkpad-10.patch b/queue-4.9/asoc-codecs-rt5670-add-quirk-for-lenovo-thinkpad-10.patch
new file mode 100644 (file)
index 0000000..221709c
--- /dev/null
@@ -0,0 +1,33 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:28 +0000
+Subject: ASoC: codecs: rt5670: add quirk for Lenovo Thinkpad 10
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-71-alexander.levin@verizon.com>
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 93ffeaa8ee3f10a0628ad135b552a2497e0bef2c ]
+
+the BIOS incorrectly reports this codec as 5640 but it is
+really a rt5670
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/rt5670.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/soc/codecs/rt5670.c
++++ b/sound/soc/codecs/rt5670.c
+@@ -2814,6 +2814,7 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id);
+ static const struct acpi_device_id rt5670_acpi_match[] = {
+       { "10EC5670", 0},
+       { "10EC5672", 0},
++      { "10EC5640", 0}, /* quirk */
+       { },
+ };
+ MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
diff --git a/queue-4.9/asoc-intel-baytrail-add-quirk-for-lenovo-thinkpad-10.patch b/queue-4.9/asoc-intel-baytrail-add-quirk-for-lenovo-thinkpad-10.patch
new file mode 100644 (file)
index 0000000..9e12cdd
--- /dev/null
@@ -0,0 +1,91 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:28 +0000
+Subject: ASoC: Intel: Baytrail: add quirk for Lenovo Thinkpad 10
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-72-alexander.levin@verizon.com>
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit fd0138dc5d17c636477b371d99265c406437c583 ]
+
+the BIOS reports this codec as RT5640 but it's a rt5670. Use the
+quirk mechanism to use the cht_bsw_rt5672 machine driver
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/intel/atom/sst/sst_acpi.c |   37 +++++++++++++++++++++++++++++++++++-
+ 1 file changed, 36 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/intel/atom/sst/sst_acpi.c
++++ b/sound/soc/intel/atom/sst/sst_acpi.c
+@@ -400,6 +400,7 @@ static int sst_acpi_remove(struct platfo
+ static unsigned long cht_machine_id;
+ #define CHT_SURFACE_MACH 1
++#define BYT_THINKPAD_10  2
+ static int cht_surface_quirk_cb(const struct dmi_system_id *id)
+ {
+@@ -407,6 +408,23 @@ static int cht_surface_quirk_cb(const st
+       return 1;
+ }
++static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id)
++{
++      cht_machine_id = BYT_THINKPAD_10;
++      return 1;
++}
++
++
++static const struct dmi_system_id byt_table[] = {
++      {
++              .callback = byt_thinkpad10_quirk_cb,
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "20C3001VHH"),
++              },
++      },
++      { }
++};
+ static const struct dmi_system_id cht_table[] = {
+       {
+@@ -424,6 +442,10 @@ static struct sst_acpi_mach cht_surface_
+       "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
+                                                               &chv_platform_data };
++static struct sst_acpi_mach byt_thinkpad_10 = {
++      "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
++                                                              &byt_rvp_platform_data };
++
+ static struct sst_acpi_mach *cht_quirk(void *arg)
+ {
+       struct sst_acpi_mach *mach = arg;
+@@ -436,8 +458,21 @@ static struct sst_acpi_mach *cht_quirk(v
+               return mach;
+ }
++static struct sst_acpi_mach *byt_quirk(void *arg)
++{
++      struct sst_acpi_mach *mach = arg;
++
++      dmi_check_system(byt_table);
++
++      if (cht_machine_id == BYT_THINKPAD_10)
++              return &byt_thinkpad_10;
++      else
++              return mach;
++}
++
++
+ static struct sst_acpi_mach sst_acpi_bytcr[] = {
+-      {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
++      {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk,
+                                               &byt_rvp_platform_data },
+       {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
+                                               &byt_rvp_platform_data },
diff --git a/queue-4.9/asoc-intel-bytcr_rt5640-quirks-for-insyde-devices.patch b/queue-4.9/asoc-intel-bytcr_rt5640-quirks-for-insyde-devices.patch
new file mode 100644 (file)
index 0000000..831758d
--- /dev/null
@@ -0,0 +1,45 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:19 +0000
+Subject: ASoC: Intel: bytcr_rt5640: quirks for Insyde devices
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-48-alexander.levin@verizon.com>
+
+From: youling257 <youling257@gmail.com>
+
+[ Upstream commit 571800487837263e914ef68681e4ad6a57d49c7f ]
+
+There are literally dozens of Insyde devices with a different
+name but with the same audio routing. Use a generic quirk to
+match on vendor name only to avoid recurring edits of the
+same thing.
+
+Signed-off-by: youling257 <youling257@gmail.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/intel/boards/bytcr_rt5640.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/sound/soc/intel/boards/bytcr_rt5640.c
++++ b/sound/soc/intel/boards/bytcr_rt5640.c
+@@ -387,6 +387,16 @@ static const struct dmi_system_id byt_rt
+                                                BYT_RT5640_SSP0_AIF1),
+       },
++      {
++              .callback = byt_rt5640_quirk_cb,
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
++              },
++              .driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP |
++                                               BYT_RT5640_MCLK_EN |
++                                               BYT_RT5640_SSP0_AIF1),
++
++      },
+       {}
+ };
diff --git a/queue-4.9/asoc-intel-bytct_rt5640-change-default-capture-settings.patch b/queue-4.9/asoc-intel-bytct_rt5640-change-default-capture-settings.patch
new file mode 100644 (file)
index 0000000..69808d2
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Mon Apr 10 17:43:55 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:04 +0000
+Subject: ASoC: Intel: bytct_rt5640: change default capture settings
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-6-alexander.levin@verizon.com>
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit bf46241bee7bc3ec28703796f4fbd56085055fca ]
+
+Most Baytrail-CR devices use analog differential microphones,
+modify capture default to avoid DMI quirks. Keep digital mics
+for all other configurations.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/intel/boards/bytcr_rt5640.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/sound/soc/intel/boards/bytcr_rt5640.c
++++ b/sound/soc/intel/boards/bytcr_rt5640.c
+@@ -57,9 +57,7 @@ struct byt_rt5640_private {
+       struct clk *mclk;
+ };
+-static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
+-                                      BYT_RT5640_DMIC_EN |
+-                                      BYT_RT5640_MCLK_EN;
++static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
+ static void log_quirks(struct device *dev)
+ {
+@@ -738,6 +736,13 @@ static int snd_byt_rt5640_mc_probe(struc
+               if (res_info->acpi_ipc_irq_index == 0) {
+                       byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
+               }
++
++              /* change defaults for Baytrail-CR capture */
++              byt_rt5640_quirk |= BYT_RT5640_IN1_MAP;
++              byt_rt5640_quirk |= BYT_RT5640_DIFF_MIC;
++      } else {
++              byt_rt5640_quirk |= (BYT_RT5640_DMIC1_MAP |
++                              BYT_RT5640_DMIC_EN);
+       }
+       /* check quirks before creating card */
diff --git a/queue-4.9/asoc-intel-cht_bsw_rt5645-add-baytrail-mclk-support.patch b/queue-4.9/asoc-intel-cht_bsw_rt5645-add-baytrail-mclk-support.patch
new file mode 100644 (file)
index 0000000..9ace1e1
--- /dev/null
@@ -0,0 +1,173 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:29 +0000
+Subject: ASoC: Intel: cht_bsw_rt5645: add Baytrail MCLK support
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-74-alexander.levin@verizon.com>
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit a50477e55fff69e1028f25624ee9fc9182d59b1f ]
+
+The existing code assumes a 19.2 MHz MCLK as the default
+hardware configuration. This is valid for CherryTrail but
+not for Baytrail.
+
+Add explicit MCLK configuration to set the 19.2 clock on/off
+depending on DAPM events.
+
+This is a prerequisite step to enable devices with Baytrail
+and RT5645 such as Asus X205TA
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/intel/boards/cht_bsw_rt5645.c |   84 +++++++++++++++++++++++++++-----
+ 1 file changed, 71 insertions(+), 13 deletions(-)
+
+--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
++++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
+@@ -24,6 +24,9 @@
+ #include <linux/acpi.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
++#include <asm/cpu_device_id.h>
++#include <asm/platform_sst_audio.h>
++#include <linux/clk.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc.h>
+@@ -45,6 +48,7 @@ struct cht_mc_private {
+       struct snd_soc_jack jack;
+       struct cht_acpi_card *acpi_card;
+       char codec_name[16];
++      struct clk *mclk;
+ };
+ static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
+@@ -65,6 +69,7 @@ static int platform_clock_control(struct
+       struct snd_soc_dapm_context *dapm = w->dapm;
+       struct snd_soc_card *card = dapm->card;
+       struct snd_soc_dai *codec_dai;
++      struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
+       int ret;
+       codec_dai = cht_get_codec_dai(card);
+@@ -73,19 +78,30 @@ static int platform_clock_control(struct
+               return -EIO;
+       }
+-      if (!SND_SOC_DAPM_EVENT_OFF(event))
+-              return 0;
++      if (SND_SOC_DAPM_EVENT_ON(event)) {
++              if (ctx->mclk) {
++                      ret = clk_prepare_enable(ctx->mclk);
++                      if (ret < 0) {
++                              dev_err(card->dev,
++                                      "could not configure MCLK state");
++                              return ret;
++                      }
++              }
++      } else {
++              /* Set codec sysclk source to its internal clock because codec PLL will
++               * be off when idle and MCLK will also be off when codec is
++               * runtime suspended. Codec needs clock for jack detection and button
++               * press. MCLK is turned off with clock framework or ACPI.
++               */
++              ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
++                                      48000 * 512, SND_SOC_CLOCK_IN);
++              if (ret < 0) {
++                      dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
++                      return ret;
++              }
+-      /* Set codec sysclk source to its internal clock because codec PLL will
+-       * be off when idle and MCLK will also be off by ACPI when codec is
+-       * runtime suspended. Codec needs clock for jack detection and button
+-       * press.
+-       */
+-      ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
+-                      0, SND_SOC_CLOCK_IN);
+-      if (ret < 0) {
+-              dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
+-              return ret;
++              if (ctx->mclk)
++                      clk_disable_unprepare(ctx->mclk);
+       }
+       return 0;
+@@ -97,7 +113,7 @@ static const struct snd_soc_dapm_widget
+       SND_SOC_DAPM_MIC("Int Mic", NULL),
+       SND_SOC_DAPM_SPK("Ext Spk", NULL),
+       SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+-                      platform_clock_control, SND_SOC_DAPM_POST_PMD),
++                      platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ };
+ static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = {
+@@ -225,6 +241,26 @@ static int cht_codec_init(struct snd_soc
+       rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack);
++      if (ctx->mclk) {
++              /*
++               * The firmware might enable the clock at
++               * boot (this information may or may not
++               * be reflected in the enable clock register).
++               * To change the rate we must disable the clock
++               * first to cover these cases. Due to common
++               * clock framework restrictions that do not allow
++               * to disable a clock that has not been enabled,
++               * we need to enable the clock first.
++               */
++              ret = clk_prepare_enable(ctx->mclk);
++              if (!ret)
++                      clk_disable_unprepare(ctx->mclk);
++
++              ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
++
++              if (ret)
++                      dev_err(runtime->dev, "unable to set MCLK rate\n");
++      }
+       return ret;
+ }
+@@ -349,6 +385,18 @@ static struct cht_acpi_card snd_soc_card
+ static char cht_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
++static bool is_valleyview(void)
++{
++      static const struct x86_cpu_id cpu_ids[] = {
++              { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
++              {}
++      };
++
++      if (!x86_match_cpu(cpu_ids))
++              return false;
++      return true;
++}
++
+ static int snd_cht_mc_probe(struct platform_device *pdev)
+ {
+       int ret_val = 0;
+@@ -401,6 +449,16 @@ static int snd_cht_mc_probe(struct platf
+               cht_dailink[dai_index].codec_name = cht_rt5640_codec_name;
+       }
++      if (is_valleyview()) {
++              drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
++              if (IS_ERR(drv->mclk)) {
++                      dev_err(&pdev->dev,
++                              "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
++                              PTR_ERR(drv->mclk));
++                      return PTR_ERR(drv->mclk);
++              }
++      }
++
+       snd_soc_card_set_drvdata(card, drv);
+       ret_val = devm_snd_soc_register_card(&pdev->dev, card);
+       if (ret_val) {
diff --git a/queue-4.9/asoc-intel-cht_bsw_rt5645-harden-acpi-device-detection.patch b/queue-4.9/asoc-intel-cht_bsw_rt5645-harden-acpi-device-detection.patch
new file mode 100644 (file)
index 0000000..71c87ca
--- /dev/null
@@ -0,0 +1,62 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:29 +0000
+Subject: ASoC: Intel: cht_bsw_rt5645: harden ACPI device detection
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-73-alexander.levin@verizon.com>
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 42648c2270ca0c96935dfc5d0f5c4f8d2406cf75 ]
+
+Fix classic issue of having multiple codecs listed in DSDT
+but a single one actually enabled. The previous code did
+not handle such errors and could also lead to uninitalized
+configurations
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/intel/boards/cht_bsw_rt5645.c |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
++++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
+@@ -358,22 +358,32 @@ static int snd_cht_mc_probe(struct platf
+       struct sst_acpi_mach *mach;
+       const char *i2c_name = NULL;
+       int dai_index = 0;
++      bool found = false;
+       drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
+       if (!drv)
+               return -ENOMEM;
++      mach = (&pdev->dev)->platform_data;
++
+       for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
+-              if (acpi_dev_found(snd_soc_cards[i].codec_id)) {
++              if (acpi_dev_found(snd_soc_cards[i].codec_id) &&
++                      (!strncmp(snd_soc_cards[i].codec_id, mach->id, 8))) {
+                       dev_dbg(&pdev->dev,
+                               "found codec %s\n", snd_soc_cards[i].codec_id);
+                       card = snd_soc_cards[i].soc_card;
+                       drv->acpi_card = &snd_soc_cards[i];
++                      found = true;
+                       break;
+               }
+       }
++
++      if (!found) {
++              dev_err(&pdev->dev, "No matching HID found in supported list\n");
++              return -ENODEV;
++      }
++
+       card->dev = &pdev->dev;
+-      mach = card->dev->platform_data;
+       sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
+       /* set correct codec name */
diff --git a/queue-4.9/asoc-rt5670-add-missing-10ec5072-acpi-id.patch b/queue-4.9/asoc-rt5670-add-missing-10ec5072-acpi-id.patch
new file mode 100644 (file)
index 0000000..ab23037
--- /dev/null
@@ -0,0 +1,33 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:28 +0000
+Subject: ASoC: rt5670: Add missing 10EC5072 ACPI ID
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-70-alexander.levin@verizon.com>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit d25280060835e1b2b84c242905da8334ab15c5b4 ]
+
+rt5670 driver supports also RT5672 codec, but its ACPI ID is missing.
+This was found on Dell Wyse 3040 box.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/rt5670.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/soc/codecs/rt5670.c
++++ b/sound/soc/codecs/rt5670.c
+@@ -2813,6 +2813,7 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id);
+ #ifdef CONFIG_ACPI
+ static const struct acpi_device_id rt5670_acpi_match[] = {
+       { "10EC5670", 0},
++      { "10EC5672", 0},
+       { },
+ };
+ MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
diff --git a/queue-4.9/asoc-sun4i-i2s-add-quirks-to-handle-a31-compatible.patch b/queue-4.9/asoc-sun4i-i2s-add-quirks-to-handle-a31-compatible.patch
new file mode 100644 (file)
index 0000000..d84c6d1
--- /dev/null
@@ -0,0 +1,151 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:30 +0000
+Subject: ASoC: sun4i-i2s: Add quirks to handle a31 compatible
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-77-alexander.levin@verizon.com>
+
+From: Mylène Josserand <mylene.josserand@free-electrons.com>
+
+[ Upstream commit 2ad6f30de7087515a0bc2a718fca6681a57739a0 ]
+
+Some SoCs have a reset line that must be asserted/deasserted.
+This patch adds a quirk to handle the new compatible
+"allwinner,sun6i-a31-i2s" which will deassert the reset
+line on probe function and assert it on remove's one.
+
+This new compatible is useful in case of A33 codec driver, for example.
+
+Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
+Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/sunxi/sun4i-i2s.c |   57 ++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 55 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/sunxi/sun4i-i2s.c
++++ b/sound/soc/sunxi/sun4i-i2s.c
+@@ -14,9 +14,11 @@
+ #include <linux/clk.h>
+ #include <linux/dmaengine.h>
+ #include <linux/module.h>
++#include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
++#include <linux/reset.h>
+ #include <sound/dmaengine_pcm.h>
+ #include <sound/pcm_params.h>
+@@ -92,6 +94,7 @@ struct sun4i_i2s {
+       struct clk      *bus_clk;
+       struct clk      *mod_clk;
+       struct regmap   *regmap;
++      struct reset_control *rst;
+       struct snd_dmaengine_dai_dma_data       playback_dma_data;
+ };
+@@ -585,9 +588,22 @@ static int sun4i_i2s_runtime_suspend(str
+       return 0;
+ }
++struct sun4i_i2s_quirks {
++      bool has_reset;
++};
++
++static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
++      .has_reset      = false,
++};
++
++static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
++      .has_reset      = true,
++};
++
+ static int sun4i_i2s_probe(struct platform_device *pdev)
+ {
+       struct sun4i_i2s *i2s;
++      const struct sun4i_i2s_quirks *quirks;
+       struct resource *res;
+       void __iomem *regs;
+       int irq, ret;
+@@ -608,6 +624,12 @@ static int sun4i_i2s_probe(struct platfo
+               return irq;
+       }
++      quirks = of_device_get_match_data(&pdev->dev);
++      if (!quirks) {
++              dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
++              return -ENODEV;
++      }
++
+       i2s->bus_clk = devm_clk_get(&pdev->dev, "apb");
+       if (IS_ERR(i2s->bus_clk)) {
+               dev_err(&pdev->dev, "Can't get our bus clock\n");
+@@ -626,7 +648,24 @@ static int sun4i_i2s_probe(struct platfo
+               dev_err(&pdev->dev, "Can't get our mod clock\n");
+               return PTR_ERR(i2s->mod_clk);
+       }
+-      
++
++      if (quirks->has_reset) {
++              i2s->rst = devm_reset_control_get(&pdev->dev, NULL);
++              if (IS_ERR(i2s->rst)) {
++                      dev_err(&pdev->dev, "Failed to get reset control\n");
++                      return PTR_ERR(i2s->rst);
++              }
++      }
++
++      if (!IS_ERR(i2s->rst)) {
++              ret = reset_control_deassert(i2s->rst);
++              if (ret) {
++                      dev_err(&pdev->dev,
++                              "Failed to deassert the reset control\n");
++                      return -EINVAL;
++              }
++      }
++
+       i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
+       i2s->playback_dma_data.maxburst = 4;
+@@ -658,23 +697,37 @@ err_suspend:
+               sun4i_i2s_runtime_suspend(&pdev->dev);
+ err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
++      if (!IS_ERR(i2s->rst))
++              reset_control_assert(i2s->rst);
+       return ret;
+ }
+ static int sun4i_i2s_remove(struct platform_device *pdev)
+ {
++      struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev);
++
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               sun4i_i2s_runtime_suspend(&pdev->dev);
++      if (!IS_ERR(i2s->rst))
++              reset_control_assert(i2s->rst);
++
+       return 0;
+ }
+ static const struct of_device_id sun4i_i2s_match[] = {
+-      { .compatible = "allwinner,sun4i-a10-i2s", },
++      {
++              .compatible = "allwinner,sun4i-a10-i2s",
++              .data = &sun4i_a10_i2s_quirks,
++      },
++      {
++              .compatible = "allwinner,sun6i-a31-i2s",
++              .data = &sun6i_a31_i2s_quirks,
++      },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, sun4i_i2s_match);
diff --git a/queue-4.9/can-flexcan-add-quirk-flexcan_quirk_enable_eacen_rrs.patch b/queue-4.9/can-flexcan-add-quirk-flexcan_quirk_enable_eacen_rrs.patch
new file mode 100644 (file)
index 0000000..0b5cde6
--- /dev/null
@@ -0,0 +1,66 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:39 +0000
+Subject: can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-99-alexander.levin@verizon.com>
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 9eb7aa891101a4a09114ff3191f9877ea35eae06 ]
+
+In order to receive RTR frames in the non HW FIFO mode the RSS and EACEN bits
+of the reg_ctrl2 have to be activated. As this has no side effect in the FIFO
+mode, we do this unconditionally on cores with the reg_ctrl2.
+
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/flexcan.c |   18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/can/flexcan.c
++++ b/drivers/net/can/flexcan.c
+@@ -189,7 +189,8 @@
+  */
+ #define FLEXCAN_QUIRK_BROKEN_ERR_STATE        BIT(1) /* [TR]WRN_INT not connected */
+ #define FLEXCAN_QUIRK_DISABLE_RXFG    BIT(2) /* Disable RX FIFO Global mask */
+-#define FLEXCAN_QUIRK_DISABLE_MECR    BIT(3) /* Disble Memory error detection */
++#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS        BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
++#define FLEXCAN_QUIRK_DISABLE_MECR    BIT(4) /* Disble Memory error detection */
+ /* Structure of the message buffer */
+ struct flexcan_mb {
+@@ -268,12 +269,13 @@ static struct flexcan_devtype_data fsl_p
+ static struct flexcan_devtype_data fsl_imx28_devtype_data;
+-static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
+-      .quirks = FLEXCAN_QUIRK_DISABLE_RXFG,
++static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
++      .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS,
+ };
+-static struct flexcan_devtype_data fsl_vf610_devtype_data = {
+-      .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
++static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
++      .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
++              FLEXCAN_QUIRK_DISABLE_MECR,
+ };
+ static const struct can_bittiming_const flexcan_bittiming_const = {
+@@ -883,6 +885,12 @@ static int flexcan_chip_start(struct net
+       netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
+       flexcan_write(reg_ctrl, &regs->ctrl);
++      if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) {
++              reg_ctrl2 = flexcan_read(&regs->ctrl2);
++              reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS;
++              flexcan_write(reg_ctrl2, &regs->ctrl2);
++      }
++
+       /* clear and invalidate all mailboxes first */
+       for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) {
+               flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
diff --git a/queue-4.9/clocksource-drivers-arm_arch_timer-don-t-assume-clock-runs-in-suspend.patch b/queue-4.9/clocksource-drivers-arm_arch_timer-don-t-assume-clock-runs-in-suspend.patch
new file mode 100644 (file)
index 0000000..ac4915c
--- /dev/null
@@ -0,0 +1,83 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:05 +0000
+Subject: clocksource/drivers/arm_arch_timer: Don't assume clock runs in suspend
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-9-alexander.levin@verizon.com>
+
+From: Brian Norris <briannorris@chromium.org>
+
+[ Upstream commit d8ec7595a013237f82d965dcf981571aeb41855b ]
+
+The ARM specifies that the system counter "must be implemented in an
+always-on power domain," and so we try to use the counter as a source of
+timekeeping across suspend/resume. Unfortunately, some SoCs (e.g.,
+Rockchip's RK3399) do not keep the counter ticking properly when
+switched from their high-power clock to the lower-power clock used in
+system suspend. Support this quirk by adding a new device tree property.
+
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Acked-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/arm/arch_timer.txt |    5 +++++
+ drivers/clocksource/arm_arch_timer.c                 |    9 ++++++++-
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+
+--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
++++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
+@@ -38,6 +38,11 @@ to deliver its interrupts via SPIs.
+   architecturally-defined reset values. Only supported for 32-bit
+   systems which follow the ARMv7 architected reset values.
++- arm,no-tick-in-suspend : The main counter does not tick when the system is in
++  low-power system suspend on some SoCs. This behavior does not match the
++  Architecture Reference Manual's specification that the system counter "must
++  be implemented in an always-on power domain."
++
+ Example:
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -81,6 +81,7 @@ static struct clock_event_device __percp
+ static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
+ static bool arch_timer_c3stop;
+ static bool arch_timer_mem_use_virtual;
++static bool arch_counter_suspend_stop;
+ static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
+@@ -576,7 +577,7 @@ static struct clocksource clocksource_co
+       .rating = 400,
+       .read   = arch_counter_read,
+       .mask   = CLOCKSOURCE_MASK(56),
+-      .flags  = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
++      .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+ static struct cyclecounter cyclecounter = {
+@@ -616,6 +617,8 @@ static void __init arch_counter_register
+               arch_timer_read_counter = arch_counter_get_cntvct_mem;
+       }
++      if (!arch_counter_suspend_stop)
++              clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
+       start_count = arch_timer_read_counter();
+       clocksource_register_hz(&clocksource_counter, arch_timer_rate);
+       cyclecounter.mult = clocksource_counter.mult;
+@@ -907,6 +910,10 @@ static int __init arch_timer_of_init(str
+           of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
+               arch_timer_uses_ppi = PHYS_SECURE_PPI;
++      /* On some systems, the counter stops ticking when in suspend. */
++      arch_counter_suspend_stop = of_property_read_bool(np,
++                                                       "arm,no-tick-in-suspend");
++
+       return arch_timer_init();
+ }
+ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
diff --git a/queue-4.9/drm-edid-constify-edid-quirk-list.patch b/queue-4.9/drm-edid-constify-edid-quirk-list.patch
new file mode 100644 (file)
index 0000000..bc8bd0b
--- /dev/null
@@ -0,0 +1,52 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:18 +0000
+Subject: drm/edid: constify edid quirk list
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-44-alexander.levin@verizon.com>
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+[ Upstream commit 23c4cfbdab494568600ae6073a2bf02be4b10f4e ]
+
+No reason not to be const.
+
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/1482923186-22430-1-git-send-email-jani.nikula@intel.com
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_edid.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/drm_edid.c
++++ b/drivers/gpu/drm/drm_edid.c
+@@ -90,7 +90,7 @@ struct detailed_mode_closure {
+ #define LEVEL_GTF2    2
+ #define LEVEL_CVT     3
+-static struct edid_quirk {
++static const struct edid_quirk {
+       char vendor[4];
+       int product_id;
+       u32 quirks;
+@@ -1449,7 +1449,7 @@ EXPORT_SYMBOL(drm_edid_duplicate);
+  *
+  * Returns true if @vendor is in @edid, false otherwise
+  */
+-static bool edid_vendor(struct edid *edid, char *vendor)
++static bool edid_vendor(struct edid *edid, const char *vendor)
+ {
+       char edid_vendor[3];
+@@ -1469,7 +1469,7 @@ static bool edid_vendor(struct edid *edi
+  */
+ static u32 edid_get_quirks(struct edid *edid)
+ {
+-      struct edid_quirk *quirk;
++      const struct edid_quirk *quirk;
+       int i;
+       for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
diff --git a/queue-4.9/drm-i915-actually-drive-the-bdw-reserved-ids.patch b/queue-4.9/drm-i915-actually-drive-the-bdw-reserved-ids.patch
new file mode 100644 (file)
index 0000000..1321e9f
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:19 +0000
+Subject: drm/i915: actually drive the BDW reserved IDs
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-47-alexander.levin@verizon.com>
+
+From: Paulo Zanoni <paulo.r.zanoni@intel.com>
+
+[ Upstream commit 98b2f01c8dfc8922a2af1fe82a1c40cac4911634 ]
+
+Back in 2014, commit fb7023e0e248 ("drm/i915: BDW: Adding Reserved PCI
+IDs.") added the reserved PCI IDs in order to try to make sure we had
+working drivers in case we ever released products using these IDs
+(since we had instances of this type of problem in the past). The
+problem is that the patch only touched the macros used by
+early-quirks.c and by the user space components that rely on
+i915_pciids.h, it didn't touch the macros used by i915_pci.c. So we
+correctly handled the stolen memory for these theoretical IDs, but we
+didn't actually drive the devices from i915.ko.
+
+So this patch fixes the original commit by actually making i915.ko
+drive these IDs, which was the goal. There's no information on what
+would be the GT count on these IDs, so we just go with the safer
+intel_broadwell_info, at the risk of ignoring a possibly inexistent
+BSD2_RING.
+
+I did some checking, and it seems that these IDs are driven by
+intel-gpu-tools, xf86-video-intel and libdrm (since they contain old
+copies of i915_pciids.h), but they are not checked by mesa.
+
+The alternative to this patch would be to just assume we're actually
+never going to use these IDs, and then remove them from our ID lists
+and make sure our user space components sync the latest i915_pciids.h
+copy. I'm fine with either approaches, as long as we make sure that
+every component tries to drive the same list of PCI IDs.
+
+Fixes: fb7023e0e248 ("drm/i915: BDW: Adding Reserved PCI IDs.")
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Cc: Ben Widawsky <ben@bwidawsk.net>
+Cc: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/1483473860-17644-3-git-send-email-paulo.r.zanoni@intel.com
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_pci.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/i915/i915_pci.c
++++ b/drivers/gpu/drm/i915/i915_pci.c
+@@ -417,6 +417,7 @@ static const struct pci_device_id pciidl
+       INTEL_VLV_IDS(&intel_valleyview_info),
+       INTEL_BDW_GT12_IDS(&intel_broadwell_info),
+       INTEL_BDW_GT3_IDS(&intel_broadwell_gt3_info),
++      INTEL_BDW_RSVD_IDS(&intel_broadwell_info),
+       INTEL_CHV_IDS(&intel_cherryview_info),
+       INTEL_SKL_GT1_IDS(&intel_skylake_info),
+       INTEL_SKL_GT2_IDS(&intel_skylake_info),
diff --git a/queue-4.9/drm-i915-fix-intel_bdw_ids-definition.patch b/queue-4.9/drm-i915-fix-intel_bdw_ids-definition.patch
new file mode 100644 (file)
index 0000000..769f33d
--- /dev/null
@@ -0,0 +1,39 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:18 +0000
+Subject: drm/i915: fix INTEL_BDW_IDS definition
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-45-alexander.levin@verizon.com>
+
+From: Paulo Zanoni <paulo.r.zanoni@intel.com>
+
+[ Upstream commit 7fbd995ce4241e98d30859405504c3fb279c4ccb ]
+
+Remove duplicated IDs from the list. Currently, this definition is
+only used by early-quirks.c. From my understanding of the code, having
+duplicated IDs shouldn't be causing any bugs.
+
+Fixes: 8d9c20e1d1e3 ("drm/i915: Remove .is_mobile field from platform struct")
+Cc: Carlos Santa <carlos.santa@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/1483473860-17644-1-git-send-email-paulo.r.zanoni@intel.com
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/drm/i915_pciids.h |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/include/drm/i915_pciids.h
++++ b/include/drm/i915_pciids.h
+@@ -240,8 +240,6 @@
+       INTEL_BDW_GT12_IDS(info), \
+       INTEL_BDW_GT3_IDS(info), \
+       INTEL_BDW_RSVDM_IDS(info), \
+-      INTEL_BDW_GT12_IDS(info), \
+-      INTEL_BDW_GT3_IDS(info), \
+       INTEL_BDW_RSVDD_IDS(info)
+ #define INTEL_CHV_IDS(info) \
diff --git a/queue-4.9/drm-i915-more-.is_mobile-cleanups-for-bdw.patch b/queue-4.9/drm-i915-more-.is_mobile-cleanups-for-bdw.patch
new file mode 100644 (file)
index 0000000..bd7297f
--- /dev/null
@@ -0,0 +1,57 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:19 +0000
+Subject: drm/i915: more .is_mobile cleanups for BDW
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-46-alexander.levin@verizon.com>
+
+From: Paulo Zanoni <paulo.r.zanoni@intel.com>
+
+[ Upstream commit 0784bc624ae9be4269f8129572ee164ca680ca7c ]
+
+Commit 8d9c20e1d1e3 ("drm/i915: Remove .is_mobile field from platform
+struct") removed mobile vs desktop differences for HSW+, but forgot
+the Broadwell reserved IDs, so do it now.
+
+It's interesting to notice that these IDs are used by early-quirks.c
+but are *not* used by i915_pci.c.
+
+Cc: Carlos Santa <carlos.santa@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/1483473860-17644-2-git-send-email-paulo.r.zanoni@intel.com
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/drm/i915_pciids.h |    9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/include/drm/i915_pciids.h
++++ b/include/drm/i915_pciids.h
+@@ -226,21 +226,18 @@
+       INTEL_VGA_DEVICE(0x162A, info), /* Server */ \
+       INTEL_VGA_DEVICE(0x162D, info)  /* Workstation */
+-#define INTEL_BDW_RSVDM_IDS(info) \
++#define INTEL_BDW_RSVD_IDS(info) \
+       INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
+       INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
+       INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \
+-      INTEL_VGA_DEVICE(0x163E, info)  /* ULX */
+-
+-#define INTEL_BDW_RSVDD_IDS(info) \
++      INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \
+       INTEL_VGA_DEVICE(0x163A, info), /* Server */ \
+       INTEL_VGA_DEVICE(0x163D, info)  /* Workstation */
+ #define INTEL_BDW_IDS(info) \
+       INTEL_BDW_GT12_IDS(info), \
+       INTEL_BDW_GT3_IDS(info), \
+-      INTEL_BDW_RSVDM_IDS(info), \
+-      INTEL_BDW_RSVDD_IDS(info)
++      INTEL_BDW_RSVD_IDS(info)
+ #define INTEL_CHV_IDS(info) \
+       INTEL_VGA_DEVICE(0x22b0, info), \
diff --git a/queue-4.9/drm-mga-remove-device_is_agp-callback.patch b/queue-4.9/drm-mga-remove-device_is_agp-callback.patch
new file mode 100644 (file)
index 0000000..a381c8e
--- /dev/null
@@ -0,0 +1,118 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:25 +0000
+Subject: drm/mga: remove device_is_agp callback
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-63-alexander.levin@verizon.com>
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit 858b2c1bf820ebfba89c5e2867ab882bdb5b2f5a ]
+
+It's only for a device quirk, and we might as well do that in the load
+callback.
+
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170125062657.19270-10-daniel.vetter@ffwll.ch
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/mga/mga_dma.c |   20 +++++++++++++++++++-
+ drivers/gpu/drm/mga/mga_drv.c |   37 -------------------------------------
+ 2 files changed, 19 insertions(+), 38 deletions(-)
+
+--- a/drivers/gpu/drm/mga/mga_dma.c
++++ b/drivers/gpu/drm/mga/mga_dma.c
+@@ -392,6 +392,24 @@ int mga_driver_load(struct drm_device *d
+       drm_mga_private_t *dev_priv;
+       int ret;
++      /* There are PCI versions of the G450.  These cards have the
++       * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
++       * bridge chip.  We detect these cards, which are not currently
++       * supported by this driver, by looking at the device ID of the
++       * bus the "card" is on.  If vendor is 0x3388 (Hint Corp) and the
++       * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
++       * device.
++       */
++      if ((dev->pdev->device == 0x0525) && dev->pdev->bus->self
++          && (dev->pdev->bus->self->vendor == 0x3388)
++          && (dev->pdev->bus->self->device == 0x0021)
++          && dev->agp) {
++              /* FIXME: This should be quirked in the pci core, but oh well
++               * the hw probably stopped existing. */
++              arch_phys_wc_del(dev->agp->agp_mtrr);
++              kfree(dev->agp);
++              dev->agp = NULL;
++      }
+       dev_priv = kzalloc(sizeof(drm_mga_private_t), GFP_KERNEL);
+       if (!dev_priv)
+               return -ENOMEM;
+@@ -698,7 +716,7 @@ static int mga_do_pci_dma_bootstrap(stru
+ static int mga_do_dma_bootstrap(struct drm_device *dev,
+                               drm_mga_dma_bootstrap_t *dma_bs)
+ {
+-      const int is_agp = (dma_bs->agp_mode != 0) && drm_pci_device_is_agp(dev);
++      const int is_agp = (dma_bs->agp_mode != 0) && dev->agp;
+       int err;
+       drm_mga_private_t *const dev_priv =
+           (drm_mga_private_t *) dev->dev_private;
+--- a/drivers/gpu/drm/mga/mga_drv.c
++++ b/drivers/gpu/drm/mga/mga_drv.c
+@@ -37,8 +37,6 @@
+ #include <drm/drm_pciids.h>
+-static int mga_driver_device_is_agp(struct drm_device *dev);
+-
+ static struct pci_device_id pciidlist[] = {
+       mga_PCI_IDS
+ };
+@@ -66,7 +64,6 @@ static struct drm_driver driver = {
+       .lastclose = mga_driver_lastclose,
+       .set_busid = drm_pci_set_busid,
+       .dma_quiescent = mga_driver_dma_quiescent,
+-      .device_is_agp = mga_driver_device_is_agp,
+       .get_vblank_counter = mga_get_vblank_counter,
+       .enable_vblank = mga_enable_vblank,
+       .disable_vblank = mga_disable_vblank,
+@@ -107,37 +104,3 @@ module_exit(mga_exit);
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+-
+-/**
+- * Determine if the device really is AGP or not.
+- *
+- * In addition to the usual tests performed by \c drm_device_is_agp, this
+- * function detects PCI G450 cards that appear to the system exactly like
+- * AGP G450 cards.
+- *
+- * \param dev   The device to be tested.
+- *
+- * \returns
+- * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
+- */
+-static int mga_driver_device_is_agp(struct drm_device *dev)
+-{
+-      const struct pci_dev *const pdev = dev->pdev;
+-
+-      /* There are PCI versions of the G450.  These cards have the
+-       * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
+-       * bridge chip.  We detect these cards, which are not currently
+-       * supported by this driver, by looking at the device ID of the
+-       * bus the "card" is on.  If vendor is 0x3388 (Hint Corp) and the
+-       * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
+-       * device.
+-       */
+-
+-      if ((pdev->device == 0x0525) && pdev->bus->self
+-          && (pdev->bus->self->vendor == 0x3388)
+-          && (pdev->bus->self->device == 0x0021)) {
+-              return 0;
+-      }
+-
+-      return 2;
+-}
diff --git a/queue-4.9/drm-msm-adreno-move-function-declarations-to-header-file.patch b/queue-4.9/drm-msm-adreno-move-function-declarations-to-header-file.patch
new file mode 100644 (file)
index 0000000..4bfbec3
--- /dev/null
@@ -0,0 +1,54 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:32 +0000
+Subject: drm/msm/adreno: move function declarations to header file
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-81-alexander.levin@verizon.com>
+
+From: Baoyou Xie <baoyou.xie@linaro.org>
+
+[ Upstream commit a5725ab0497ad91a2df7c01a78bf1a0cc5be4526 ]
+
+We get 2 warnings when building kernel with W=1:
+drivers/gpu/drm/msm/adreno/a3xx_gpu.c:535:17: warning: no previous prototype for 'a3xx_gpu_init' [-Wmissing-prototypes]
+drivers/gpu/drm/msm/adreno/a4xx_gpu.c:624:17: warning: no previous prototype for 'a4xx_gpu_init' [-Wmissing-prototypes]
+
+In fact, both functions are declared in
+drivers/gpu/drm/msm/adreno/adreno_device.c, but should be declared
+in a header file. So this patch moves both function declarations to
+drivers/gpu/drm/msm/adreno/adreno_gpu.h.
+
+Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
+Reviewed-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: http://patchwork.freedesktop.org/patch/msgid/1477127865-9381-1-git-send-email-baoyou.xie@linaro.org
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/msm/adreno/adreno_device.c |    3 ---
+ drivers/gpu/drm/msm/adreno/adreno_gpu.h    |    3 +++
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
++++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
+@@ -25,9 +25,6 @@ bool hang_debug = false;
+ MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
+ module_param_named(hang_debug, hang_debug, bool, 0600);
+-struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
+-struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
+-
+ static const struct adreno_info gpulist[] = {
+       {
+               .rev   = ADRENO_REV(3, 0, 5, ANY_ID),
+--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
++++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+@@ -311,4 +311,7 @@ static inline void adreno_gpu_write(stru
+               gpu_write(&gpu->base, reg - 1, data);
+ }
++struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
++struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
++
+ #endif /* __ADRENO_GPU_H__ */
diff --git a/queue-4.9/firmware-qcom-scm-fix-interrupted-scm-calls.patch b/queue-4.9/firmware-qcom-scm-fix-interrupted-scm-calls.patch
new file mode 100644 (file)
index 0000000..a473376
--- /dev/null
@@ -0,0 +1,122 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:32 +0000
+Subject: firmware: qcom: scm: Fix interrupted SCM calls
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-80-alexander.levin@verizon.com>
+
+From: Andy Gross <andy.gross@linaro.org>
+
+[ Upstream commit 82bcd087029f6056506ea929f11af02622230901 ]
+
+This patch adds a Qualcomm specific quirk to the arm_smccc_smc call.
+
+On Qualcomm ARM64 platforms, the SMC call can return before it has
+completed.  If this occurs, the call can be restarted, but it requires
+using the returned session ID value from the interrupted SMC call.
+
+The quirk stores off the session ID from the interrupted call in the
+quirk structure so that it can be used by the caller.
+
+This patch folds in a fix given by Sricharan R:
+https://lkml.org/lkml/2016/9/28/272
+
+Signed-off-by: Andy Gross <andy.gross@linaro.org>
+Reviewed-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/smccc-call.S |    9 ++++++++-
+ drivers/firmware/qcom_scm-64.c |   13 ++++++++++---
+ include/linux/arm-smccc.h      |   11 ++++++++---
+ 3 files changed, 26 insertions(+), 7 deletions(-)
+
+--- a/arch/arm64/kernel/smccc-call.S
++++ b/arch/arm64/kernel/smccc-call.S
+@@ -12,6 +12,7 @@
+  *
+  */
+ #include <linux/linkage.h>
++#include <linux/arm-smccc.h>
+ #include <asm/asm-offsets.h>
+       .macro SMCCC instr
+@@ -20,7 +21,13 @@
+       ldr     x4, [sp]
+       stp     x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
+       stp     x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
+-      ret
++      ldr     x4, [sp, #8]
++      cbz     x4, 1f /* no quirk structure */
++      ldr     x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
++      cmp     x9, #ARM_SMCCC_QUIRK_QCOM_A6
++      b.ne    1f
++      str     x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
++1:    ret
+       .cfi_endproc
+       .endm
+--- a/drivers/firmware/qcom_scm-64.c
++++ b/drivers/firmware/qcom_scm-64.c
+@@ -91,6 +91,7 @@ static int qcom_scm_call(struct device *
+       dma_addr_t args_phys = 0;
+       void *args_virt = NULL;
+       size_t alloc_len;
++      struct arm_smccc_quirk quirk = {.id = ARM_SMCCC_QUIRK_QCOM_A6};
+       if (unlikely(arglen > N_REGISTER_ARGS)) {
+               alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
+@@ -131,10 +132,16 @@ static int qcom_scm_call(struct device *
+                                        qcom_smccc_convention,
+                                        ARM_SMCCC_OWNER_SIP, fn_id);
++              quirk.state.a6 = 0;
++
+               do {
+-                      arm_smccc_smc(cmd, desc->arginfo, desc->args[0],
+-                                    desc->args[1], desc->args[2], x5, 0, 0,
+-                                    res);
++                      arm_smccc_smc_quirk(cmd, desc->arginfo, desc->args[0],
++                                    desc->args[1], desc->args[2], x5,
++                                    quirk.state.a6, 0, res, &quirk);
++
++                      if (res->a0 == QCOM_SCM_INTERRUPTED)
++                              cmd = res->a0;
++
+               } while (res->a0 == QCOM_SCM_INTERRUPTED);
+               mutex_unlock(&qcom_scm_lock);
+--- a/include/linux/arm-smccc.h
++++ b/include/linux/arm-smccc.h
+@@ -14,9 +14,6 @@
+ #ifndef __LINUX_ARM_SMCCC_H
+ #define __LINUX_ARM_SMCCC_H
+-#include <linux/linkage.h>
+-#include <linux/types.h>
+-
+ /*
+  * This file provides common defines for ARM SMC Calling Convention as
+  * specified in
+@@ -60,6 +57,13 @@
+ #define ARM_SMCCC_OWNER_TRUSTED_OS    50
+ #define ARM_SMCCC_OWNER_TRUSTED_OS_END        63
++#define ARM_SMCCC_QUIRK_NONE          0
++#define ARM_SMCCC_QUIRK_QCOM_A6               1 /* Save/restore register a6 */
++
++#ifndef __ASSEMBLY__
++
++#include <linux/linkage.h>
++#include <linux/types.h>
+ /**
+  * struct arm_smccc_res - Result from SMC/HVC call
+  * @a0-a3 result values from registers 0 to 3
+@@ -125,4 +129,5 @@ asmlinkage void __arm_smccc_hvc(unsigned
+ #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
++#endif /*__ASSEMBLY__*/
+ #endif /*__LINUX_ARM_SMCCC_H*/
diff --git a/queue-4.9/hid-asus-add-i2c-touchpad-support.patch b/queue-4.9/hid-asus-add-i2c-touchpad-support.patch
new file mode 100644 (file)
index 0000000..2dce7c3
--- /dev/null
@@ -0,0 +1,407 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:15 +0000
+Subject: HID: asus: Add i2c touchpad support
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-36-alexander.levin@verizon.com>
+
+From: Brendan McGrath <redmcg@redmandi.dyndns.org>
+
+[ Upstream commit 9ce12d8be12c94334634dd57050444910415e45f ]
+
+Update the hid-asus module to add multitouch support for the Asus i2c touchpad.
+
+This patch aims to resolve the issue raised here:
+https://bugzilla.kernel.org/show_bug.cgi?id=120181
+
+The issue is in relation to an Asus touchpad device which currently does not
+have multitouch support.
+
+The device currently falls through to the hid-generic driver which
+treats the device as a mouse.
+
+This patch aims to add the multitouch support.
+
+[jkosina@suse.cz: move most of the 'patch comment' into actual changelog]
+[jkosina@suse.cz: drop hunk that changes ->name of the driver]
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Brendan McGrath <redmcg@redmandi.dyndns.org>
+Signed-off-by: Victor Vlasenko <victor.vlasenko@sysgears.com>
+Signed-off-by: Frederik Wenigwieser <frederik.wenigwieser@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/Kconfig    |    2 
+ drivers/hid/hid-asus.c |  299 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ drivers/hid/hid-core.c |    1 
+ drivers/hid/hid-ids.h  |    1 
+ 4 files changed, 296 insertions(+), 7 deletions(-)
+
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -138,7 +138,7 @@ config HID_ASUS
+       tristate "Asus"
+       depends on I2C_HID
+       ---help---
+-      Support for Asus notebook built-in keyboard via i2c.
++      Support for Asus notebook built-in keyboard and touchpad via i2c.
+       Supported devices:
+       - EeeBook X205TA
+--- a/drivers/hid/hid-asus.c
++++ b/drivers/hid/hid-asus.c
+@@ -11,6 +11,12 @@
+  *  This module based on hid-ortek by
+  *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
+  *  Copyright (c) 2011 Jiri Kosina
++ *
++ *  This module has been updated to add support for Asus i2c touchpad.
++ *
++ *  Copyright (c) 2016 Brendan McGrath <redmcg@redmandi.dyndns.org>
++ *  Copyright (c) 2016 Victor Vlasenko <victor.vlasenko@sysgears.com>
++ *  Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com>
+  */
+ /*
+@@ -20,16 +26,287 @@
+  * any later version.
+  */
+-#include <linux/device.h>
+ #include <linux/hid.h>
+ #include <linux/module.h>
++#include <linux/input/mt.h>
+ #include "hid-ids.h"
++MODULE_AUTHOR("Yusuke Fujimaki <usk.fujimaki@gmail.com>");
++MODULE_AUTHOR("Brendan McGrath <redmcg@redmandi.dyndns.org>");
++MODULE_AUTHOR("Victor Vlasenko <victor.vlasenko@sysgears.com>");
++MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>");
++MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
++
++#define FEATURE_REPORT_ID 0x0d
++#define INPUT_REPORT_ID 0x5d
++
++#define INPUT_REPORT_SIZE 28
++
++#define MAX_CONTACTS 5
++
++#define MAX_X 2794
++#define MAX_Y 1758
++#define MAX_TOUCH_MAJOR 8
++#define MAX_PRESSURE 128
++
++#define CONTACT_DATA_SIZE 5
++
++#define BTN_LEFT_MASK 0x01
++#define CONTACT_TOOL_TYPE_MASK 0x80
++#define CONTACT_X_MSB_MASK 0xf0
++#define CONTACT_Y_MSB_MASK 0x0f
++#define CONTACT_TOUCH_MAJOR_MASK 0x07
++#define CONTACT_PRESSURE_MASK 0x7f
++
++#define QUIRK_FIX_NOTEBOOK_REPORT     BIT(0)
++#define QUIRK_NO_INIT_REPORTS         BIT(1)
++#define QUIRK_SKIP_INPUT_MAPPING      BIT(2)
++#define QUIRK_IS_MULTITOUCH           BIT(3)
++
++#define NOTEBOOK_QUIRKS                       QUIRK_FIX_NOTEBOOK_REPORT
++#define TOUCHPAD_QUIRKS                       (QUIRK_NO_INIT_REPORTS | \
++                                               QUIRK_SKIP_INPUT_MAPPING | \
++                                               QUIRK_IS_MULTITOUCH)
++
++#define TRKID_SGN       ((TRKID_MAX + 1) >> 1)
++
++struct asus_drvdata {
++      unsigned long quirks;
++      struct input_dev *input;
++};
++
++static void asus_report_contact_down(struct input_dev *input,
++              int toolType, u8 *data)
++{
++      int touch_major, pressure;
++      int x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1];
++      int y = MAX_Y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]);
++
++      if (toolType == MT_TOOL_PALM) {
++              touch_major = MAX_TOUCH_MAJOR;
++              pressure = MAX_PRESSURE;
++      } else {
++              touch_major = (data[3] >> 4) & CONTACT_TOUCH_MAJOR_MASK;
++              pressure = data[4] & CONTACT_PRESSURE_MASK;
++      }
++
++      input_report_abs(input, ABS_MT_POSITION_X, x);
++      input_report_abs(input, ABS_MT_POSITION_Y, y);
++      input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major);
++      input_report_abs(input, ABS_MT_PRESSURE, pressure);
++}
++
++/* Required for Synaptics Palm Detection */
++static void asus_report_tool_width(struct input_dev *input)
++{
++      struct input_mt *mt = input->mt;
++      struct input_mt_slot *oldest;
++      int oldid, count, i;
++
++      oldest = NULL;
++      oldid = mt->trkid;
++      count = 0;
++
++      for (i = 0; i < mt->num_slots; ++i) {
++              struct input_mt_slot *ps = &mt->slots[i];
++              int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
++
++              if (id < 0)
++                      continue;
++              if ((id - oldid) & TRKID_SGN) {
++                      oldest = ps;
++                      oldid = id;
++              }
++              count++;
++      }
++
++      if (oldest) {
++              input_report_abs(input, ABS_TOOL_WIDTH,
++                      input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR));
++      }
++}
++
++static void asus_report_input(struct input_dev *input, u8 *data)
++{
++      int i;
++      u8 *contactData = data + 2;
++
++      for (i = 0; i < MAX_CONTACTS; i++) {
++              bool down = !!(data[1] & BIT(i+3));
++              int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ?
++                                              MT_TOOL_PALM : MT_TOOL_FINGER;
++
++              input_mt_slot(input, i);
++              input_mt_report_slot_state(input, toolType, down);
++
++              if (down) {
++                      asus_report_contact_down(input, toolType, contactData);
++                      contactData += CONTACT_DATA_SIZE;
++              }
++      }
++
++      input_report_key(input, BTN_LEFT, data[1] & BTN_LEFT_MASK);
++      asus_report_tool_width(input);
++
++      input_mt_sync_frame(input);
++      input_sync(input);
++}
++
++static int asus_raw_event(struct hid_device *hdev,
++              struct hid_report *report, u8 *data, int size)
++{
++      struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
++
++      if (drvdata->quirks & QUIRK_IS_MULTITOUCH &&
++                                       data[0] == INPUT_REPORT_ID &&
++                                              size == INPUT_REPORT_SIZE) {
++              asus_report_input(drvdata->input, data);
++              return 1;
++      }
++
++      return 0;
++}
++
++static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
++{
++      struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
++
++      if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
++              int ret;
++              struct input_dev *input = hi->input;
++
++              input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);
++              input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);
++              input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0);
++              input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
++              input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
++
++              __set_bit(BTN_LEFT, input->keybit);
++              __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
++
++              ret = input_mt_init_slots(input, MAX_CONTACTS, INPUT_MT_POINTER);
++
++              if (ret) {
++                      hid_err(hdev, "Asus input mt init slots failed: %d\n", ret);
++                      return ret;
++              }
++
++              drvdata->input = input;
++      }
++
++      return 0;
++}
++
++static int asus_input_mapping(struct hid_device *hdev,
++              struct hid_input *hi, struct hid_field *field,
++              struct hid_usage *usage, unsigned long **bit,
++              int *max)
++{
++      struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
++
++      if (drvdata->quirks & QUIRK_SKIP_INPUT_MAPPING) {
++              /* Don't map anything from the HID report.
++               * We do it all manually in asus_input_configured
++               */
++              return -1;
++      }
++
++      return 0;
++}
++
++static int asus_start_multitouch(struct hid_device *hdev)
++{
++      int ret;
++      const unsigned char buf[] = { FEATURE_REPORT_ID, 0x00, 0x03, 0x01, 0x00 };
++      unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
++
++      if (!dmabuf) {
++              ret = -ENOMEM;
++              hid_err(hdev, "Asus failed to alloc dma buf: %d\n", ret);
++              return ret;
++      }
++
++      ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
++                                      HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
++
++      kfree(dmabuf);
++
++      if (ret != sizeof(buf)) {
++              hid_err(hdev, "Asus failed to start multitouch: %d\n", ret);
++              return ret;
++      }
++
++      return 0;
++}
++
++static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
++{
++      struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
++
++      if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
++              return asus_start_multitouch(hdev);
++
++      return 0;
++}
++
++static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
++{
++      int ret;
++      struct asus_drvdata *drvdata;
++
++      drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
++      if (drvdata == NULL) {
++              hid_err(hdev, "Can't alloc Asus descriptor\n");
++              return -ENOMEM;
++      }
++
++      hid_set_drvdata(hdev, drvdata);
++
++      drvdata->quirks = id->driver_data;
++
++      if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
++              hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
++
++      ret = hid_parse(hdev);
++      if (ret) {
++              hid_err(hdev, "Asus hid parse failed: %d\n", ret);
++              return ret;
++      }
++
++      ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
++      if (ret) {
++              hid_err(hdev, "Asus hw start failed: %d\n", ret);
++              return ret;
++      }
++
++      if (!drvdata->input) {
++              hid_err(hdev, "Asus input not registered\n");
++              ret = -ENOMEM;
++              goto err_stop_hw;
++      }
++
++      drvdata->input->name = "Asus TouchPad";
++
++      if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
++              ret = asus_start_multitouch(hdev);
++              if (ret)
++                      goto err_stop_hw;
++      }
++
++      return 0;
++err_stop_hw:
++      hid_hw_stop(hdev);
++      return ret;
++}
++
+ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
+ {
+-      if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) {
++      struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
++
++      if (drvdata->quirks & QUIRK_FIX_NOTEBOOK_REPORT &&
++                      *rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) {
+               hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
+               rdesc[55] = 0xdd;
+       }
+@@ -37,15 +314,25 @@ static __u8 *asus_report_fixup(struct hi
+ }
+ static const struct hid_device_id asus_devices[] = {
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
++      { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
++               USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), NOTEBOOK_QUIRKS},
++      { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
++                       USB_DEVICE_ID_ASUSTEK_TOUCHPAD), TOUCHPAD_QUIRKS },
+       { }
+ };
+ MODULE_DEVICE_TABLE(hid, asus_devices);
+ static struct hid_driver asus_driver = {
+-      .name = "asus",
+-      .id_table = asus_devices,
+-      .report_fixup = asus_report_fixup
++      .name                   = "asus",
++      .id_table               = asus_devices,
++      .report_fixup           = asus_report_fixup,
++      .probe                  = asus_probe,
++      .input_mapping          = asus_input_mapping,
++      .input_configured       = asus_input_configured,
++#ifdef CONFIG_PM
++      .reset_resume           = asus_reset_resume,
++#endif
++      .raw_event              = asus_raw_event
+ };
+ module_hid_driver(asus_driver);
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1856,6 +1856,7 @@ static const struct hid_device_id hid_ha
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
++      { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_TOUCHPAD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -174,6 +174,7 @@
+ #define USB_DEVICE_ID_ASUSTEK_LCM     0x1726
+ #define USB_DEVICE_ID_ASUSTEK_LCM2    0x175b
+ #define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD       0x8585
++#define USB_DEVICE_ID_ASUSTEK_TOUCHPAD        0x0101
+ #define USB_VENDOR_ID_ATEN            0x0557
+ #define USB_DEVICE_ID_ATEN_UC100KM    0x2004
diff --git a/queue-4.9/hid-asus-fix-keyboard-support.patch b/queue-4.9/hid-asus-fix-keyboard-support.patch
new file mode 100644 (file)
index 0000000..553ce26
--- /dev/null
@@ -0,0 +1,88 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:15 +0000
+Subject: HID: asus: Fix keyboard support
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-37-alexander.levin@verizon.com>
+
+From: Brendan McGrath <redmcg@redmandi.dyndns.org>
+
+[ Upstream commit c8b1b3dd89ea7b3f77a73e59c4c4495e16338e15 ]
+
+The previous submission which added Touchpad support broke the
+Keyboard support of this driver. This patch:
+1. fixes the Keyboard support (by assigning drvdata->input);
+2. renames NOTEBOOK_QUIRKS to KEYBOARD_QUIRKS;
+3. adds the NO_INIT_REPORT quirk to the KEYBOARD_QUIRKS; and
+4. sets the input->name to 'Asus Keyboard' for the keyboard
+
+Signed-off-by: Brendan McGrath <redmcg@redmandi.dyndns.org>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-asus.c |   17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/hid/hid-asus.c
++++ b/drivers/hid/hid-asus.c
+@@ -64,7 +64,8 @@ MODULE_DESCRIPTION("Asus HID Keyboard an
+ #define QUIRK_SKIP_INPUT_MAPPING      BIT(2)
+ #define QUIRK_IS_MULTITOUCH           BIT(3)
+-#define NOTEBOOK_QUIRKS                       QUIRK_FIX_NOTEBOOK_REPORT
++#define KEYBOARD_QUIRKS                       (QUIRK_FIX_NOTEBOOK_REPORT | \
++                                               QUIRK_NO_INIT_REPORTS)
+ #define TOUCHPAD_QUIRKS                       (QUIRK_NO_INIT_REPORTS | \
+                                                QUIRK_SKIP_INPUT_MAPPING | \
+                                                QUIRK_IS_MULTITOUCH)
+@@ -170,11 +171,11 @@ static int asus_raw_event(struct hid_dev
+ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
+ {
++      struct input_dev *input = hi->input;
+       struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+       if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+               int ret;
+-              struct input_dev *input = hi->input;
+               input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);
+               input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);
+@@ -191,10 +192,10 @@ static int asus_input_configured(struct
+                       hid_err(hdev, "Asus input mt init slots failed: %d\n", ret);
+                       return ret;
+               }
+-
+-              drvdata->input = input;
+       }
++      drvdata->input = input;
++
+       return 0;
+ }
+@@ -286,7 +287,11 @@ static int asus_probe(struct hid_device
+               goto err_stop_hw;
+       }
+-      drvdata->input->name = "Asus TouchPad";
++      if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
++              drvdata->input->name = "Asus TouchPad";
++      } else {
++              drvdata->input->name = "Asus Keyboard";
++      }
+       if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+               ret = asus_start_multitouch(hdev);
+@@ -315,7 +320,7 @@ static __u8 *asus_report_fixup(struct hi
+ static const struct hid_device_id asus_devices[] = {
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
+-               USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), NOTEBOOK_QUIRKS},
++               USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), KEYBOARD_QUIRKS},
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
+                        USB_DEVICE_ID_ASUSTEK_TOUCHPAD), TOUCHPAD_QUIRKS },
+       { }
index a06bca031adfaa74831218fa005396c9ee84f3d8..7fe32c355c8f0f5c1e2bde506488063d27698cad 100644 (file)
@@ -19,7 +19,6 @@ device can be powered on afterwards.
 Signed-off-by: HungNien Chen <hn.chen@weidahitech.com>
 Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
 Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-
 Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 ---
diff --git a/queue-4.9/hid-microsoft-add-surface-4-type-cover-pro-4-not-jp-versions.patch b/queue-4.9/hid-microsoft-add-surface-4-type-cover-pro-4-not-jp-versions.patch
new file mode 100644 (file)
index 0000000..a4e9321
--- /dev/null
@@ -0,0 +1,84 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:16 +0000
+Subject: HID: microsoft: Add Surface 4 type cover pro 4 not JP versions
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-38-alexander.levin@verizon.com>
+
+From: Daniel Keller <daniel.keller@gcd.de>
+
+[ Upstream commit 2ae3986b84e9d325bc92a1efbcf0c6b0f5016b35 ]
+
+Adding support for not JP versions of the Microsoft Surface 4 Type Cover Pro
+
+[jkosina@suse.cz: The identical patch has been sent by Jeff Farthing, so I am
+ including his signoff as well]
+
+Signed-off-by: Jeff Farthing <jeff@jfarthing.com>
+Signed-off-by: Daniel Keller <daniel.keller@gcd.de>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-core.c          |    4 ++++
+ drivers/hid/hid-ids.h           |    2 ++
+ drivers/hid/hid-microsoft.c     |    4 ++++
+ drivers/hid/usbhid/hid-quirks.c |    2 ++
+ 4 files changed, 12 insertions(+)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -727,6 +727,8 @@ static void hid_scan_collection(struct h
+           (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
++           hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 ||
++           hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP ||
+            hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
+           hid->group == HID_GROUP_MULTITOUCH)
+@@ -1983,6 +1985,8 @@ static const struct hid_device_id hid_ha
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -724,6 +724,8 @@
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3    0x07dc
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2  0x07e2
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
++#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 0x07e4
++#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 0x07e8
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9
+ #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
+--- a/drivers/hid/hid-microsoft.c
++++ b/drivers/hid/hid-microsoft.c
+@@ -280,6 +280,10 @@ static const struct hid_device_id ms_dev
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
+               .driver_data = MS_HIDINPUT },
++      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4),
++              .driver_data = MS_HIDINPUT },
++      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2),
++              .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP),
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -104,6 +104,8 @@ static const struct hid_blacklist {
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
++      { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4, HID_QUIRK_NO_INIT_REPORTS },
++      { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/queue-4.9/hid-multitouch-do-not-retrieve-all-reports-for-all-devices.patch b/queue-4.9/hid-multitouch-do-not-retrieve-all-reports-for-all-devices.patch
new file mode 100644 (file)
index 0000000..095153c
--- /dev/null
@@ -0,0 +1,146 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:07 +0000
+Subject: HID: multitouch: do not retrieve all reports for all devices
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-14-alexander.levin@verizon.com>
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+[ Upstream commit b897f6db3ae2cd9a42377f8b1865450f34ceff0e ]
+
+We already have in place a quirk for Windows 8 devices, but it looks
+like the Surface Cover are not conforming to it.
+Given that we are only interested in 3 feature reports (the ones that
+the Windows driver retrieves), we should be safe to unconditionally apply
+the quirk to everybody.
+
+In case there is an issue with a controller, we can always mark it as such
+in the transport driver, and hid-multitouch won't try to retrieve the
+feature report.
+
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-multitouch.c |   76 ++++++++++++++++++++++---------------------
+ 1 file changed, 40 insertions(+), 36 deletions(-)
+
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -108,6 +108,7 @@ struct mt_device {
+       int cc_value_index;     /* contact count value index in the field */
+       unsigned last_slot_field;       /* the last field of a slot */
+       unsigned mt_report_id;  /* the report ID of the multitouch device */
++      unsigned long initial_quirks;   /* initial quirks state */
+       __s16 inputmode;        /* InputMode HID feature, -1 if non-existent */
+       __s16 inputmode_index;  /* InputMode HID feature index in the report */
+       __s16 maxcontact_report_id;     /* Maximum Contact Number HID feature,
+@@ -318,13 +319,10 @@ static void mt_get_feature(struct hid_de
+       u8 *buf;
+       /*
+-       * Only fetch the feature report if initial reports are not already
+-       * been retrieved. Currently this is only done for Windows 8 touch
+-       * devices.
++       * Do not fetch the feature report if the device has been explicitly
++       * marked as non-capable.
+        */
+-      if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS))
+-              return;
+-      if (td->mtclass.name != MT_CLS_WIN_8)
++      if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS)
+               return;
+       buf = hid_alloc_report_buf(report, GFP_KERNEL);
+@@ -1085,36 +1083,6 @@ static int mt_probe(struct hid_device *h
+               }
+       }
+-      /* This allows the driver to correctly support devices
+-       * that emit events over several HID messages.
+-       */
+-      hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+-
+-      /*
+-       * This allows the driver to handle different input sensors
+-       * that emits events through different reports on the same HID
+-       * device.
+-       */
+-      hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+-      hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
+-
+-      /*
+-       * Handle special quirks for Windows 8 certified devices.
+-       */
+-      if (id->group == HID_GROUP_MULTITOUCH_WIN_8)
+-              /*
+-               * Some multitouch screens do not like to be polled for input
+-               * reports. Fortunately, the Win8 spec says that all touches
+-               * should be sent during each report, making the initialization
+-               * of input reports unnecessary.
+-               *
+-               * In addition some touchpads do not behave well if we read
+-               * all feature reports from them. Instead we prevent
+-               * initial report fetching and then selectively fetch each
+-               * report we are interested in.
+-               */
+-              hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+-
+       td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
+       if (!td) {
+               dev_err(&hdev->dev, "cannot allocate multitouch data\n");
+@@ -1138,6 +1106,39 @@ static int mt_probe(struct hid_device *h
+       if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
+               td->serial_maybe = true;
++      /*
++       * Store the initial quirk state
++       */
++      td->initial_quirks = hdev->quirks;
++
++      /* This allows the driver to correctly support devices
++       * that emit events over several HID messages.
++       */
++      hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
++
++      /*
++       * This allows the driver to handle different input sensors
++       * that emits events through different reports on the same HID
++       * device.
++       */
++      hdev->quirks |= HID_QUIRK_MULTI_INPUT;
++      hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
++
++      /*
++       * Some multitouch screens do not like to be polled for input
++       * reports. Fortunately, the Win8 spec says that all touches
++       * should be sent during each report, making the initialization
++       * of input reports unnecessary. For Win7 devices, well, let's hope
++       * they will still be happy (this is only be a problem if a touch
++       * was already there while probing the device).
++       *
++       * In addition some touchpads do not behave well if we read
++       * all feature reports from them. Instead we prevent
++       * initial report fetching and then selectively fetch each
++       * report we are interested in.
++       */
++      hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
++
+       ret = hid_parse(hdev);
+       if (ret != 0)
+               return ret;
+@@ -1206,8 +1207,11 @@ static int mt_resume(struct hid_device *
+ static void mt_remove(struct hid_device *hdev)
+ {
++      struct mt_device *td = hid_get_drvdata(hdev);
++
+       sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
+       hid_hw_stop(hdev);
++      hdev->quirks = td->initial_quirks;
+ }
+ /*
diff --git a/queue-4.9/hid-multitouch-enable-the-surface-3-type-cover-to-report-multitouch-data.patch b/queue-4.9/hid-multitouch-enable-the-surface-3-type-cover-to-report-multitouch-data.patch
new file mode 100644 (file)
index 0000000..aef70fd
--- /dev/null
@@ -0,0 +1,94 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:06 +0000
+Subject: HID: multitouch: enable the Surface 3 Type Cover to report multitouch data
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-13-alexander.levin@verizon.com>
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+[ Upstream commit 8fe89ef076fa104f514da6ef61d90f5bf93488e3 ]
+
+There is no reasons to filter out keyboard and consumer control collections
+in hid-multitouch.
+With the previous hid-input fix, there is now a full support of the Type
+Cover and we can remove all specific bits from hid-core and hid-microsoft.
+
+hid-multitouch will automatically set HID_QUIRK_NO_INIT_REPORTS so we can
+also remove it from the list of ushbid quirks.
+
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-core.c          |    2 --
+ drivers/hid/hid-ids.h           |    1 -
+ drivers/hid/hid-microsoft.c     |    2 --
+ drivers/hid/hid-multitouch.c    |    4 +++-
+ drivers/hid/usbhid/hid-quirks.c |    1 -
+ 5 files changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -728,7 +728,6 @@ static void hid_scan_collection(struct h
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP ||
+-           hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
+            hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
+           hid->group == HID_GROUP_MULTITOUCH)
+               hid->group = HID_GROUP_GENERIC;
+@@ -1984,7 +1983,6 @@ static const struct hid_device_id hid_ha
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -724,7 +724,6 @@
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2  0x07e2
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9
+-#define USB_DEVICE_ID_MS_TYPE_COVER_3    0x07de
+ #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
+ #define USB_VENDOR_ID_MOJO            0x8282
+--- a/drivers/hid/hid-microsoft.c
++++ b/drivers/hid/hid-microsoft.c
+@@ -282,8 +282,6 @@ static const struct hid_device_id ms_dev
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP),
+               .driver_data = MS_HIDINPUT },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
+-              .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD),
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -842,7 +842,9 @@ static int mt_input_mapping(struct hid_d
+       if (!td->mtclass.export_all_inputs &&
+           field->application != HID_DG_TOUCHSCREEN &&
+           field->application != HID_DG_PEN &&
+-          field->application != HID_DG_TOUCHPAD)
++          field->application != HID_DG_TOUCHPAD &&
++          field->application != HID_GD_KEYBOARD &&
++          field->application != HID_CP_CONSUMER_CONTROL)
+               return -1;
+       /*
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -105,7 +105,6 @@ static const struct hid_blacklist {
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS },
+-      { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/queue-4.9/hid-multitouch-enable-the-surface-4-type-cover-pro-jp-to-report-multitouch-data.patch b/queue-4.9/hid-multitouch-enable-the-surface-4-type-cover-pro-jp-to-report-multitouch-data.patch
new file mode 100644 (file)
index 0000000..c76e5c6
--- /dev/null
@@ -0,0 +1,80 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:16 +0000
+Subject: HID: multitouch: enable the Surface 4 Type Cover Pro (JP) to report multitouch data
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-39-alexander.levin@verizon.com>
+
+From: Yuta Kobayashi <alu.ula@outlook.com>
+
+[ Upstream commit 4fed0231994b27b3896bc63885ac66d02fff625b ]
+
+Since commit 8fe89ef076fa1 ("HID: multitouch: enable the Surface 3 Type
+Cover to report multitouch data"), the TypeCover can be properly handled
+by hid-multitouch and don't require any special quirk in the kernel.
+
+Remove the support of the Surface 4 Type Cover Pro (JP) from
+hid-microsoft so it can properly report multitouch from the touchpad.
+
+Signed-off-by: Yuta Kobayashi <alu.ula@outlook.com>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-core.c          |    2 --
+ drivers/hid/hid-ids.h           |    1 -
+ drivers/hid/hid-microsoft.c     |    2 --
+ drivers/hid/usbhid/hid-quirks.c |    1 -
+ 4 files changed, 6 deletions(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -729,7 +729,6 @@ static void hid_scan_collection(struct h
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 ||
+-           hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP ||
+            hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
+           hid->group == HID_GROUP_MULTITOUCH)
+               hid->group = HID_GROUP_GENERIC;
+@@ -1987,7 +1986,6 @@ static const struct hid_device_id hid_ha
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2) },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -726,7 +726,6 @@
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 0x07e4
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 0x07e8
+-#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9
+ #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
+ #define USB_VENDOR_ID_MOJO            0x8282
+--- a/drivers/hid/hid-microsoft.c
++++ b/drivers/hid/hid-microsoft.c
+@@ -284,8 +284,6 @@ static const struct hid_device_id ms_dev
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2),
+               .driver_data = MS_HIDINPUT },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP),
+-              .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD),
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -106,7 +106,6 @@ static const struct hid_blacklist {
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2, HID_QUIRK_NO_INIT_REPORTS },
+-      { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/queue-4.9/hid-sensor-hub-add-quirk-for-microchip-mm7150.patch b/queue-4.9/hid-sensor-hub-add-quirk-for-microchip-mm7150.patch
new file mode 100644 (file)
index 0000000..dc4c00b
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:06 +0000
+Subject: HID: sensor-hub: add quirk for Microchip MM7150
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-12-alexander.levin@verizon.com>
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+[ Upstream commit 5cc5084dd9afa2f9bf953b0217bdb1b7c2158be1 ]
+
+One more device requiring a quirk :/
+
+Reported-by: Christian-Nils Boda <christian-nils.boda@gadz.org>
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-sensor-hub.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/hid/hid-sensor-hub.c
++++ b/drivers/hid/hid-sensor-hub.c
+@@ -799,6 +799,9 @@ static const struct hid_device_id sensor
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
+                       0x07bd), /* Microsoft Surface 3 */
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
++      { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROCHIP,
++                      0x0f01), /* MM7150 */
++                      .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
+                       USB_DEVICE_ID_STM_HID_SENSOR),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
diff --git a/queue-4.9/hid-sensor-hub-add-quirk-for-microsoft-surface-3.patch b/queue-4.9/hid-sensor-hub-add-quirk-for-microsoft-surface-3.patch
new file mode 100644 (file)
index 0000000..d55320d
--- /dev/null
@@ -0,0 +1,36 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:06 +0000
+Subject: HID: sensor-hub add quirk for Microsoft Surface 3
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-11-alexander.levin@verizon.com>
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+[ Upstream commit da809197a919942ab6ee0d008c20a011872181b1 ]
+
+One more device requiring a quirk :/
+
+[jkosina@suse.cz: update comment based on Bastien's remark]
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Tested-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-sensor-hub.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/hid/hid-sensor-hub.c
++++ b/drivers/hid/hid-sensor-hub.c
+@@ -796,6 +796,9 @@ static const struct hid_device_id sensor
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
+                       USB_DEVICE_ID_MS_TYPE_COVER_2),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
++      { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
++                      0x07bd), /* Microsoft Surface 3 */
++                      .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
+                       USB_DEVICE_ID_STM_HID_SENSOR),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
diff --git a/queue-4.9/hid-usbhid-add-quirk-for-mayflash-dragonrise-dolphinbar.patch b/queue-4.9/hid-usbhid-add-quirk-for-mayflash-dragonrise-dolphinbar.patch
new file mode 100644 (file)
index 0000000..1366778
--- /dev/null
@@ -0,0 +1,46 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:18 +0000
+Subject: HID: usbhid: Add quirk for Mayflash/Dragonrise DolphinBar.
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-43-alexander.levin@verizon.com>
+
+From: Marcel Hasler <mahasler@gmail.com>
+
+[ Upstream commit 8aa2cc7e747881d1fd52db28261b201d4e3e5565 ]
+
+The DolphinBar by Mayflash (identified as Dragonrise) needs
+HID_QUIRK_MULTI_INPUT to split it up into four input devices. Without this
+quirk the adapter is falsely recognized as a tablet. See also bug 115841
+(https://bugzilla.kernel.org/show_bug.cgi?id=115841).
+
+Signed-off-by: Marcel Hasler <mahasler@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-ids.h           |    1 +
+ drivers/hid/usbhid/hid-quirks.c |    1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -322,6 +322,7 @@
+ #define USB_VENDOR_ID_DRAGONRISE              0x0079
+ #define USB_DEVICE_ID_DRAGONRISE_WIIU         0x1800
+ #define USB_DEVICE_ID_DRAGONRISE_PS3          0x1801
++#define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR   0x1803
+ #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE     0x1843
+ #define USB_VENDOR_ID_DWAV            0x0eef
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -84,6 +84,7 @@ static const struct hid_blacklist {
+       { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT },
++      { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
diff --git a/queue-4.9/hid-usbhid-add-quirk-for-the-futaba-tosd-5711bb-vfd.patch b/queue-4.9/hid-usbhid-add-quirk-for-the-futaba-tosd-5711bb-vfd.patch
new file mode 100644 (file)
index 0000000..cba53ce
--- /dev/null
@@ -0,0 +1,46 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:17 +0000
+Subject: HID: usbhid: Add quirk for the Futaba TOSD-5711BB VFD
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-42-alexander.levin@verizon.com>
+
+From: Alex Wood <thetewood@gmail.com>
+
+[ Upstream commit f83f90cf7ba68deb09406ea9da80852a64c4db29 ]
+
+The Futaba TOSD-5711BB VFD crashes when the initial HID report is requested,
+register the display in hid-ids and tell hid-quirks to not do the init.
+
+Signed-off-by: Alex Wood <thetewood@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-ids.h           |    3 +++
+ drivers/hid/usbhid/hid-quirks.c |    1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -368,6 +368,9 @@
+ #define USB_VENDOR_ID_FLATFROG                0x25b5
+ #define USB_DEVICE_ID_MULTITOUCH_3200 0x0002
++#define USB_VENDOR_ID_FUTABA            0x0547
++#define USB_DEVICE_ID_LED_DISPLAY       0x7000
++
+ #define USB_VENDOR_ID_ESSENTIAL_REALITY       0x0d7f
+ #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -89,6 +89,7 @@ static const struct hid_blacklist {
+       { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
++      { USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
diff --git a/queue-4.9/hid-wacom-don-t-apply-generic-settings-to-old-devices.patch b/queue-4.9/hid-wacom-don-t-apply-generic-settings-to-old-devices.patch
new file mode 100644 (file)
index 0000000..3eadafd
--- /dev/null
@@ -0,0 +1,42 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:31 +0000
+Subject: HID: wacom: don't apply generic settings to old devices
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-78-alexander.levin@verizon.com>
+
+From: Ping Cheng <pinglinux@gmail.com>
+
+[ Upstream commit e7deb1570a527d3c74be4e21a72b1b459605c501 ]
+
+Non-generic devices have numbered_buttons set for both pen and
+touch interfaces by default. The actual number of buttons on the
+interface is normally manually decided later, which is different
+from what those HID generic devices are processed, where number
+of buttons are directly retrieved from HID descriptors.
+
+This patch adds the missed HID_GENERIC check and moves the statement
+to wacom_setup_pad_input_capabilities since it's not a quirk anymore.
+
+Signed-off-by: Ping Cheng <ping.cheng@wacom.com>
+Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/wacom_wac.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -2896,6 +2896,9 @@ int wacom_setup_pad_input_capabilities(s
+ {
+       struct wacom_features *features = &wacom_wac->features;
++      if ((features->type == HID_GENERIC) && features->numbered_buttons > 0)
++              features->device_type |= WACOM_DEVICETYPE_PAD;
++
+       if (!(features->device_type & WACOM_DEVICETYPE_PAD))
+               return -ENODEV;
diff --git a/queue-4.9/input-gpio_keys-add-support-for-gpio-descriptors.patch b/queue-4.9/input-gpio_keys-add-support-for-gpio-descriptors.patch
new file mode 100644 (file)
index 0000000..72603a2
--- /dev/null
@@ -0,0 +1,144 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:22 +0000
+Subject: Input: gpio_keys - add support for GPIO descriptors
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-56-alexander.levin@verizon.com>
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit 5feeca3c1e39c01f9ef5abc94dea94021ccf94fc ]
+
+GPIO descriptors are the preferred way over legacy GPIO numbers
+nowadays. Convert the driver to use GPIO descriptors internally but
+still allow passing legacy GPIO numbers from platform data to support
+existing platforms.
+
+Based on commits 633a21d80b4a2cd6 ("input: gpio_keys_polled: Add support
+for GPIO descriptors") and 1ae5ddb6f8837558 ("Input: gpio_keys_polled -
+request GPIO pin as input.").
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/keyboard/gpio_keys.c |   37 ++++++++++++++++++++++++++-----------
+ 1 file changed, 26 insertions(+), 11 deletions(-)
+
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -26,6 +26,7 @@
+ #include <linux/gpio_keys.h>
+ #include <linux/workqueue.h>
+ #include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_gpio.h>
+@@ -35,6 +36,7 @@
+ struct gpio_button_data {
+       const struct gpio_keys_button *button;
+       struct input_dev *input;
++      struct gpio_desc *gpiod;
+       struct timer_list release_timer;
+       unsigned int release_delay;     /* in msecs, for IRQ-only buttons */
+@@ -140,7 +142,7 @@ static void gpio_keys_disable_button(str
+                */
+               disable_irq(bdata->irq);
+-              if (gpio_is_valid(bdata->button->gpio))
++              if (bdata->gpiod)
+                       cancel_delayed_work_sync(&bdata->work);
+               else
+                       del_timer_sync(&bdata->release_timer);
+@@ -358,19 +360,20 @@ static void gpio_keys_gpio_report_event(
+       const struct gpio_keys_button *button = bdata->button;
+       struct input_dev *input = bdata->input;
+       unsigned int type = button->type ?: EV_KEY;
+-      int state = gpio_get_value_cansleep(button->gpio);
++      int state;
++      state = gpiod_get_value_cansleep(bdata->gpiod);
+       if (state < 0) {
+-              dev_err(input->dev.parent, "failed to get gpio state\n");
++              dev_err(input->dev.parent,
++                      "failed to get gpio state: %d\n", state);
+               return;
+       }
+-      state = (state ? 1 : 0) ^ button->active_low;
+       if (type == EV_ABS) {
+               if (state)
+                       input_event(input, type, button->code, button->value);
+       } else {
+-              input_event(input, type, button->code, !!state);
++              input_event(input, type, button->code, state);
+       }
+       input_sync(input);
+ }
+@@ -456,7 +459,7 @@ static void gpio_keys_quiesce_key(void *
+ {
+       struct gpio_button_data *bdata = data;
+-      if (gpio_is_valid(bdata->button->gpio))
++      if (bdata->gpiod)
+               cancel_delayed_work_sync(&bdata->work);
+       else
+               del_timer_sync(&bdata->release_timer);
+@@ -478,18 +481,30 @@ static int gpio_keys_setup_key(struct pl
+       bdata->button = button;
+       spin_lock_init(&bdata->lock);
++      /*
++       * Legacy GPIO number, so request the GPIO here and
++       * convert it to descriptor.
++       */
+       if (gpio_is_valid(button->gpio)) {
++              unsigned flags = GPIOF_IN;
++
++              if (button->active_low)
++                      flags |= GPIOF_ACTIVE_LOW;
+-              error = devm_gpio_request_one(&pdev->dev, button->gpio,
+-                                            GPIOF_IN, desc);
++              error = devm_gpio_request_one(&pdev->dev, button->gpio, flags,
++                                            desc);
+               if (error < 0) {
+                       dev_err(dev, "Failed to request GPIO %d, error %d\n",
+                               button->gpio, error);
+                       return error;
+               }
++              bdata->gpiod = gpio_to_desc(button->gpio);
++              if (!bdata->gpiod)
++                      return -EINVAL;
++
+               if (button->debounce_interval) {
+-                      error = gpio_set_debounce(button->gpio,
++                      error = gpiod_set_debounce(bdata->gpiod,
+                                       button->debounce_interval * 1000);
+                       /* use timer if gpiolib doesn't provide debounce */
+                       if (error < 0)
+@@ -500,7 +515,7 @@ static int gpio_keys_setup_key(struct pl
+               if (button->irq) {
+                       bdata->irq = button->irq;
+               } else {
+-                      irq = gpio_to_irq(button->gpio);
++                      irq = gpiod_to_irq(bdata->gpiod);
+                       if (irq < 0) {
+                               error = irq;
+                               dev_err(dev,
+@@ -575,7 +590,7 @@ static void gpio_keys_report_state(struc
+       for (i = 0; i < ddata->pdata->nbuttons; i++) {
+               struct gpio_button_data *bdata = &ddata->data[i];
+-              if (gpio_is_valid(bdata->button->gpio))
++              if (bdata->gpiod)
+                       gpio_keys_gpio_report_event(bdata);
+       }
+       input_sync(input);
diff --git a/queue-4.9/mmc-sdhci-msm-enable-few-quirks.patch b/queue-4.9/mmc-sdhci-msm-enable-few-quirks.patch
new file mode 100644 (file)
index 0000000..b506f6a
--- /dev/null
@@ -0,0 +1,38 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:07 +0000
+Subject: mmc: sdhci-msm: Enable few quirks
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-15-alexander.levin@verizon.com>
+
+From: Ritesh Harjani <riteshh@codeaurora.org>
+
+[ Upstream commit a0e3142869d29688de6f77be31aa7a401a4a88f1 ]
+
+sdhc-msm controller needs this SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN
+& SDHCI_QUIRK2_PRESET_VALUE_BROKEN to be set. Hence setting it.
+
+Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
+Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci-msm.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/sdhci-msm.c
++++ b/drivers/mmc/host/sdhci-msm.c
+@@ -524,7 +524,9 @@ static const struct sdhci_ops sdhci_msm_
+ static const struct sdhci_pltfm_data sdhci_msm_pdata = {
+       .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+                 SDHCI_QUIRK_NO_CARD_NO_RESET |
+-                SDHCI_QUIRK_SINGLE_POWER_WRITE,
++                SDHCI_QUIRK_SINGLE_POWER_WRITE |
++                SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
++      .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+       .ops = &sdhci_msm_ops,
+ };
diff --git a/queue-4.9/mmc-sdhci-of-esdhc-remove-default-broken-cd-for-arm.patch b/queue-4.9/mmc-sdhci-of-esdhc-remove-default-broken-cd-for-arm.patch
new file mode 100644 (file)
index 0000000..d096eeb
--- /dev/null
@@ -0,0 +1,71 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:33 +0000
+Subject: mmc: sdhci-of-esdhc: remove default broken-cd for ARM
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-85-alexander.levin@verizon.com>
+
+From: yangbo lu <yangbo.lu@nxp.com>
+
+[ Upstream commit e9acc77dd046b22c7ebf70e35f68968978445f8b ]
+
+Initially all QorIQ platforms were PowerPC architecture and they didn't
+support card detection except several platforms. The driver added the
+quirk SDHCI_QUIRK_BROKEN_CARD_DETECTION as default and this made broken-cd
+property in dts node didn't work. Now QorIQ platform turns to ARM
+architecture and most of them could support card detection. However it's
+a large number of dts trees that need to be fixed with broken-cd if we
+remove the default SDHCI_QUIRK_BROKEN_CARD_DETECTION in driver. And the
+users don't want to see this. So this patch is to remove this default
+quirk just for ARM and keep it for PowerPC.(Note, QorIQ PowerPC platform
+only has big-endian eSDHC while QorIQ ARM platform has big-endian or
+little-endian eSDHC) This makes broken-cd property work again for ARM.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -559,16 +559,19 @@ static const struct sdhci_ops sdhci_esdh
+ };
+ static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = {
+-      .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+-              | SDHCI_QUIRK_NO_CARD_NO_RESET
+-              | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
++      .quirks = ESDHC_DEFAULT_QUIRKS |
++#ifdef CONFIG_PPC
++                SDHCI_QUIRK_BROKEN_CARD_DETECTION |
++#endif
++                SDHCI_QUIRK_NO_CARD_NO_RESET |
++                SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+       .ops = &sdhci_esdhc_be_ops,
+ };
+ static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
+-      .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+-              | SDHCI_QUIRK_NO_CARD_NO_RESET
+-              | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
++      .quirks = ESDHC_DEFAULT_QUIRKS |
++                SDHCI_QUIRK_NO_CARD_NO_RESET |
++                SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+       .ops = &sdhci_esdhc_le_ops,
+ };
+@@ -623,8 +626,7 @@ static int sdhci_esdhc_probe(struct plat
+           of_device_is_compatible(np, "fsl,p5020-esdhc") ||
+           of_device_is_compatible(np, "fsl,p4080-esdhc") ||
+           of_device_is_compatible(np, "fsl,p1020-esdhc") ||
+-          of_device_is_compatible(np, "fsl,t1040-esdhc") ||
+-          of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
++          of_device_is_compatible(np, "fsl,t1040-esdhc"))
+               host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+       if (of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
diff --git a/queue-4.9/net-mlx4_core-use-device-id-defines.patch b/queue-4.9/net-mlx4_core-use-device-id-defines.patch
new file mode 100644 (file)
index 0000000..ba0fffc
--- /dev/null
@@ -0,0 +1,119 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:04 +0000
+Subject: net/mlx4_core: Use device ID defines
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-8-alexander.levin@verizon.com>
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit c19e4b9037fa8a0477525a64e93847f534e8cc17 ]
+
+We added a bunch of new Mellanox device ID definitions because they'll be
+used by INTx quirks.  Use them in the mlx4 ID table also so grep can find
+both places.  No functional change intended.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Tariq Toukan <tariqt@mellanox.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/mellanox/mlx4/main.c |   84 +++++++++++++++---------------
+ 1 file changed, 43 insertions(+), 41 deletions(-)
+
+--- a/drivers/net/ethernet/mellanox/mlx4/main.c
++++ b/drivers/net/ethernet/mellanox/mlx4/main.c
+@@ -4020,49 +4020,51 @@ int mlx4_restart_one(struct pci_dev *pde
+       return err;
+ }
++#define MLX_SP(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_FORCE_SENSE_PORT }
++#define MLX_VF(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_IS_VF }
++#define MLX_GN(id) { PCI_VDEVICE(MELLANOX, id), 0 }
++
+ static const struct pci_device_id mlx4_pci_table[] = {
+-      /* MT25408 "Hermon" SDR */
+-      { PCI_VDEVICE(MELLANOX, 0x6340), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25408 "Hermon" DDR */
+-      { PCI_VDEVICE(MELLANOX, 0x634a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25408 "Hermon" QDR */
+-      { PCI_VDEVICE(MELLANOX, 0x6354), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25408 "Hermon" DDR PCIe gen2 */
+-      { PCI_VDEVICE(MELLANOX, 0x6732), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25408 "Hermon" QDR PCIe gen2 */
+-      { PCI_VDEVICE(MELLANOX, 0x673c), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25408 "Hermon" EN 10GigE */
+-      { PCI_VDEVICE(MELLANOX, 0x6368), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
+-      { PCI_VDEVICE(MELLANOX, 0x6750), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25458 ConnectX EN 10GBASE-T 10GigE */
+-      { PCI_VDEVICE(MELLANOX, 0x6372), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
+-      { PCI_VDEVICE(MELLANOX, 0x675a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT26468 ConnectX EN 10GigE PCIe gen2*/
+-      { PCI_VDEVICE(MELLANOX, 0x6764), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
+-      { PCI_VDEVICE(MELLANOX, 0x6746), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT26478 ConnectX2 40GigE PCIe gen2 */
+-      { PCI_VDEVICE(MELLANOX, 0x676e), MLX4_PCI_DEV_FORCE_SENSE_PORT },
+-      /* MT25400 Family [ConnectX-2 Virtual Function] */
+-      { PCI_VDEVICE(MELLANOX, 0x1002), MLX4_PCI_DEV_IS_VF },
++      /* MT25408 "Hermon" */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_SDR),      /* SDR */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_DDR),      /* DDR */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_QDR),      /* QDR */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_DDR_GEN2), /* DDR Gen2 */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_QDR_GEN2), /* QDR Gen2 */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_EN),       /* EN 10GigE */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_EN_GEN2),  /* EN 10GigE Gen2 */
++      /* MT25458 ConnectX EN 10GBASE-T */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN),
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_T_GEN2),      /* Gen2 */
++      /* MT26468 ConnectX EN 10GigE PCIe Gen2*/
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_GEN2),
++      /* MT26438 ConnectX EN 40GigE PCIe Gen2 5GT/s */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_5_GEN2),
++      /* MT26478 ConnectX2 40GigE PCIe Gen2 */
++      MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX2),
++      /* MT25400 Family [ConnectX-2] */
++      MLX_VF(0x1002),                                 /* Virtual Function */
+       /* MT27500 Family [ConnectX-3] */
+-      { PCI_VDEVICE(MELLANOX, 0x1003), 0 },
+-      /* MT27500 Family [ConnectX-3 Virtual Function] */
+-      { PCI_VDEVICE(MELLANOX, 0x1004), MLX4_PCI_DEV_IS_VF },
+-      { PCI_VDEVICE(MELLANOX, 0x1005), 0 }, /* MT27510 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x1006), 0 }, /* MT27511 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x1007), 0 }, /* MT27520 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x1008), 0 }, /* MT27521 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x1009), 0 }, /* MT27530 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x100a), 0 }, /* MT27531 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x100b), 0 }, /* MT27540 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x100c), 0 }, /* MT27541 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x100d), 0 }, /* MT27550 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x100e), 0 }, /* MT27551 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x100f), 0 }, /* MT27560 Family */
+-      { PCI_VDEVICE(MELLANOX, 0x1010), 0 }, /* MT27561 Family */
++      MLX_GN(PCI_DEVICE_ID_MELLANOX_CONNECTX3),
++      MLX_VF(0x1004),                                 /* Virtual Function */
++      MLX_GN(0x1005),                                 /* MT27510 Family */
++      MLX_GN(0x1006),                                 /* MT27511 Family */
++      MLX_GN(PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO),   /* MT27520 Family */
++      MLX_GN(0x1008),                                 /* MT27521 Family */
++      MLX_GN(0x1009),                                 /* MT27530 Family */
++      MLX_GN(0x100a),                                 /* MT27531 Family */
++      MLX_GN(0x100b),                                 /* MT27540 Family */
++      MLX_GN(0x100c),                                 /* MT27541 Family */
++      MLX_GN(0x100d),                                 /* MT27550 Family */
++      MLX_GN(0x100e),                                 /* MT27551 Family */
++      MLX_GN(0x100f),                                 /* MT27560 Family */
++      MLX_GN(0x1010),                                 /* MT27561 Family */
++
++      /*
++       * See the mellanox_check_broken_intx_masking() quirk when
++       * adding devices
++       */
++
+       { 0, }
+ };
diff --git a/queue-4.9/nvme-simplify-stripe-quirk.patch b/queue-4.9/nvme-simplify-stripe-quirk.patch
new file mode 100644 (file)
index 0000000..0af4833
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:16 +0000
+Subject: nvme: simplify stripe quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-40-alexander.levin@verizon.com>
+
+From: Keith Busch <keith.busch@intel.com>
+
+[ Upstream commit e6282aef7b89a11d26e731060c4409b7aac278bf ]
+
+Some OEMs believe they own the Identify Controller vendor specific
+region and will repurpose it with their own values. While not common,
+we can't rely on the PCI VID:DID to tell use how to decode the field
+we reserved for this as the stripe size so we need to do something else
+for the list of devices using this quirk.
+
+The field was supposed to allow flexibility on the device's back-end
+striping, but it turned out that never materialized; the chunk is always
+the same as MDTS in the products subscribing to this quirk, so this
+patch removes the stripe_size field and sets the chunk to the max hw
+transfer size for the devices using this quirk.
+
+Signed-off-by: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/core.c |   17 ++---------------
+ drivers/nvme/host/nvme.h |    1 -
+ 2 files changed, 2 insertions(+), 16 deletions(-)
+
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -1204,8 +1204,8 @@ static void nvme_set_queue_limits(struct
+               blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors);
+               blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX));
+       }
+-      if (ctrl->stripe_size)
+-              blk_queue_chunk_sectors(q, ctrl->stripe_size >> 9);
++      if (ctrl->quirks & NVME_QUIRK_STRIPE_SIZE)
++              blk_queue_chunk_sectors(q, ctrl->max_hw_sectors);
+       blk_queue_virt_boundary(q, ctrl->page_size - 1);
+       if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
+               vwc = true;
+@@ -1261,19 +1261,6 @@ int nvme_init_identify(struct nvme_ctrl
+       ctrl->max_hw_sectors =
+               min_not_zero(ctrl->max_hw_sectors, max_hw_sectors);
+-      if ((ctrl->quirks & NVME_QUIRK_STRIPE_SIZE) && id->vs[3]) {
+-              unsigned int max_hw_sectors;
+-
+-              ctrl->stripe_size = 1 << (id->vs[3] + page_shift);
+-              max_hw_sectors = ctrl->stripe_size >> (page_shift - 9);
+-              if (ctrl->max_hw_sectors) {
+-                      ctrl->max_hw_sectors = min(max_hw_sectors,
+-                                                      ctrl->max_hw_sectors);
+-              } else {
+-                      ctrl->max_hw_sectors = max_hw_sectors;
+-              }
+-      }
+-
+       nvme_set_queue_limits(ctrl, ctrl->admin_q);
+       ctrl->sgls = le32_to_cpu(id->sgls);
+       ctrl->kas = le16_to_cpu(id->kas);
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -121,7 +121,6 @@ struct nvme_ctrl {
+       u32 page_size;
+       u32 max_hw_sectors;
+-      u32 stripe_size;
+       u16 oncs;
+       u16 vid;
+       atomic_t abort_limit;
diff --git a/queue-4.9/pci-acpi-check-for-platform-specific-mcfg-quirks.patch b/queue-4.9/pci-acpi-check-for-platform-specific-mcfg-quirks.patch
new file mode 100644 (file)
index 0000000..cb56c22
--- /dev/null
@@ -0,0 +1,167 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:10 +0000
+Subject: PCI/ACPI: Check for platform-specific MCFG quirks
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-23-alexander.levin@verizon.com>
+
+From: Tomasz Nowicki <tn@semihalf.com>
+
+[ Upstream commit 5b69b85ba1ddd36be01f5c57830b37a3c8256009 ]
+
+The PCIe spec (r3.0, sec 7.2.2) specifies an "Enhanced Configuration Access
+Mechanism" (ECAM) for memory-mapped access to configuration space.  ECAM is
+required for PCIe systems unless there's a standard firmware interface for
+config access.
+
+In the absence of a firmware interface, we use pci_generic_ecam_ops, and on
+ACPI systems, we discover the ECAM space via the MCFG table and/or the _CBA
+method.
+
+Unfortunately some systems provide MCFG but don't implement ECAM according
+to spec, so we need a mechanism for quirks to make those systems work.
+
+Add an MCFG quirk mechanism to override the config accessor functions
+and/or the memory-mapped address space.
+
+A quirk is selected if it matches all of the following:
+
+  - OEM ID
+  - OEM Table ID
+  - OEM Revision
+  - PCI segment (from _SEG)
+  - PCI bus number range (from _CRS, wildcard allowed)
+
+If the quirk specifies config accessor functions or a memory-mapped address
+range, these override the defaults.
+
+[bhelgaas: changelog, reorder quirk matching, fix oem_revision typo per
+Duc, add under #ifdef CONFIG_PCI_QUIRKS]
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
+Signed-off-by: Christopher Covington <cov@codeaurora.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/pci_mcfg.c |   92 ++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 86 insertions(+), 6 deletions(-)
+
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -33,6 +33,69 @@ struct mcfg_entry {
+       u8                      bus_end;
+ };
++#ifdef CONFIG_PCI_QUIRKS
++struct mcfg_fixup {
++      char oem_id[ACPI_OEM_ID_SIZE + 1];
++      char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
++      u32 oem_revision;
++      u16 segment;
++      struct resource bus_range;
++      struct pci_ecam_ops *ops;
++      struct resource cfgres;
++};
++
++#define MCFG_BUS_RANGE(start, end)    DEFINE_RES_NAMED((start),       \
++                                              ((end) - (start) + 1),  \
++                                              NULL, IORESOURCE_BUS)
++#define MCFG_BUS_ANY                  MCFG_BUS_RANGE(0x0, 0xff)
++
++static struct mcfg_fixup mcfg_quirks[] = {
++/*    { OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
++};
++
++static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
++static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
++static u32 mcfg_oem_revision;
++
++static int pci_mcfg_quirk_matches(struct mcfg_fixup *f, u16 segment,
++                                struct resource *bus_range)
++{
++      if (!memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
++          !memcmp(f->oem_table_id, mcfg_oem_table_id,
++                  ACPI_OEM_TABLE_ID_SIZE) &&
++          f->oem_revision == mcfg_oem_revision &&
++          f->segment == segment &&
++          resource_contains(&f->bus_range, bus_range))
++              return 1;
++
++      return 0;
++}
++#endif
++
++static void pci_mcfg_apply_quirks(struct acpi_pci_root *root,
++                                struct resource *cfgres,
++                                struct pci_ecam_ops **ecam_ops)
++{
++#ifdef CONFIG_PCI_QUIRKS
++      u16 segment = root->segment;
++      struct resource *bus_range = &root->secondary;
++      struct mcfg_fixup *f;
++      int i;
++
++      for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) {
++              if (pci_mcfg_quirk_matches(f, segment, bus_range)) {
++                      if (f->cfgres.start)
++                              *cfgres = f->cfgres;
++                      if (f->ops)
++                              *ecam_ops =  f->ops;
++                      dev_info(&root->device->dev, "MCFG quirk: ECAM at %pR for %pR with %ps\n",
++                               cfgres, bus_range, *ecam_ops);
++                      return;
++              }
++      }
++#endif
++}
++
+ /* List to save MCFG entries */
+ static LIST_HEAD(pci_mcfg_list);
+@@ -61,14 +124,24 @@ int pci_mcfg_lookup(struct acpi_pci_root
+       }
+-      if (!root->mcfg_addr)
+-              return -ENXIO;
+-
+ skip_lookup:
+       memset(&res, 0, sizeof(res));
+-      res.start = root->mcfg_addr + (bus_res->start << 20);
+-      res.end = res.start + (resource_size(bus_res) << 20) - 1;
+-      res.flags = IORESOURCE_MEM;
++      if (root->mcfg_addr) {
++              res.start = root->mcfg_addr + (bus_res->start << 20);
++              res.end = res.start + (resource_size(bus_res) << 20) - 1;
++              res.flags = IORESOURCE_MEM;
++      }
++
++      /*
++       * Allow quirks to override default ECAM ops and CFG resource
++       * range.  This may even fabricate a CFG resource range in case
++       * MCFG does not have it.  Invalid CFG start address means MCFG
++       * firmware bug or we need another quirk in array.
++       */
++      pci_mcfg_apply_quirks(root, &res, &ops);
++      if (!res.start)
++              return -ENXIO;
++
+       *cfgres = res;
+       *ecam_ops = ops;
+       return 0;
+@@ -101,6 +174,13 @@ static __init int pci_mcfg_parse(struct
+               list_add(&e->list, &pci_mcfg_list);
+       }
++#ifdef CONFIG_PCI_QUIRKS
++      /* Save MCFG IDs and revision for quirks matching */
++      memcpy(mcfg_oem_id, header->oem_id, ACPI_OEM_ID_SIZE);
++      memcpy(mcfg_oem_table_id, header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
++      mcfg_oem_revision = header->oem_revision;
++#endif
++
+       pr_info("MCFG table detected, %d entries\n", n);
+       return 0;
+ }
diff --git a/queue-4.9/pci-acpi-extend-pci_mcfg_lookup-to-return-ecam-config-accessors.patch b/queue-4.9/pci-acpi-extend-pci_mcfg_lookup-to-return-ecam-config-accessors.patch
new file mode 100644 (file)
index 0000000..c7c1e83
--- /dev/null
@@ -0,0 +1,144 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:09 +0000
+Subject: PCI/ACPI: Extend pci_mcfg_lookup() to return ECAM config accessors
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-22-alexander.levin@verizon.com>
+
+From: Tomasz Nowicki <tn@semihalf.com>
+
+[ Upstream commit 13983eb89d5afaa65acd4479fad151cbd4de5509 ]
+
+pci_mcfg_lookup() is the external interface to the generic MCFG code.
+Previously it merely looked up the ECAM base address for a given domain and
+bus range.  We want a way to add MCFG quirks, some of which may require
+special config accessors and adjustments to the ECAM address range.
+
+Extend pci_mcfg_lookup() so it can return a pointer to a pci_ecam_ops
+structure and a struct resource for the ECAM address space.  For now, it
+always returns &pci_generic_ecam_ops (the standard accessor) and the
+resource described by the MCFG.
+
+No functional changes intended.
+
+[bhelgaas: changelog]
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/pci.c  |   17 +++++------------
+ drivers/acpi/pci_mcfg.c  |   28 +++++++++++++++++++++++++---
+ include/linux/pci-acpi.h |    4 +++-
+ 3 files changed, 33 insertions(+), 16 deletions(-)
+
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -124,25 +124,18 @@ pci_acpi_setup_ecam_mapping(struct acpi_
+       struct device *dev = &root->device->dev;
+       struct resource *bus_res = &root->secondary;
+       u16 seg = root->segment;
++      struct pci_ecam_ops *ecam_ops;
+       struct resource cfgres;
+       struct acpi_device *adev;
+       struct pci_config_window *cfg;
+-      unsigned int bsz;
++      int ret;
+-      /* Use address from _CBA if present, otherwise lookup MCFG */
+-      if (!root->mcfg_addr)
+-              root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
+-
+-      if (!root->mcfg_addr) {
++      ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops);
++      if (ret) {
+               dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res);
+               return NULL;
+       }
+-      bsz = 1 << pci_generic_ecam_ops.bus_shift;
+-      cfgres.start = root->mcfg_addr + bus_res->start * bsz;
+-      cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
+-      cfgres.flags = IORESOURCE_MEM;
+-
+       adev = acpi_resource_consumer(&cfgres);
+       if (adev)
+               dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres,
+@@ -151,7 +144,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_
+               dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n",
+                        &cfgres);
+-      cfg = pci_ecam_create(dev, &cfgres, bus_res, &pci_generic_ecam_ops);
++      cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops);
+       if (IS_ERR(cfg)) {
+               dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
+                       PTR_ERR(cfg));
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -22,6 +22,7 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/pci-acpi.h>
++#include <linux/pci-ecam.h>
+ /* Structure to hold entries from the MCFG table */
+ struct mcfg_entry {
+@@ -35,9 +36,18 @@ struct mcfg_entry {
+ /* List to save MCFG entries */
+ static LIST_HEAD(pci_mcfg_list);
+-phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
++int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
++                  struct pci_ecam_ops **ecam_ops)
+ {
++      struct pci_ecam_ops *ops = &pci_generic_ecam_ops;
++      struct resource *bus_res = &root->secondary;
++      u16 seg = root->segment;
+       struct mcfg_entry *e;
++      struct resource res;
++
++      /* Use address from _CBA if present, otherwise lookup MCFG */
++      if (root->mcfg_addr)
++              goto skip_lookup;
+       /*
+        * We expect exact match, unless MCFG entry end bus covers more than
+@@ -45,10 +55,22 @@ phys_addr_t pci_mcfg_lookup(u16 seg, str
+        */
+       list_for_each_entry(e, &pci_mcfg_list, list) {
+               if (e->segment == seg && e->bus_start == bus_res->start &&
+-                  e->bus_end >= bus_res->end)
+-                      return e->addr;
++                  e->bus_end >= bus_res->end) {
++                      root->mcfg_addr = e->addr;
++              }
++
+       }
++      if (!root->mcfg_addr)
++              return -ENXIO;
++
++skip_lookup:
++      memset(&res, 0, sizeof(res));
++      res.start = root->mcfg_addr + (bus_res->start << 20);
++      res.end = res.start + (resource_size(bus_res) << 20) - 1;
++      res.flags = IORESOURCE_MEM;
++      *cfgres = res;
++      *ecam_ops = ops;
+       return 0;
+ }
+--- a/include/linux/pci-acpi.h
++++ b/include/linux/pci-acpi.h
+@@ -24,7 +24,9 @@ static inline acpi_status pci_acpi_remov
+ }
+ extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
+-extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
++struct pci_ecam_ops;
++extern int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
++                         struct pci_ecam_ops **ecam_ops);
+ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
+ {
diff --git a/queue-4.9/pci-add-acs-quirk-for-intel-union-point.patch b/queue-4.9/pci-add-acs-quirk-for-intel-union-point.patch
new file mode 100644 (file)
index 0000000..1693c6c
--- /dev/null
@@ -0,0 +1,67 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:26 +0000
+Subject: PCI: Add ACS quirk for Intel Union Point
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-65-alexander.levin@verizon.com>
+
+From: Alex Williamson <alex.williamson@redhat.com>
+
+[ Upstream commit 7184f5b451cf3dc61de79091d235b5d2bba2782d ]
+
+Intel 200-series chipsets have the same errata as 100-series: the ACS
+capability doesn't follow the PCIe spec, the capability and control
+registers are dwords rather than words.  Add PCIe root port device IDs to
+existing quirk.
+
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/quirks.c |   28 ++++++++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -4151,15 +4151,35 @@ static int pci_quirk_intel_pch_acs(struc
+  *
+  * N.B. This doesn't fix what lspci shows.
+  *
++ * The 100 series chipset specification update includes this as errata #23[3].
++ *
++ * The 200 series chipset (Union Point) has the same bug according to the
++ * specification update (Intel 200 Series Chipset Family Platform Controller
++ * Hub, Specification Update, January 2017, Revision 001, Document# 335194-001,
++ * Errata 22)[4].  Per the datasheet[5], root port PCI Device IDs for this
++ * chipset include:
++ *
++ * 0xa290-0xa29f PCI Express Root port #{0-16}
++ * 0xa2e7-0xa2ee PCI Express Root port #{17-24}
++ *
+  * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html
+  * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html
++ * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html
++ * [4] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-spec-update.html
++ * [5] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-1.html
+  */
+ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev)
+ {
+-      return pci_is_pcie(dev) &&
+-              pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT &&
+-              ((dev->device & ~0xf) == 0xa110 ||
+-               (dev->device >= 0xa167 && dev->device <= 0xa16a));
++      if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
++              return false;
++
++      switch (dev->device) {
++      case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */
++      case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */
++              return true;
++      }
++
++      return false;
+ }
+ #define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4)
diff --git a/queue-4.9/pci-add-acs-quirk-for-qualcomm-qdf2400-and-qdf2432.patch b/queue-4.9/pci-add-acs-quirk-for-qualcomm-qdf2400-and-qdf2432.patch
new file mode 100644 (file)
index 0000000..3ac7101
--- /dev/null
@@ -0,0 +1,77 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:34 +0000
+Subject: PCI: Add ACS quirk for Qualcomm QDF2400 and QDF2432
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-87-alexander.levin@verizon.com>
+
+From: Sinan Kaya <okaya@codeaurora.org>
+
+[ Upstream commit 33be632b8443b6ac74aa293504f430604fb9abeb ]
+
+The Qualcomm QDF2xxx root ports don't advertise an ACS capability, but they
+do provide ACS-like features to disable peer transactions and validate bus
+numbers in requests.
+
+To be specific:
+* Hardware supports source validation but it will report the issue as
+Completer Abort instead of ACS Violation.
+
+* Hardware doesn't support peer-to-peer and each root port is a root
+complex with unique segment numbers.
+
+* It is not possible for one root port to pass traffic to the other root
+port.  All PCIe transactions are terminated inside the root port.
+
+Add an ACS quirk for the QDF2400 and QDF2432 products.
+
+[bhelgaas: changelog]
+Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/quirks.c |   23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -4161,6 +4161,26 @@ static int pci_quirk_intel_pch_acs(struc
+ }
+ /*
++ * These QCOM root ports do provide ACS-like features to disable peer
++ * transactions and validate bus numbers in requests, but do not provide an
++ * actual PCIe ACS capability.  Hardware supports source validation but it
++ * will report the issue as Completer Abort instead of ACS Violation.
++ * Hardware doesn't support peer-to-peer and each root port is a root
++ * complex with unique segment numbers.  It is not possible for one root
++ * port to pass traffic to another root port.  All PCIe transactions are
++ * terminated inside the root port.
++ */
++static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags)
++{
++      u16 flags = (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV);
++      int ret = acs_flags & ~flags ? 0 : 1;
++
++      dev_info(&dev->dev, "Using QCOM ACS Quirk (%d)\n", ret);
++
++      return ret;
++}
++
++/*
+  * Sunrise Point PCH root ports implement ACS, but unfortunately as shown in
+  * the datasheet (Intel 100 Series Chipset Family PCH Datasheet, Vol. 2,
+  * 12.1.46, 12.1.47)[1] this chipset uses dwords for the ACS capability and
+@@ -4316,6 +4336,9 @@ static const struct pci_dev_acs_enabled
+       /* I219 */
+       { PCI_VENDOR_ID_INTEL, 0x15b7, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs },
++      /* QCOM QDF2xxx root ports */
++      { 0x17cb, 0x400, pci_quirk_qcom_rp_acs },
++      { 0x17cb, 0x401, pci_quirk_qcom_rp_acs },
+       /* Intel PCH root ports */
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs },
diff --git a/queue-4.9/pci-add-broadcom-northstar2-paxc-quirk-for-device-class-and-mpss.patch b/queue-4.9/pci-add-broadcom-northstar2-paxc-quirk-for-device-class-and-mpss.patch
new file mode 100644 (file)
index 0000000..9ef5607
--- /dev/null
@@ -0,0 +1,56 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:33 +0000
+Subject: PCI: Add Broadcom Northstar2 PAXC quirk for device class and MPSS
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-83-alexander.levin@verizon.com>
+
+From: Jon Mason <jon.mason@broadcom.com>
+
+[ Upstream commit ce709f86501a013e941e9986cb072eae375ddf3e ]
+
+The Broadcom Northstar2 SoC has a number of quirks for the PAXC
+(internal/fake) PCI bus.  Specifically, the PCI config space is shared
+between the root port and the first PF (ie., PF0), and a number of fields
+are tied to zero (thus preventing them from being set).  These cannot be
+"fixed" in device firmware, so we must fix them with a quirk.
+
+Signed-off-by: Jon Mason <jon.mason@broadcom.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/quirks.c |   21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2240,6 +2240,27 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_B
+                        PCI_DEVICE_ID_TIGON3_5719,
+                        quirk_brcm_5719_limit_mrrs);
++#ifdef CONFIG_PCIE_IPROC_PLATFORM
++static void quirk_paxc_bridge(struct pci_dev *pdev)
++{
++      /* The PCI config space is shared with the PAXC root port and the first
++       * Ethernet device.  So, we need to workaround this by telling the PCI
++       * code that the bridge is not an Ethernet device.
++       */
++      if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
++              pdev->class = PCI_CLASS_BRIDGE_PCI << 8;
++
++      /* MPSS is not being set properly (as it is currently 0).  This is
++       * because that area of the PCI config space is hard coded to zero, and
++       * is not modifiable by firmware.  Set this to 2 (e.g., 512 byte MPS)
++       * so that the MPS can be set to the real max value.
++       */
++      pdev->pcie_mpss = 2;
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16cd, quirk_paxc_bridge);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16f0, quirk_paxc_bridge);
++#endif
++
+ /* Originally in EDAC sources for i82875P:
+  * Intel tells BIOS developers to hide device 6 which
+  * configures the overflow device access containing
diff --git a/queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass1.x-host-controller.patch b/queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass1.x-host-controller.patch
new file mode 100644 (file)
index 0000000..612ea73
--- /dev/null
@@ -0,0 +1,140 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:12 +0000
+Subject: PCI: Add MCFG quirks for Cavium ThunderX pass1.x host controller
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-28-alexander.levin@verizon.com>
+
+From: Tomasz Nowicki <tn@semihalf.com>
+
+[ Upstream commit 648d93fc77da4f655cf13108417f33c91d745e2c ]
+
+ThunderX pass1.x requires to emulate the EA headers for on-chip devices
+hence it has to use custom pci_thunder_ecam_ops for accessing PCI config
+space (pci-thunder-ecam.c). Add new entries to MCFG quirk array where it
+can be applied while probing ACPI based PCI host controller.
+
+ThunderX pass1.x is using the same way for accessing off-chip devices
+(so-called PEM) as silicon pass-2.x so we need to add PEM quirk entries
+too.
+
+Quirk is considered for ThunderX silicon pass1.x only which is identified
+via MCFG revision 2.
+
+ThunderX pass 1.x requires the following accessors:
+
+  NUMA node 0 PCI segments  0- 3: pci_thunder_ecam_ops (MCFG quirk)
+  NUMA node 0 PCI segments  4- 9: thunder_pem_ecam_ops (MCFG quirk)
+  NUMA node 1 PCI segments 10-13: pci_thunder_ecam_ops (MCFG quirk)
+  NUMA node 1 PCI segments 14-19: thunder_pem_ecam_ops (MCFG quirk)
+
+[bhelgaas: change Makefile/ifdefs so quirk doesn't depend on
+CONFIG_PCI_HOST_THUNDER_ECAM]
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/pci_mcfg.c             |   15 +++++++++++++++
+ drivers/pci/host/Kconfig            |    3 ++-
+ drivers/pci/host/Makefile           |    2 +-
+ drivers/pci/host/pci-thunder-ecam.c |    9 ++++++++-
+ include/linux/pci-ecam.h            |    3 ++-
+ 5 files changed, 28 insertions(+), 4 deletions(-)
+
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -93,6 +93,21 @@ static struct mcfg_fixup mcfg_quirks[] =
+       /* SoC pass2.x */
+       THUNDER_PEM_QUIRK(1, 0),
+       THUNDER_PEM_QUIRK(1, 1),
++
++#define THUNDER_ECAM_QUIRK(rev, seg)                                  \
++      { "CAVIUM", "THUNDERX", rev, seg, MCFG_BUS_ANY,                 \
++      &pci_thunder_ecam_ops }
++      /* SoC pass1.x */
++      THUNDER_PEM_QUIRK(2, 0),        /* off-chip devices */
++      THUNDER_PEM_QUIRK(2, 1),        /* off-chip devices */
++      THUNDER_ECAM_QUIRK(2,  0),
++      THUNDER_ECAM_QUIRK(2,  1),
++      THUNDER_ECAM_QUIRK(2,  2),
++      THUNDER_ECAM_QUIRK(2,  3),
++      THUNDER_ECAM_QUIRK(2, 10),
++      THUNDER_ECAM_QUIRK(2, 11),
++      THUNDER_ECAM_QUIRK(2, 12),
++      THUNDER_ECAM_QUIRK(2, 13),
+ };
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+--- a/drivers/pci/host/Kconfig
++++ b/drivers/pci/host/Kconfig
+@@ -248,7 +248,8 @@ config PCI_HOST_THUNDER_PEM
+ config PCI_HOST_THUNDER_ECAM
+       bool "Cavium Thunder ECAM controller to on-chip devices on pass-1.x silicon"
+-      depends on OF && ARM64
++      depends on ARM64
++      depends on OF || (ACPI && PCI_QUIRKS)
+       select PCI_HOST_COMMON
+       help
+         Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs.
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -27,7 +27,7 @@ obj-$(CONFIG_PCIE_ALTERA) += pcie-altera
+ obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
+ obj-$(CONFIG_ARM64) += pcie-hisi.o
+ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
+-obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
++obj-$(CONFIG_ARM64) += pci-thunder-ecam.o
+ obj-$(CONFIG_ARM64) += pci-thunder-pem.o
+ obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
+ obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
+--- a/drivers/pci/host/pci-thunder-ecam.c
++++ b/drivers/pci/host/pci-thunder-ecam.c
+@@ -14,6 +14,8 @@
+ #include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
++#if defined(CONFIG_PCI_HOST_THUNDER_ECAM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
++
+ static void set_val(u32 v, int where, int size, u32 *val)
+ {
+       int shift = (where & 3) * 8;
+@@ -346,7 +348,7 @@ static int thunder_ecam_config_write(str
+       return pci_generic_config_write(bus, devfn, where, size, val);
+ }
+-static struct pci_ecam_ops pci_thunder_ecam_ops = {
++struct pci_ecam_ops pci_thunder_ecam_ops = {
+       .bus_shift      = 20,
+       .pci_ops        = {
+               .map_bus        = pci_ecam_map_bus,
+@@ -355,6 +357,8 @@ static struct pci_ecam_ops pci_thunder_e
+       }
+ };
++#ifdef CONFIG_PCI_HOST_THUNDER_ECAM
++
+ static const struct of_device_id thunder_ecam_of_match[] = {
+       { .compatible = "cavium,pci-host-thunder-ecam" },
+       { },
+@@ -373,3 +377,6 @@ static struct platform_driver thunder_ec
+       .probe = thunder_ecam_probe,
+ };
+ builtin_platform_driver(thunder_ecam_driver);
++
++#endif
++#endif
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -62,7 +62,8 @@ extern struct pci_ecam_ops pci_generic_e
+ #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
+ extern struct pci_ecam_ops pci_32b_ops;               /* 32-bit accesses only */
+ extern struct pci_ecam_ops hisi_pcie_ops;     /* HiSilicon */
+-extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 2.x */
++extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 1.x & 2.x */
++extern struct pci_ecam_ops pci_thunder_ecam_ops; /* Cavium ThunderX 1.x */
+ #endif
+ #ifdef CONFIG_PCI_HOST_GENERIC
diff --git a/queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass2.x-host-controller.patch b/queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass2.x-host-controller.patch
new file mode 100644 (file)
index 0000000..3c5417e
--- /dev/null
@@ -0,0 +1,176 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:11 +0000
+Subject: PCI: Add MCFG quirks for Cavium ThunderX pass2.x host controller
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-27-alexander.levin@verizon.com>
+
+From: Tomasz Nowicki <tn@semihalf.com>
+
+[ Upstream commit 44f22bd91e88f9a1203a6e564a237e593f5f2f74 ]
+
+ThunderX PCIe controller to off-chip devices (so-called PEM) is not fully
+compliant with ECAM standard. It uses non-standard configuration space
+accessors (see thunder_pem_ecam_ops) and custom configuration space
+granulation (see bus_shift = 24). In order to access configuration space
+and probe PEM as ACPI-based PCI host controller we need to add MCFG quirk
+infrastructure. This involves:
+1. A new thunder_pem_acpi_init() init function to locate PEM-specific
+   register ranges using ACPI.
+2. Export PEM thunder_pem_ecam_ops structure so it is visible to MCFG quirk
+   code.
+3. New quirk entries for each PEM segment. Each contains platform IDs,
+   mentioned thunder_pem_ecam_ops and CFG resources.
+
+Quirk is considered for ThunderX silicon pass2.x only which is identified
+via MCFG revision 1.
+
+ThunderX pass 2.x requires the following accessors:
+
+  NUMA Node 0 PCI segments  0- 3: pci_generic_ecam_ops (ECAM-compliant)
+  NUMA Node 0 PCI segments  4- 9: thunder_pem_ecam_ops (MCFG quirk)
+  NUMA Node 1 PCI segments 10-13: pci_generic_ecam_ops (ECAM-compliant)
+  NUMA Node 1 PCI segments 14-19: thunder_pem_ecam_ops (MCFG quirk)
+
+[bhelgaas: adapt to use acpi_get_rc_resources(), update Makefile/ifdefs so
+quirk doesn't depend on CONFIG_PCI_HOST_THUNDER_PEM]
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/pci_mcfg.c            |   19 +++++++++++++++
+ drivers/pci/host/Kconfig           |    3 +-
+ drivers/pci/host/Makefile          |    2 -
+ drivers/pci/host/pci-thunder-pem.c |   44 +++++++++++++++++++++++++++++++++++++
+ include/linux/pci-ecam.h           |    1 
+ 5 files changed, 67 insertions(+), 2 deletions(-)
+
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -74,6 +74,25 @@ static struct mcfg_fixup mcfg_quirks[] =
+       HISI_QUAD_DOM("HIP07   ",  4, &hisi_pcie_ops),
+       HISI_QUAD_DOM("HIP07   ",  8, &hisi_pcie_ops),
+       HISI_QUAD_DOM("HIP07   ", 12, &hisi_pcie_ops),
++
++#define THUNDER_PEM_RES(addr, node) \
++      DEFINE_RES_MEM((addr) + ((u64) (node) << 44), 0x39 * SZ_16M)
++#define THUNDER_PEM_QUIRK(rev, node) \
++      { "CAVIUM", "THUNDERX", rev, 4 + (10 * (node)), MCFG_BUS_ANY,       \
++        &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88001f000000UL, node) },  \
++      { "CAVIUM", "THUNDERX", rev, 5 + (10 * (node)), MCFG_BUS_ANY,       \
++        &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x884057000000UL, node) },  \
++      { "CAVIUM", "THUNDERX", rev, 6 + (10 * (node)), MCFG_BUS_ANY,       \
++        &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88808f000000UL, node) },  \
++      { "CAVIUM", "THUNDERX", rev, 7 + (10 * (node)), MCFG_BUS_ANY,       \
++        &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89001f000000UL, node) },  \
++      { "CAVIUM", "THUNDERX", rev, 8 + (10 * (node)), MCFG_BUS_ANY,       \
++        &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x894057000000UL, node) },  \
++      { "CAVIUM", "THUNDERX", rev, 9 + (10 * (node)), MCFG_BUS_ANY,       \
++        &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89808f000000UL, node) }
++      /* SoC pass2.x */
++      THUNDER_PEM_QUIRK(1, 0),
++      THUNDER_PEM_QUIRK(1, 1),
+ };
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+--- a/drivers/pci/host/Kconfig
++++ b/drivers/pci/host/Kconfig
+@@ -240,7 +240,8 @@ config PCIE_QCOM
+ config PCI_HOST_THUNDER_PEM
+       bool "Cavium Thunder PCIe controller to off-chip devices"
+-      depends on OF && ARM64
++      depends on ARM64
++      depends on OF || (ACPI && PCI_QUIRKS)
+       select PCI_HOST_COMMON
+       help
+         Say Y here if you want PCIe support for CN88XX Cavium Thunder SoCs.
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -28,7 +28,7 @@ obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-al
+ obj-$(CONFIG_ARM64) += pcie-hisi.o
+ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
+ obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
+-obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
++obj-$(CONFIG_ARM64) += pci-thunder-pem.o
+ obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
+ obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
+ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
+--- a/drivers/pci/host/pci-thunder-pem.c
++++ b/drivers/pci/host/pci-thunder-pem.c
+@@ -18,8 +18,12 @@
+ #include <linux/init.h>
+ #include <linux/of_address.h>
+ #include <linux/of_pci.h>
++#include <linux/pci-acpi.h>
+ #include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
++#include "../pci.h"
++
++#if defined(CONFIG_PCI_HOST_THUNDER_PEM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
+ #define PEM_CFG_WR 0x28
+ #define PEM_CFG_RD 0x30
+@@ -313,6 +317,43 @@ static int thunder_pem_init(struct devic
+       return 0;
+ }
++#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
++
++static int thunder_pem_acpi_init(struct pci_config_window *cfg)
++{
++      struct device *dev = cfg->parent;
++      struct acpi_device *adev = to_acpi_device(dev);
++      struct acpi_pci_root *root = acpi_driver_data(adev);
++      struct resource *res_pem;
++      int ret;
++
++      res_pem = devm_kzalloc(&adev->dev, sizeof(*res_pem), GFP_KERNEL);
++      if (!res_pem)
++              return -ENOMEM;
++
++      ret = acpi_get_rc_resources(dev, "THRX0002", root->segment, res_pem);
++      if (ret) {
++              dev_err(dev, "can't get rc base address\n");
++              return ret;
++      }
++
++      return thunder_pem_init(dev, cfg, res_pem);
++}
++
++struct pci_ecam_ops thunder_pem_ecam_ops = {
++      .bus_shift      = 24,
++      .init           = thunder_pem_acpi_init,
++      .pci_ops        = {
++              .map_bus        = pci_ecam_map_bus,
++              .read           = thunder_pem_config_read,
++              .write          = thunder_pem_config_write,
++      }
++};
++
++#endif
++
++#ifdef CONFIG_PCI_HOST_THUNDER_PEM
++
+ static int thunder_pem_platform_init(struct pci_config_window *cfg)
+ {
+       struct device *dev = cfg->parent;
+@@ -364,3 +405,6 @@ static struct platform_driver thunder_pe
+       .probe = thunder_pem_probe,
+ };
+ builtin_platform_driver(thunder_pem_driver);
++
++#endif
++#endif
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -62,6 +62,7 @@ extern struct pci_ecam_ops pci_generic_e
+ #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
+ extern struct pci_ecam_ops pci_32b_ops;               /* 32-bit accesses only */
+ extern struct pci_ecam_ops hisi_pcie_ops;     /* HiSilicon */
++extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 2.x */
+ #endif
+ #ifdef CONFIG_PCI_HOST_GENERIC
diff --git a/queue-4.9/pci-add-mcfg-quirks-for-hisilicon-hip05-06-07-host-controllers.patch b/queue-4.9/pci-add-mcfg-quirks-for-hisilicon-hip05-06-07-host-controllers.patch
new file mode 100644 (file)
index 0000000..d8d33e8
--- /dev/null
@@ -0,0 +1,192 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:11 +0000
+Subject: PCI: Add MCFG quirks for HiSilicon Hip05/06/07 host controllers
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-25-alexander.levin@verizon.com>
+
+From: Dongdong Liu <liudongdong3@huawei.com>
+
+[ Upstream commit 5f00f1a0178cf52928366a5e1f376a65f1f3f389 ]
+
+The PCIe controller in Hip05/Hip06/Hip07 SoCs is not completely
+ECAM-compliant.  It is non-ECAM only for the RC bus config space; for any
+other bus underneath the root bus it does support ECAM access.
+
+Add specific quirks for PCI config space accessors.  This involves:
+1. New initialization call hisi_pcie_init() to obtain RC base
+addresses from PNP0C02 at the root of the ACPI namespace (under \_SB).
+2. New entry in common quirk array.
+
+[bhelgaas: move to pcie-hisi.c and change Makefile/ifdefs so quirk doesn't
+depend on CONFIG_PCI_HISI]
+Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
+Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/pci_mcfg.c      |   12 +++++
+ drivers/pci/host/Makefile    |    2 
+ drivers/pci/host/pcie-hisi.c |  101 +++++++++++++++++++++++++++++++++++++++++++
+ include/linux/pci-ecam.h     |    1 
+ 4 files changed, 115 insertions(+), 1 deletion(-)
+
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -62,6 +62,18 @@ static struct mcfg_fixup mcfg_quirks[] =
+       QCOM_ECAM32(5),
+       QCOM_ECAM32(6),
+       QCOM_ECAM32(7),
++
++#define HISI_QUAD_DOM(table_id, seg, ops) \
++      { "HISI  ", table_id, 0, (seg) + 0, MCFG_BUS_ANY, ops }, \
++      { "HISI  ", table_id, 0, (seg) + 1, MCFG_BUS_ANY, ops }, \
++      { "HISI  ", table_id, 0, (seg) + 2, MCFG_BUS_ANY, ops }, \
++      { "HISI  ", table_id, 0, (seg) + 3, MCFG_BUS_ANY, ops }
++      HISI_QUAD_DOM("HIP05   ",  0, &hisi_pcie_ops),
++      HISI_QUAD_DOM("HIP06   ",  0, &hisi_pcie_ops),
++      HISI_QUAD_DOM("HIP07   ",  0, &hisi_pcie_ops),
++      HISI_QUAD_DOM("HIP07   ",  4, &hisi_pcie_ops),
++      HISI_QUAD_DOM("HIP07   ",  8, &hisi_pcie_ops),
++      HISI_QUAD_DOM("HIP07   ", 12, &hisi_pcie_ops),
+ };
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -25,7 +25,7 @@ obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pci
+ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
+ obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
+ obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
+-obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
++obj-$(CONFIG_ARM64) += pcie-hisi.o
+ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
+ obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
+ obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
+--- a/drivers/pci/host/pcie-hisi.c
++++ b/drivers/pci/host/pcie-hisi.c
+@@ -18,7 +18,106 @@
+ #include <linux/of_pci.h>
+ #include <linux/platform_device.h>
+ #include <linux/of_device.h>
++#include <linux/pci.h>
++#include <linux/pci-acpi.h>
++#include <linux/pci-ecam.h>
+ #include <linux/regmap.h>
++#include "../pci.h"
++
++#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
++
++static int hisi_pcie_acpi_rd_conf(struct pci_bus *bus, u32 devfn, int where,
++                                int size, u32 *val)
++{
++      struct pci_config_window *cfg = bus->sysdata;
++      int dev = PCI_SLOT(devfn);
++
++      if (bus->number == cfg->busr.start) {
++              /* access only one slot on each root port */
++              if (dev > 0)
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++              else
++                      return pci_generic_config_read32(bus, devfn, where,
++                                                       size, val);
++      }
++
++      return pci_generic_config_read(bus, devfn, where, size, val);
++}
++
++static int hisi_pcie_acpi_wr_conf(struct pci_bus *bus, u32 devfn,
++                                int where, int size, u32 val)
++{
++      struct pci_config_window *cfg = bus->sysdata;
++      int dev = PCI_SLOT(devfn);
++
++      if (bus->number == cfg->busr.start) {
++              /* access only one slot on each root port */
++              if (dev > 0)
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++              else
++                      return pci_generic_config_write32(bus, devfn, where,
++                                                        size, val);
++      }
++
++      return pci_generic_config_write(bus, devfn, where, size, val);
++}
++
++static void __iomem *hisi_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
++                                     int where)
++{
++      struct pci_config_window *cfg = bus->sysdata;
++      void __iomem *reg_base = cfg->priv;
++
++      if (bus->number == cfg->busr.start)
++              return reg_base + where;
++      else
++              return pci_ecam_map_bus(bus, devfn, where);
++}
++
++static int hisi_pcie_init(struct pci_config_window *cfg)
++{
++      struct device *dev = cfg->parent;
++      struct acpi_device *adev = to_acpi_device(dev);
++      struct acpi_pci_root *root = acpi_driver_data(adev);
++      struct resource *res;
++      void __iomem *reg_base;
++      int ret;
++
++      /*
++       * Retrieve RC base and size from a HISI0081 device with _UID
++       * matching our segment.
++       */
++      res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
++      if (!res)
++              return -ENOMEM;
++
++      ret = acpi_get_rc_resources(dev, "HISI0081", root->segment, res);
++      if (ret) {
++              dev_err(dev, "can't get rc base address\n");
++              return -ENOMEM;
++      }
++
++      reg_base = devm_ioremap(dev, res->start, resource_size(res));
++      if (!reg_base)
++              return -ENOMEM;
++
++      cfg->priv = reg_base;
++      return 0;
++}
++
++struct pci_ecam_ops hisi_pcie_ops = {
++      .bus_shift    = 20,
++      .init         =  hisi_pcie_init,
++      .pci_ops      = {
++              .map_bus    = hisi_pcie_map_bus,
++              .read       = hisi_pcie_acpi_rd_conf,
++              .write      = hisi_pcie_acpi_wr_conf,
++      }
++};
++
++#endif
++
++#ifdef CONFIG_PCI_HISI
+ #include "pcie-designware.h"
+@@ -227,3 +326,5 @@ static struct platform_driver hisi_pcie_
+       },
+ };
+ builtin_platform_driver(hisi_pcie_driver);
++
++#endif
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -61,6 +61,7 @@ extern struct pci_ecam_ops pci_generic_e
+ #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
+ extern struct pci_ecam_ops pci_32b_ops;               /* 32-bit accesses only */
++extern struct pci_ecam_ops hisi_pcie_ops;     /* HiSilicon */
+ #endif
+ #ifdef CONFIG_PCI_HOST_GENERIC
diff --git a/queue-4.9/pci-add-mcfg-quirks-for-qualcomm-qdf2432-host-controller.patch b/queue-4.9/pci-add-mcfg-quirks-for-qualcomm-qdf2432-host-controller.patch
new file mode 100644 (file)
index 0000000..63f0dd0
--- /dev/null
@@ -0,0 +1,78 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:10 +0000
+Subject: PCI: Add MCFG quirks for Qualcomm QDF2432 host controller
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-24-alexander.levin@verizon.com>
+
+From: Christopher Covington <cov@codeaurora.org>
+
+[ Upstream commit 2ca5b8ddc6f70d77a51851ba5e5cd0d39c27dd88 ]
+
+The Qualcomm Technologies QDF2432 SoC does not support accesses smaller
+than 32 bits to the PCI configuration space.  Register the appropriate
+quirk.
+
+[bhelgaas: add QCOM_ECAM32 macro, ifdef for ACPI and PCI_QUIRKS]
+Signed-off-by: Christopher Covington <cov@codeaurora.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/pci_mcfg.c  |   11 +++++++++++
+ drivers/pci/ecam.c       |   12 ++++++++++++
+ include/linux/pci-ecam.h |    4 ++++
+ 3 files changed, 27 insertions(+)
+
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -51,6 +51,17 @@ struct mcfg_fixup {
+ static struct mcfg_fixup mcfg_quirks[] = {
+ /*    { OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
++
++#define QCOM_ECAM32(seg) \
++      { "QCOM  ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
++      QCOM_ECAM32(0),
++      QCOM_ECAM32(1),
++      QCOM_ECAM32(2),
++      QCOM_ECAM32(3),
++      QCOM_ECAM32(4),
++      QCOM_ECAM32(5),
++      QCOM_ECAM32(6),
++      QCOM_ECAM32(7),
+ };
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+--- a/drivers/pci/ecam.c
++++ b/drivers/pci/ecam.c
+@@ -162,3 +162,15 @@ struct pci_ecam_ops pci_generic_ecam_ops
+               .write          = pci_generic_config_write,
+       }
+ };
++
++#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
++/* ECAM ops for 32-bit access only (non-compliant) */
++struct pci_ecam_ops pci_32b_ops = {
++      .bus_shift      = 20,
++      .pci_ops        = {
++              .map_bus        = pci_ecam_map_bus,
++              .read           = pci_generic_config_read32,
++              .write          = pci_generic_config_write32,
++      }
++};
++#endif
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -59,6 +59,10 @@ void __iomem *pci_ecam_map_bus(struct pc
+ /* default ECAM ops */
+ extern struct pci_ecam_ops pci_generic_ecam_ops;
++#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
++extern struct pci_ecam_ops pci_32b_ops;               /* 32-bit accesses only */
++#endif
++
+ #ifdef CONFIG_PCI_HOST_GENERIC
+ /* for DT-based PCI controllers that support ECAM */
+ int pci_host_common_probe(struct platform_device *pdev,
diff --git a/queue-4.9/pci-add-mcfg-quirks-for-x-gene-host-controller.patch b/queue-4.9/pci-add-mcfg-quirks-for-x-gene-host-controller.patch
new file mode 100644 (file)
index 0000000..c7b72d7
--- /dev/null
@@ -0,0 +1,295 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:12 +0000
+Subject: PCI: Add MCFG quirks for X-Gene host controller
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-29-alexander.levin@verizon.com>
+
+From: Duc Dang <dhdang@apm.com>
+
+[ Upstream commit c5d4603961009c39de94725213d8b5420f110f9e ]
+
+PCIe controllers in X-Gene SoCs are not ECAM compliant: software needs to
+configure additional controller's register to address device at
+bus:dev:function.
+
+Add a quirk to discover controller MMIO register space and configure
+controller registers to select and address the target secondary device.
+
+The quirk will only be applied for X-Gene PCIe MCFG table with
+OEM revison 1, 2, 3 or 4 (PCIe controller v1 and v2 on X-Gene SoCs).
+
+Tested-by: Jon Masters <jcm@redhat.com>
+Signed-off-by: Duc Dang <dhdang@apm.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/pci_mcfg.c      |   25 ++++++++
+ drivers/pci/host/Kconfig     |    4 -
+ drivers/pci/host/Makefile    |    2 
+ drivers/pci/host/pci-xgene.c |  126 ++++++++++++++++++++++++++++++++++++++++---
+ include/linux/pci-ecam.h     |    2 
+ 5 files changed, 149 insertions(+), 10 deletions(-)
+
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -108,6 +108,31 @@ static struct mcfg_fixup mcfg_quirks[] =
+       THUNDER_ECAM_QUIRK(2, 11),
+       THUNDER_ECAM_QUIRK(2, 12),
+       THUNDER_ECAM_QUIRK(2, 13),
++
++#define XGENE_V1_ECAM_MCFG(rev, seg) \
++      {"APM   ", "XGENE   ", rev, seg, MCFG_BUS_ANY, \
++              &xgene_v1_pcie_ecam_ops }
++#define XGENE_V2_ECAM_MCFG(rev, seg) \
++      {"APM   ", "XGENE   ", rev, seg, MCFG_BUS_ANY, \
++              &xgene_v2_pcie_ecam_ops }
++      /* X-Gene SoC with v1 PCIe controller */
++      XGENE_V1_ECAM_MCFG(1, 0),
++      XGENE_V1_ECAM_MCFG(1, 1),
++      XGENE_V1_ECAM_MCFG(1, 2),
++      XGENE_V1_ECAM_MCFG(1, 3),
++      XGENE_V1_ECAM_MCFG(1, 4),
++      XGENE_V1_ECAM_MCFG(2, 0),
++      XGENE_V1_ECAM_MCFG(2, 1),
++      XGENE_V1_ECAM_MCFG(2, 2),
++      XGENE_V1_ECAM_MCFG(2, 3),
++      XGENE_V1_ECAM_MCFG(2, 4),
++      /* X-Gene SoC with v2.1 PCIe controller */
++      XGENE_V2_ECAM_MCFG(3, 0),
++      XGENE_V2_ECAM_MCFG(3, 1),
++      /* X-Gene SoC with v2.2 PCIe controller */
++      XGENE_V2_ECAM_MCFG(4, 0),
++      XGENE_V2_ECAM_MCFG(4, 1),
++      XGENE_V2_ECAM_MCFG(4, 2),
+ };
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+--- a/drivers/pci/host/Kconfig
++++ b/drivers/pci/host/Kconfig
+@@ -133,8 +133,8 @@ config PCIE_XILINX
+ config PCI_XGENE
+       bool "X-Gene PCIe controller"
+-      depends on ARCH_XGENE
+-      depends on OF
++      depends on ARM64
++      depends on OF || (ACPI && PCI_QUIRKS)
+       select PCIEPORTBUS
+       help
+         Say Y here if you want internal PCI support on APM X-Gene SoC.
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -15,7 +15,7 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spe
+ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
+ obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
+ obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
+-obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
++obj-$(CONFIG_ARM64) += pci-xgene.o
+ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
+ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
+ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+--- a/drivers/pci/host/pci-xgene.c
++++ b/drivers/pci/host/pci-xgene.c
+@@ -27,6 +27,8 @@
+ #include <linux/of_irq.h>
+ #include <linux/of_pci.h>
+ #include <linux/pci.h>
++#include <linux/pci-acpi.h>
++#include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+@@ -64,7 +66,9 @@
+ /* PCIe IP version */
+ #define XGENE_PCIE_IP_VER_UNKN                0
+ #define XGENE_PCIE_IP_VER_1           1
++#define XGENE_PCIE_IP_VER_2           2
++#if defined(CONFIG_PCI_XGENE) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
+ struct xgene_pcie_port {
+       struct device_node      *node;
+       struct device           *dev;
+@@ -91,13 +95,24 @@ static inline u32 pcie_bar_low_val(u32 a
+       return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags;
+ }
++static inline struct xgene_pcie_port *pcie_bus_to_port(struct pci_bus *bus)
++{
++      struct pci_config_window *cfg;
++
++      if (acpi_disabled)
++              return (struct xgene_pcie_port *)(bus->sysdata);
++
++      cfg = bus->sysdata;
++      return (struct xgene_pcie_port *)(cfg->priv);
++}
++
+ /*
+  * When the address bit [17:16] is 2'b01, the Configuration access will be
+  * treated as Type 1 and it will be forwarded to external PCIe device.
+  */
+ static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus)
+ {
+-      struct xgene_pcie_port *port = bus->sysdata;
++      struct xgene_pcie_port *port = pcie_bus_to_port(bus);
+       if (bus->number >= (bus->primary + 1))
+               return port->cfg_base + AXI_EP_CFG_ACCESS;
+@@ -111,7 +126,7 @@ static void __iomem *xgene_pcie_get_cfg_
+  */
+ static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
+ {
+-      struct xgene_pcie_port *port = bus->sysdata;
++      struct xgene_pcie_port *port = pcie_bus_to_port(bus);
+       unsigned int b, d, f;
+       u32 rtdid_val = 0;
+@@ -158,7 +173,7 @@ static void __iomem *xgene_pcie_map_bus(
+ static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 *val)
+ {
+-      struct xgene_pcie_port *port = bus->sysdata;
++      struct xgene_pcie_port *port = pcie_bus_to_port(bus);
+       if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
+           PCIBIOS_SUCCESSFUL)
+@@ -182,13 +197,103 @@ static int xgene_pcie_config_read32(stru
+       return PCIBIOS_SUCCESSFUL;
+ }
++#endif
+-static struct pci_ops xgene_pcie_ops = {
+-      .map_bus = xgene_pcie_map_bus,
+-      .read = xgene_pcie_config_read32,
+-      .write = pci_generic_config_write32,
++#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
++static int xgene_get_csr_resource(struct acpi_device *adev,
++                                struct resource *res)
++{
++      struct device *dev = &adev->dev;
++      struct resource_entry *entry;
++      struct list_head list;
++      unsigned long flags;
++      int ret;
++
++      INIT_LIST_HEAD(&list);
++      flags = IORESOURCE_MEM;
++      ret = acpi_dev_get_resources(adev, &list,
++                                   acpi_dev_filter_resource_type_cb,
++                                   (void *) flags);
++      if (ret < 0) {
++              dev_err(dev, "failed to parse _CRS method, error code %d\n",
++                      ret);
++              return ret;
++      }
++
++      if (ret == 0) {
++              dev_err(dev, "no IO and memory resources present in _CRS\n");
++              return -EINVAL;
++      }
++
++      entry = list_first_entry(&list, struct resource_entry, node);
++      *res = *entry->res;
++      acpi_dev_free_resource_list(&list);
++      return 0;
++}
++
++static int xgene_pcie_ecam_init(struct pci_config_window *cfg, u32 ipversion)
++{
++      struct device *dev = cfg->parent;
++      struct acpi_device *adev = to_acpi_device(dev);
++      struct xgene_pcie_port *port;
++      struct resource csr;
++      int ret;
++
++      port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
++      if (!port)
++              return -ENOMEM;
++
++      ret = xgene_get_csr_resource(adev, &csr);
++      if (ret) {
++              dev_err(dev, "can't get CSR resource\n");
++              kfree(port);
++              return ret;
++      }
++      port->csr_base = devm_ioremap_resource(dev, &csr);
++      if (IS_ERR(port->csr_base)) {
++              kfree(port);
++              return -ENOMEM;
++      }
++
++      port->cfg_base = cfg->win;
++      port->version = ipversion;
++
++      cfg->priv = port;
++      return 0;
++}
++
++static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
++{
++      return xgene_pcie_ecam_init(cfg, XGENE_PCIE_IP_VER_1);
++}
++
++struct pci_ecam_ops xgene_v1_pcie_ecam_ops = {
++      .bus_shift      = 16,
++      .init           = xgene_v1_pcie_ecam_init,
++      .pci_ops        = {
++              .map_bus        = xgene_pcie_map_bus,
++              .read           = xgene_pcie_config_read32,
++              .write          = pci_generic_config_write,
++      }
++};
++
++static int xgene_v2_pcie_ecam_init(struct pci_config_window *cfg)
++{
++      return xgene_pcie_ecam_init(cfg, XGENE_PCIE_IP_VER_2);
++}
++
++struct pci_ecam_ops xgene_v2_pcie_ecam_ops = {
++      .bus_shift      = 16,
++      .init           = xgene_v2_pcie_ecam_init,
++      .pci_ops        = {
++              .map_bus        = xgene_pcie_map_bus,
++              .read           = xgene_pcie_config_read32,
++              .write          = pci_generic_config_write,
++      }
+ };
++#endif
++#if defined(CONFIG_PCI_XGENE)
+ static u64 xgene_pcie_set_ib_mask(struct xgene_pcie_port *port, u32 addr,
+                                 u32 flags, u64 size)
+ {
+@@ -521,6 +626,12 @@ static int xgene_pcie_setup(struct xgene
+       return 0;
+ }
++static struct pci_ops xgene_pcie_ops = {
++      .map_bus = xgene_pcie_map_bus,
++      .read = xgene_pcie_config_read32,
++      .write = pci_generic_config_write32,
++};
++
+ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -591,3 +702,4 @@ static struct platform_driver xgene_pcie
+       .probe = xgene_pcie_probe_bridge,
+ };
+ builtin_platform_driver(xgene_pcie_driver);
++#endif
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -64,6 +64,8 @@ extern struct pci_ecam_ops pci_32b_ops;
+ extern struct pci_ecam_ops hisi_pcie_ops;     /* HiSilicon */
+ extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 1.x & 2.x */
+ extern struct pci_ecam_ops pci_thunder_ecam_ops; /* Cavium ThunderX 1.x */
++extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops; /* APM X-Gene PCIe v1 */
++extern struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x */
+ #endif
+ #ifdef CONFIG_PCI_HOST_GENERIC
diff --git a/queue-4.9/pci-disable-msi-for-hisilicon-hip06-hip07-root-ports.patch b/queue-4.9/pci-disable-msi-for-hisilicon-hip06-hip07-root-ports.patch
new file mode 100644 (file)
index 0000000..9d7e565
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:33 +0000
+Subject: PCI: Disable MSI for HiSilicon Hip06/Hip07 Root Ports
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-84-alexander.levin@verizon.com>
+
+From: Dongdong Liu <liudongdong3@huawei.com>
+
+[ Upstream commit 72f2ff0deb870145a5a2d24cd75b4f9936159a62 ]
+
+The PCIe Root Port in Hip06/Hip07 SoCs advertises an MSI capability, but it
+cannot generate MSIs.  It can transfer MSI/MSI-X from downstream devices,
+but does not support MSI/MSI-X itself.
+
+Add a quirk to prevent use of MSI/MSI-X by the Root Port.
+
+[bhelgaas: changelog, sort vendor ID #define, drop device ID #define]
+Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+Reviewed-by: Zhou Wang <wangzhou1@hisilicon.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/quirks.c    |    1 +
+ include/linux/pci_ids.h |    2 ++
+ 2 files changed, 3 insertions(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1634,6 +1634,7 @@ static void quirk_pcie_mch(struct pci_de
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_E7520_MCH,  quirk_pcie_mch);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_E7320_MCH,  quirk_pcie_mch);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_E7525_MCH,  quirk_pcie_mch);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_HUAWEI, 0x1610, quirk_pcie_mch);
+ /*
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2513,6 +2513,8 @@
+ #define PCI_DEVICE_ID_KORENIX_JETCARDF2       0x1700
+ #define PCI_DEVICE_ID_KORENIX_JETCARDF3       0x17ff
++#define PCI_VENDOR_ID_HUAWEI          0x19e5
++
+ #define PCI_VENDOR_ID_NETRONOME               0x19ee
+ #define PCI_DEVICE_ID_NETRONOME_NFP3200       0x3200
+ #define PCI_DEVICE_ID_NETRONOME_NFP3240       0x3240
diff --git a/queue-4.9/pci-expand-vpd-access-disabled-quirk-message.patch b/queue-4.9/pci-expand-vpd-access-disabled-quirk-message.patch
new file mode 100644 (file)
index 0000000..d7a84eb
--- /dev/null
@@ -0,0 +1,37 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:14 +0000
+Subject: PCI: Expand "VPD access disabled" quirk message
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-33-alexander.levin@verizon.com>
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit 044bc425bb72ffdecfb2a66d50cb1d024ecb96d0 ]
+
+It's not very enlightening to see
+
+  pci 0000:07:00.0: [Firmware Bug]: VPD access disabled
+
+in the dmesg log because there's no clue about what the firmware bug is.
+Expand the message to explain why we're disabling VPD.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/quirks.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2156,7 +2156,7 @@ static void quirk_blacklist_vpd(struct p
+ {
+       if (dev->vpd) {
+               dev->vpd->len = 0;
+-              dev_warn(&dev->dev, FW_BUG "VPD access disabled\n");
++              dev_warn(&dev->dev, FW_BUG "disabling VPD access (can't determine size of non-standard VPD format)\n");
+       }
+ }
diff --git a/queue-4.9/pci-explain-arm64-acpi-mcfg-quirk-kconfig-and-build-strategy.patch b/queue-4.9/pci-explain-arm64-acpi-mcfg-quirk-kconfig-and-build-strategy.patch
new file mode 100644 (file)
index 0000000..a380b64
--- /dev/null
@@ -0,0 +1,60 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:13 +0000
+Subject: PCI: Explain ARM64 ACPI/MCFG quirk Kconfig and build strategy
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-30-alexander.levin@verizon.com>
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit ca5ab37b19dfd1d77787d0474b767ec1185670f4 ]
+
+Add Makefile comments to explain the Kconfig and build strategy for ARM64
+drivers that work around not-quite-ECAM issues.  No functional change
+intended.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/host/Makefile |   19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -15,7 +15,6 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spe
+ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
+ obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
+ obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
+-obj-$(CONFIG_ARM64) += pci-xgene.o
+ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
+ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
+ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+@@ -25,11 +24,23 @@ obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pci
+ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
+ obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
+ obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
+-obj-$(CONFIG_ARM64) += pcie-hisi.o
+ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
+-obj-$(CONFIG_ARM64) += pci-thunder-ecam.o
+-obj-$(CONFIG_ARM64) += pci-thunder-pem.o
+ obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
+ obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
+ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
+ obj-$(CONFIG_VMD) += vmd.o
++
++# The following drivers are for devices that use the generic ACPI
++# pci_root.c driver but don't support standard ECAM config access.
++# They contain MCFG quirks to replace the generic ECAM accessors with
++# device-specific ones that are shared with the DT driver.
++
++# The ACPI driver is generic and should not require driver-specific
++# config options to be enabled, so we always build these drivers on
++# ARM64 and use internal ifdefs to only build the pieces we need
++# depending on whether ACPI, the DT driver, or both are enabled.
++
++obj-$(CONFIG_ARM64) += pcie-hisi.o
++obj-$(CONFIG_ARM64) += pci-thunder-ecam.o
++obj-$(CONFIG_ARM64) += pci-thunder-pem.o
++obj-$(CONFIG_ARM64) += pci-xgene.o
diff --git a/queue-4.9/pci-sort-the-list-of-devices-with-d3-delay-quirk-by-id.patch b/queue-4.9/pci-sort-the-list-of-devices-with-d3-delay-quirk-by-id.patch
new file mode 100644 (file)
index 0000000..0a2f779
--- /dev/null
@@ -0,0 +1,72 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:34 +0000
+Subject: PCI: Sort the list of devices with D3 delay quirk by ID
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-86-alexander.levin@verizon.com>
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit cd3e2eb8905d14fe28a2fc75362b8ecec16f0fb6 ]
+
+Sort the list of Intel devices that have no PCI D3 delay by ID.  Add a
+comment for group of devices that had not been marked yet.
+
+There is no functional change.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/quirks.c |   26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -3136,30 +3136,32 @@ static void quirk_remove_d3_delay(struct
+ {
+       dev->d3_delay = 0;
+ }
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3_delay);
++/* C600 Series devices do not need 10ms d3_delay */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0412, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c0c, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3_delay);
++/* Lynxpoint-H PCH devices do not need 10ms d3_delay */
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c18, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c1c, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
+ /* Intel Cherrytrail devices do not need 10ms d3_delay */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2280, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b0, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b8, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22d8, quirk_remove_d3_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22dc, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
+ /*
+  * Some devices may pass our check in pci_intx_mask_supported() if
diff --git a/queue-4.9/pci-thunder-pem-factor-out-resource-lookup.patch b/queue-4.9/pci-thunder-pem-factor-out-resource-lookup.patch
new file mode 100644 (file)
index 0000000..e6513f1
--- /dev/null
@@ -0,0 +1,98 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:11 +0000
+Subject: PCI: thunder-pem: Factor out resource lookup
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-26-alexander.levin@verizon.com>
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit 0d414268fb8d0844030f87027e904f69d96706be ]
+
+Pull the register resource lookup out of thunder_pem_init() so we can
+easily add a corresponding lookup using ACPI.  No functional change
+intended.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/host/pci-thunder-pem.c |   50 +++++++++++++++++++------------------
+ 1 file changed, 27 insertions(+), 23 deletions(-)
+
+--- a/drivers/pci/host/pci-thunder-pem.c
++++ b/drivers/pci/host/pci-thunder-pem.c
+@@ -284,35 +284,16 @@ static int thunder_pem_config_write(stru
+       return pci_generic_config_write(bus, devfn, where, size, val);
+ }
+-static int thunder_pem_init(struct pci_config_window *cfg)
++static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg,
++                          struct resource *res_pem)
+ {
+-      struct device *dev = cfg->parent;
+-      resource_size_t bar4_start;
+-      struct resource *res_pem;
+       struct thunder_pem_pci *pem_pci;
+-      struct platform_device *pdev;
+-
+-      /* Only OF support for now */
+-      if (!dev->of_node)
+-              return -EINVAL;
++      resource_size_t bar4_start;
+       pem_pci = devm_kzalloc(dev, sizeof(*pem_pci), GFP_KERNEL);
+       if (!pem_pci)
+               return -ENOMEM;
+-      pdev = to_platform_device(dev);
+-
+-      /*
+-       * The second register range is the PEM bridge to the PCIe
+-       * bus.  It has a different config access method than those
+-       * devices behind the bridge.
+-       */
+-      res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-      if (!res_pem) {
+-              dev_err(dev, "missing \"reg[1]\"property\n");
+-              return -EINVAL;
+-      }
+-
+       pem_pci->pem_reg_base = devm_ioremap(dev, res_pem->start, 0x10000);
+       if (!pem_pci->pem_reg_base)
+               return -ENOMEM;
+@@ -332,9 +313,32 @@ static int thunder_pem_init(struct pci_c
+       return 0;
+ }
++static int thunder_pem_platform_init(struct pci_config_window *cfg)
++{
++      struct device *dev = cfg->parent;
++      struct platform_device *pdev = to_platform_device(dev);
++      struct resource *res_pem;
++
++      if (!dev->of_node)
++              return -EINVAL;
++
++      /*
++       * The second register range is the PEM bridge to the PCIe
++       * bus.  It has a different config access method than those
++       * devices behind the bridge.
++       */
++      res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      if (!res_pem) {
++              dev_err(dev, "missing \"reg[1]\"property\n");
++              return -EINVAL;
++      }
++
++      return thunder_pem_init(dev, cfg, res_pem);
++}
++
+ static struct pci_ecam_ops pci_thunder_pem_ops = {
+       .bus_shift      = 24,
+-      .init           = thunder_pem_init,
++      .init           = thunder_pem_platform_init,
+       .pci_ops        = {
+               .map_bus        = pci_ecam_map_bus,
+               .read           = thunder_pem_config_read,
diff --git a/queue-4.9/pci-xgene-fix-double-free-on-init-error.patch b/queue-4.9/pci-xgene-fix-double-free-on-init-error.patch
new file mode 100644 (file)
index 0000000..8fa42e1
--- /dev/null
@@ -0,0 +1,46 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:26 +0000
+Subject: PCI: xgene: Fix double free on init error
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-66-alexander.levin@verizon.com>
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+[ Upstream commit 1ded56df3247d358390ae6dc09ccee620262ac5f ]
+
+The "port" variable was allocated with devm_kzalloc() so if we free it with
+kfree() it will be freed twice.  Also I changed it to propogate the error
+from devm_ioremap_resource() instead of returning -ENOMEM.
+
+Fixes: c5d460396100 ("PCI: Add MCFG quirks for X-Gene host controller")
+Also-posted-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Tanmay Inamdar <tinamdar@apm.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/host/pci-xgene.c |    7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/host/pci-xgene.c
++++ b/drivers/pci/host/pci-xgene.c
+@@ -246,14 +246,11 @@ static int xgene_pcie_ecam_init(struct p
+       ret = xgene_get_csr_resource(adev, &csr);
+       if (ret) {
+               dev_err(dev, "can't get CSR resource\n");
+-              kfree(port);
+               return ret;
+       }
+       port->csr_base = devm_ioremap_resource(dev, &csr);
+-      if (IS_ERR(port->csr_base)) {
+-              kfree(port);
+-              return -ENOMEM;
+-      }
++      if (IS_ERR(port->csr_base))
++              return PTR_ERR(port->csr_base);
+       port->cfg_base = cfg->win;
+       port->version = ipversion;
diff --git a/queue-4.9/platform-x86-acer-wmi-only-supports-amw0_guid1-on-acer-family.patch b/queue-4.9/platform-x86-acer-wmi-only-supports-amw0_guid1-on-acer-family.patch
new file mode 100644 (file)
index 0000000..dca6940
--- /dev/null
@@ -0,0 +1,121 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:14 +0000
+Subject: platform/x86: acer-wmi: Only supports AMW0_GUID1 on acer family
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-35-alexander.levin@verizon.com>
+
+From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com>
+
+[ Upstream commit 5241b1938a4d33eee3d3b43f23067c8e5b96db45 ]
+
+The AMW0_GUID1 wmi is not only found on Acer family but also other
+machines like Lenovo, Fujitsu and Medion. In the past, acer-wmi handled
+those non-Acer machines by quirks list.
+
+But actually acer-wmi driver was loaded on any machine that had
+AMW0_GUID1. This behavior is strange because those machines should be
+supported by appropriate wmi drivers. e.g. fujitsu-laptop,
+ideapad-laptop.
+
+This patch adds the logic to check the machine that has AMW0_GUID1
+should be in Acer/Packard Bell/Gateway white list. But, it still keeps
+the quirk list of those supported non-acer machines for backward
+compatibility.
+
+Tested-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
+Signed-off-by: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/acer-wmi.c |   56 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+--- a/drivers/platform/x86/acer-wmi.c
++++ b/drivers/platform/x86/acer-wmi.c
+@@ -355,6 +355,32 @@ static const struct dmi_system_id acer_b
+       {}
+ };
++static const struct dmi_system_id amw0_whitelist[] __initconst = {
++      {
++              .ident = "Acer",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++              },
++      },
++      {
++              .ident = "Gateway",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Gateway"),
++              },
++      },
++      {
++              .ident = "Packard Bell",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"),
++              },
++      },
++      {}
++};
++
++/*
++ * This quirk table is only for Acer/Gateway/Packard Bell family
++ * that those machines are supported by acer-wmi driver.
++ */
+ static const struct dmi_system_id acer_quirks[] __initconst = {
+       {
+               .callback = dmi_matched,
+@@ -464,6 +490,17 @@ static const struct dmi_system_id acer_q
+               },
+               .driver_data = &quirk_acer_travelmate_2490,
+       },
++      {}
++};
++
++/*
++ * This quirk list is for those non-acer machines that have AMW0_GUID1
++ * but supported by acer-wmi in past days. Keeping this quirk list here
++ * is only for backward compatible. Please do not add new machine to
++ * here anymore. Those non-acer machines should be supported by
++ * appropriate wmi drivers.
++ */
++static const struct dmi_system_id non_acer_quirks[] __initconst = {
+       {
+               .callback = dmi_matched,
+               .ident = "Fujitsu Siemens Amilo Li 1718",
+@@ -598,6 +635,7 @@ static void __init find_quirks(void)
+ {
+       if (!force_series) {
+               dmi_check_system(acer_quirks);
++              dmi_check_system(non_acer_quirks);
+       } else if (force_series == 2490) {
+               quirks = &quirk_acer_travelmate_2490;
+       }
+@@ -2108,6 +2146,24 @@ static int __init acer_wmi_init(void)
+       find_quirks();
+       /*
++       * The AMW0_GUID1 wmi is not only found on Acer family but also other
++       * machines like Lenovo, Fujitsu and Medion. In the past days,
++       * acer-wmi driver handled those non-Acer machines by quirks list.
++       * But actually acer-wmi driver was loaded on any machines that have
++       * AMW0_GUID1. This behavior is strange because those machines should
++       * be supported by appropriate wmi drivers. e.g. fujitsu-laptop,
++       * ideapad-laptop. So, here checks the machine that has AMW0_GUID1
++       * should be in Acer/Gateway/Packard Bell white list, or it's already
++       * in the past quirk list.
++       */
++      if (wmi_has_guid(AMW0_GUID1) &&
++          !dmi_check_system(amw0_whitelist) &&
++          quirks == &quirk_unknown) {
++              pr_err("Unsupported machine has AMW0_GUID1, unable to load\n");
++              return -ENODEV;
++      }
++
++      /*
+        * Detect which ACPI-WMI interface we're using.
+        */
+       if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
diff --git a/queue-4.9/platform-x86-asus-wmi-detect-quirk_no_rfkill-from-the-dsdt.patch b/queue-4.9/platform-x86-asus-wmi-detect-quirk_no_rfkill-from-the-dsdt.patch
new file mode 100644 (file)
index 0000000..691decf
--- /dev/null
@@ -0,0 +1,105 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:36 +0000
+Subject: platform/x86: asus-wmi: Detect quirk_no_rfkill from the DSDT
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-92-alexander.levin@verizon.com>
+
+From: João Paulo Rechi Vita <jprvita@gmail.com>
+
+[ Upstream commit 71050ae7bf83e4d71a859257d11adc5de517073e ]
+
+Some Asus laptops that have an airplane-mode indicator LED, also have
+the WMI WLAN user bit set, and the following bits in their DSDT:
+
+    Scope (_SB)
+    {
+      (...)
+      Device (ATKD)
+      {
+        (...)
+        Method (WMNB, 3, Serialized)
+        {
+          (...)
+          If (LEqual (IIA0, 0x00010002))
+          {
+            OWGD (IIA1)
+            Return (One)
+          }
+        }
+      }
+    }
+
+So when asus-wmi uses ASUS_WMI_DEVID_WLAN_LED (0x00010002) to store the
+wlan state, it drives the airplane-mode indicator LED (through the call
+to OWGD) in an inverted fashion: the LED is ON when airplane mode is OFF
+(since wlan is ON), and vice-versa.
+
+This commit skips registering RFKill switches at all for these laptops,
+to allow the asus-wireless driver to drive the airplane mode LED
+correctly through the ASHS ACPI device. Relying on the presence of ASHS
+and ASUS_WMI_DSTS_USER_BIT avoids adding DMI-based quirks for at least
+21 different laptops.
+
+Signed-off-by: João Paulo Rechi Vita <jprvita@endlessm.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/asus-wmi.c |   23 +++++++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -159,6 +159,8 @@ MODULE_LICENSE("GPL");
+ #define USB_INTEL_XUSB2PR             0xD0
+ #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
++static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
++
+ struct bios_args {
+       u32 arg0;
+       u32 arg1;
+@@ -2051,6 +2053,16 @@ static int asus_wmi_fan_init(struct asus
+       return 0;
+ }
++static bool ashs_present(void)
++{
++      int i = 0;
++      while (ashs_ids[i]) {
++              if (acpi_dev_found(ashs_ids[i++]))
++                      return true;
++      }
++      return false;
++}
++
+ /*
+  * WMI Driver
+  */
+@@ -2095,6 +2107,13 @@ static int asus_wmi_add(struct platform_
+       if (err)
+               goto fail_leds;
++      asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
++      if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
++              asus->driver->wlan_ctrl_by_user = 1;
++
++      if (asus->driver->wlan_ctrl_by_user && ashs_present())
++              asus->driver->quirks->no_rfkill = 1;
++
+       if (!asus->driver->quirks->no_rfkill) {
+               err = asus_wmi_rfkill_init(asus);
+               if (err)
+@@ -2134,10 +2153,6 @@ static int asus_wmi_add(struct platform_
+       if (err)
+               goto fail_debugfs;
+-      asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
+-      if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
+-              asus->driver->wlan_ctrl_by_user = 1;
+-
+       return 0;
+ fail_debugfs:
diff --git a/queue-4.9/platform-x86-asus-wmi-set-specified-xusb2pr-value-for-x550lb.patch b/queue-4.9/platform-x86-asus-wmi-set-specified-xusb2pr-value-for-x550lb.patch
new file mode 100644 (file)
index 0000000..4e5f5e3
--- /dev/null
@@ -0,0 +1,177 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:36 +0000
+Subject: platform/x86: asus-wmi: Set specified XUSB2PR value for X550LB
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-91-alexander.levin@verizon.com>
+
+From: Kai-Chuan Hsieh <kai.chiuan@gmail.com>
+
+[ Upstream commit 8023eff10e7b0327898f17f0b553d2e45c71cef3 ]
+
+The bluetooth adapter Atheros AR3012 can't be enumerated
+and make the bluetooth function broken.
+
+T:  Bus=02 Lev=01 Prnt=01 Port=05 Cnt=02 Dev#=  5 Spd=12  MxCh= 0
+D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
+P:  Vendor=13d3 ProdID=3362 Rev=00.02
+S:  Manufacturer=Atheros Communications
+S:  Product=Bluetooth USB Host Controller
+S:  SerialNumber=Alaska Day 2006
+C:  #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+I:  If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+
+The error is:
+
+ usb 2-6: device not accepting address 7, error -62
+ usb usb2-port6: unable to enumerate USB device
+
+It is caused by adapter's connected port is mapped to xHC
+controller, but the xHCI is not supported by the usb device.
+
+The output of 'sudo lspci -nnxxx -s 00:14.0':
+
+ 00:14.0 USB controller [0c03]: Intel Corporation 8 Series USB xHCI HC [8086:9c31] (rev 04)
+ 00: 86 80 31 9c 06 04 90 02 04 30 03 0c 00 00 00 00
+ 10: 04 00 a0 f7 00 00 00 00 00 00 00 00 00 00 00 00
+ 20: 00 00 00 00 00 00 00 00 00 00 00 00 43 10 1f 20
+ 30: 00 00 00 00 70 00 00 00 00 00 00 00 0b 01 00 00
+ 40: fd 01 36 80 89 c6 0f 80 00 00 00 00 00 00 00 00
+ 50: 5f 2e ce 0f 00 00 00 00 00 00 00 00 00 00 00 00
+ 60: 30 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 70: 01 80 c2 c1 08 00 00 00 00 00 00 00 00 00 00 00
+ 80: 05 00 87 00 0c a0 e0 fe 00 00 00 00 a1 41 00 00
+ 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ a0: 00 01 04 00 00 00 00 00 00 00 00 00 00 00 00 00
+ b0: 0f 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00
+ c0: 03 c0 30 00 00 00 00 00 03 0c 00 00 00 00 00 00
+ d0: f9 01 00 00 f9 01 00 00 0f 00 00 00 0f 00 00 00
+ e0: 00 08 00 00 00 00 00 00 00 00 00 00 d8 d8 00 00
+ f0: 00 00 00 00 00 00 00 00 b1 0f 04 08 00 00 00 00
+
+By referencing Intel Platform Controller Hub(PCH) datasheet,
+the xHC USB 2.0 Port Routing(XUSB2PR) at offset 0xD0-0xD3h
+decides the setting of mapping the port to EHCI controller or
+xHC controller. And the port mapped to xHC will enable xHCI
+during bus resume.
+
+The setting of disabling bluetooth adapter's connected port is
+0x000001D9. The value can be obtained by few times 1 bit flip
+operation. The suited configuration should have the 'lsusb -t'
+result with bluetooth using ehci:
+
+/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
+/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/9p, 480M
+    |__ Port 5: Dev 2, If 0, Class=Video, Driver=uvcvideo, 480M
+    |__ Port 5: Dev 2, If 1, Class=Video, Driver=uvcvideo, 480M
+/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
+    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M
+        |__ Port 6: Dev 3, If 0, Class=Wireless, Driver=btusb, 12M
+        |__ Port 6: Dev 3, If 1, Class=Wireless, Driver=btusb, 12M
+
+Signed-off-by: Kai-Chuan Hsieh <kai.chiuan@gmail.com>
+Acked-by: Corentin Chary <corentin.chary@gmail.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+[andy: resolve merge conflict in asus-wmi.h]
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/asus-nb-wmi.c |   13 +++++++++++++
+ drivers/platform/x86/asus-wmi.c    |   29 +++++++++++++++++++++++++++++
+ drivers/platform/x86/asus-wmi.h    |    1 +
+ 3 files changed, 43 insertions(+)
+
+--- a/drivers/platform/x86/asus-nb-wmi.c
++++ b/drivers/platform/x86/asus-nb-wmi.c
+@@ -116,6 +116,10 @@ static struct quirk_entry quirk_asus_ux3
+       .wmi_backlight_native = true,
+ };
++static struct quirk_entry quirk_asus_x550lb = {
++      .xusb2pr = 0x01D9,
++};
++
+ static int dmi_matched(const struct dmi_system_id *dmi)
+ {
+       quirks = dmi->driver_data;
+@@ -407,6 +411,15 @@ static const struct dmi_system_id asus_q
+               },
+               .driver_data = &quirk_asus_ux303ub,
+       },
++      {
++              .callback = dmi_matched,
++              .ident = "ASUSTeK COMPUTER INC. X550LB",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "X550LB"),
++              },
++              .driver_data = &quirk_asus_x550lb,
++      },
+       {},
+ };
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -156,6 +156,9 @@ MODULE_LICENSE("GPL");
+ #define ASUS_FAN_CTRL_MANUAL          1
+ #define ASUS_FAN_CTRL_AUTO            2
++#define USB_INTEL_XUSB2PR             0xD0
++#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
++
+ struct bios_args {
+       u32 arg0;
+       u32 arg1;
+@@ -1080,6 +1083,29 @@ exit:
+       return result;
+ }
++static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)
++{
++      struct pci_dev *xhci_pdev;
++      u32 orig_ports_available;
++      u32 ports_available = asus->driver->quirks->xusb2pr;
++
++      xhci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
++                      PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI,
++                      NULL);
++
++      if (!xhci_pdev)
++              return;
++
++      pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
++                              &orig_ports_available);
++
++      pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
++                              cpu_to_le32(ports_available));
++
++      pr_info("set USB_INTEL_XUSB2PR old: 0x%04x, new: 0x%04x\n",
++                      orig_ports_available, ports_available);
++}
++
+ /*
+  * Hwmon device
+  */
+@@ -2087,6 +2113,9 @@ static int asus_wmi_add(struct platform_
+       if (asus->driver->quirks->wmi_backlight_native)
+               acpi_video_set_dmi_backlight_type(acpi_backlight_native);
++      if (asus->driver->quirks->xusb2pr)
++              asus_wmi_set_xusb2pr(asus);
++
+       if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
+               err = asus_wmi_backlight_init(asus);
+               if (err && err != -ENODEV)
+--- a/drivers/platform/x86/asus-wmi.h
++++ b/drivers/platform/x86/asus-wmi.h
+@@ -53,6 +53,7 @@ struct quirk_entry {
+        * and let the ACPI interrupt to send out the key event.
+        */
+       int no_display_toggle;
++      u32 xusb2pr;
+       bool (*i8042_filter)(unsigned char data, unsigned char str,
+                            struct serio *serio);
diff --git a/queue-4.9/rx51-broken-build.patch b/queue-4.9/rx51-broken-build.patch
new file mode 100644 (file)
index 0000000..2a3f443
--- /dev/null
@@ -0,0 +1,45 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:26 +0000
+Subject: [media] rx51: broken build
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-67-alexander.levin@verizon.com>
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit 922ee72da7c739157ed02ea04a5c100d19f67226 ]
+
+As reported by kernel build test:
+
+   In file included from arch/arm/mach-omap2/pdata-quirks.c:15:0:
+>> arch/arm/mach-omap2/pdata-quirks.c:536:49: error: 'rx51_lirc_data' undeclared here (not in a function)
+     OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_lirc_data),
+                                                    ^
+   include/linux/of_platform.h:52:21: note: in definition of macro 'OF_DEV_AUXDATA'
+       .platform_data = _pdata }
+                        ^~~~~~
+
+Since "a92def1 [media] ir-rx51: port to rc-core" the build fails on
+some arm configurations.
+
+Reported-by: kbuild test robot <fengguang.wu@intel.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/mach-omap2/pdata-quirks.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/mach-omap2/pdata-quirks.c
++++ b/arch/arm/mach-omap2/pdata-quirks.c
+@@ -534,7 +534,7 @@ static struct of_dev_auxdata omap_auxdat
+                      &omap3_iommu_pdata),
+       OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
+       OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
+-      OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_lirc_data),
++      OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_ir_data),
+       /* Only on am3517 */
+       OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
+       OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
diff --git a/queue-4.9/sata-ahci-da850-implement-a-workaround-for-the-softreset-quirk.patch b/queue-4.9/sata-ahci-da850-implement-a-workaround-for-the-softreset-quirk.patch
new file mode 100644 (file)
index 0000000..5ad4acb
--- /dev/null
@@ -0,0 +1,74 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:27 +0000
+Subject: sata: ahci-da850: implement a workaround for the softreset quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-68-alexander.levin@verizon.com>
+
+From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+
+[ Upstream commit f4d435f3265661d04e5290a0a0450e3a38898128 ]
+
+There's an issue with the da850 SATA controller: if port multiplier
+support is compiled in, but we're connecting the drive directly to
+the SATA port on the board, the drive can't be detected.
+
+To make SATA work on the da850-lcdk board: first try to softreset
+with pmp - if the operation fails with -EBUSY, retry without pmp.
+
+Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sekhar Nori <nsekhar@ti.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/ahci_da850.c |   33 ++++++++++++++++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+--- a/drivers/ata/ahci_da850.c
++++ b/drivers/ata/ahci_da850.c
+@@ -54,11 +54,42 @@ static void da850_sata_init(struct devic
+       writel(val, ahci_base + SATA_P0PHYCR_REG);
+ }
++static int ahci_da850_softreset(struct ata_link *link,
++                              unsigned int *class, unsigned long deadline)
++{
++      int pmp, ret;
++
++      pmp = sata_srst_pmp(link);
++
++      /*
++       * There's an issue with the SATA controller on da850 SoCs: if we
++       * enable Port Multiplier support, but the drive is connected directly
++       * to the board, it can't be detected. As a workaround: if PMP is
++       * enabled, we first call ahci_do_softreset() and pass it the result of
++       * sata_srst_pmp(). If this call fails, we retry with pmp = 0.
++       */
++      ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
++      if (pmp && ret == -EBUSY)
++              return ahci_do_softreset(link, class, 0,
++                                       deadline, ahci_check_ready);
++
++      return ret;
++}
++
++static struct ata_port_operations ahci_da850_port_ops = {
++      .inherits = &ahci_platform_ops,
++      .softreset = ahci_da850_softreset,
++      /*
++       * No need to override .pmp_softreset - it's only used for actual
++       * PMP-enabled ports.
++       */
++};
++
+ static const struct ata_port_info ahci_da850_port_info = {
+       .flags          = AHCI_FLAG_COMMON,
+       .pio_mask       = ATA_PIO4,
+       .udma_mask      = ATA_UDMA6,
+-      .port_ops       = &ahci_platform_ops,
++      .port_ops       = &ahci_da850_port_ops,
+ };
+ static struct scsi_host_template ahci_platform_sht = {
diff --git a/queue-4.9/scsi-ufs-add-quirk-to-increase-host-pa_saveconfigtime.patch b/queue-4.9/scsi-ufs-add-quirk-to-increase-host-pa_saveconfigtime.patch
new file mode 100644 (file)
index 0000000..a853d9f
--- /dev/null
@@ -0,0 +1,211 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:13 +0000
+Subject: scsi: ufs: add quirk to increase host PA_SaveConfigTime
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-31-alexander.levin@verizon.com>
+
+From: Subhash Jadavani <subhashj@codeaurora.org>
+
+[ Upstream commit 56d4a1866d748732fd8d690b2c2156bbc9c9eb02 ]
+
+The maximum value PA_SaveConfigTime is 250 (10us) but this is not enough
+for some vendors. Gear switch from PWM to HS may fail even with this
+max.  PA_SaveConfigTime. Gear switch can be issued by host controller as
+an error recovery and any software delay will not help on this case so
+we need to increase PA_SaveConfigTime to >32us as per vendor
+recommendation.  This change adds a quirk to increase the
+PA_SaveConfigTime parameter.
+
+Reviewed-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/ufs/ufs-qcom.c   |   30 ++++++++++++++++++++++++++++++
+ drivers/scsi/ufs/ufs-qcom.h   |    1 +
+ drivers/scsi/ufs/ufs_quirks.h |   30 +++++++++---------------------
+ drivers/scsi/ufs/ufshcd.c     |   26 ++++++++++++++++++++++++++
+ drivers/scsi/ufs/ufshcd.h     |    9 +++++++++
+ 5 files changed, 75 insertions(+), 21 deletions(-)
+
+--- a/drivers/scsi/ufs/ufs-qcom.c
++++ b/drivers/scsi/ufs/ufs-qcom.c
+@@ -23,6 +23,7 @@
+ #include "unipro.h"
+ #include "ufs-qcom.h"
+ #include "ufshci.h"
++#include "ufs_quirks.h"
+ #define UFS_QCOM_DEFAULT_DBG_PRINT_EN \
+       (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+@@ -1031,6 +1032,34 @@ out:
+       return ret;
+ }
++static int ufs_qcom_quirk_host_pa_saveconfigtime(struct ufs_hba *hba)
++{
++      int err;
++      u32 pa_vs_config_reg1;
++
++      err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1),
++                           &pa_vs_config_reg1);
++      if (err)
++              goto out;
++
++      /* Allow extension of MSB bits of PA_SaveConfigTime attribute */
++      err = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1),
++                          (pa_vs_config_reg1 | (1 << 12)));
++
++out:
++      return err;
++}
++
++static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
++{
++      int err = 0;
++
++      if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME)
++              err = ufs_qcom_quirk_host_pa_saveconfigtime(hba);
++
++      return err;
++}
++
+ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
+ {
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+@@ -1616,6 +1645,7 @@ static struct ufs_hba_variant_ops ufs_hb
+       .hce_enable_notify      = ufs_qcom_hce_enable_notify,
+       .link_startup_notify    = ufs_qcom_link_startup_notify,
+       .pwr_change_notify      = ufs_qcom_pwr_change_notify,
++      .apply_dev_quirks       = ufs_qcom_apply_dev_quirks,
+       .suspend                = ufs_qcom_suspend,
+       .resume                 = ufs_qcom_resume,
+       .dbg_register_dump      = ufs_qcom_dump_dbg_regs,
+--- a/drivers/scsi/ufs/ufs-qcom.h
++++ b/drivers/scsi/ufs/ufs-qcom.h
+@@ -142,6 +142,7 @@ enum ufs_qcom_phy_init_type {
+        UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+ /* QUniPro Vendor specific attributes */
++#define PA_VS_CONFIG_REG1     0x9000
+ #define DME_VS_CORE_CLK_CTRL  0xD002
+ /* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
+ #define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT              BIT(8)
+--- a/drivers/scsi/ufs/ufs_quirks.h
++++ b/drivers/scsi/ufs/ufs_quirks.h
+@@ -134,29 +134,17 @@ struct ufs_dev_fix {
+  */
+ #define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE    (1 << 7)
++/*
++ * The max. value PA_SaveConfigTime is 250 (10us) but this is not enough for
++ * some vendors.
++ * Gear switch from PWM to HS may fail even with this max. PA_SaveConfigTime.
++ * Gear switch can be issued by host controller as an error recovery and any
++ * software delay will not help on this case so we need to increase
++ * PA_SaveConfigTime to >32us as per vendor recommendation.
++ */
++#define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME       (1 << 8)
+ struct ufs_hba;
+ void ufs_advertise_fixup_device(struct ufs_hba *hba);
+-static struct ufs_dev_fix ufs_fixups[] = {
+-      /* UFS cards deviations table */
+-      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+-              UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
+-      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
+-      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+-              UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
+-      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+-              UFS_DEVICE_NO_FASTAUTO),
+-      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+-              UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
+-      UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
+-              UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
+-      UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
+-              UFS_DEVICE_QUIRK_PA_TACTIVATE),
+-      UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
+-              UFS_DEVICE_QUIRK_PA_TACTIVATE),
+-      UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
+-
+-      END_FIX
+-};
+ #endif /* UFS_QUIRKS_H_ */
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -188,6 +188,30 @@ ufs_get_pm_lvl_to_link_pwr_state(enum uf
+       return ufs_pm_lvl_states[lvl].link_state;
+ }
++static struct ufs_dev_fix ufs_fixups[] = {
++      /* UFS cards deviations table */
++      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
++              UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
++      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
++      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
++              UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
++      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
++              UFS_DEVICE_NO_FASTAUTO),
++      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
++              UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
++      UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
++              UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
++      UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
++              UFS_DEVICE_QUIRK_PA_TACTIVATE),
++      UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
++              UFS_DEVICE_QUIRK_PA_TACTIVATE),
++      UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
++      UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
++              UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
++
++      END_FIX
++};
++
+ static void ufshcd_tmc_handler(struct ufs_hba *hba);
+ static void ufshcd_async_scan(void *data, async_cookie_t cookie);
+ static int ufshcd_reset_and_restore(struct ufs_hba *hba);
+@@ -5062,6 +5086,8 @@ static void ufshcd_tune_unipro_params(st
+       if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
+               ufshcd_quirk_tune_host_pa_tactivate(hba);
++
++      ufshcd_vops_apply_dev_quirks(hba);
+ }
+ /**
+--- a/drivers/scsi/ufs/ufshcd.h
++++ b/drivers/scsi/ufs/ufshcd.h
+@@ -261,6 +261,7 @@ struct ufs_pwr_mode_info {
+  * @pwr_change_notify: called before and after a power mode change
+  *                    is carried out to allow vendor spesific capabilities
+  *                    to be set.
++ * @apply_dev_quirks: called to apply device specific quirks
+  * @suspend: called during host controller PM callback
+  * @resume: called during host controller PM callback
+  * @dbg_register_dump: used to dump controller debug information
+@@ -283,6 +284,7 @@ struct ufs_hba_variant_ops {
+                                       enum ufs_notify_change_status status,
+                                       struct ufs_pa_layer_attr *,
+                                       struct ufs_pa_layer_attr *);
++      int     (*apply_dev_quirks)(struct ufs_hba *);
+       int     (*suspend)(struct ufs_hba *, enum ufs_pm_op);
+       int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
+       void    (*dbg_register_dump)(struct ufs_hba *hba);
+@@ -805,6 +807,13 @@ static inline int ufshcd_vops_pwr_change
+       return -ENOTSUPP;
+ }
++static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
++{
++      if (hba->vops && hba->vops->apply_dev_quirks)
++              return hba->vops->apply_dev_quirks(hba);
++      return 0;
++}
++
+ static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
+ {
+       if (hba->vops && hba->vops->suspend)
diff --git a/queue-4.9/scsi-ufs-ensure-that-host-pa_tactivate-is-higher-than-device.patch b/queue-4.9/scsi-ufs-ensure-that-host-pa_tactivate-is-higher-than-device.patch
new file mode 100644 (file)
index 0000000..ad09060
--- /dev/null
@@ -0,0 +1,161 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:07 +0000
+Subject: scsi: ufs: ensure that host pa_tactivate is higher than device
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-16-alexander.levin@verizon.com>
+
+From: Subhash Jadavani <subhashj@codeaurora.org>
+
+[ Upstream commit c6a6db439868c7ba5cc90d4c461d9697ec731fa1 ]
+
+Some UFS devices require host PA_TACTIVATE to be higher than
+device PA_TACTIVATE otherwise it may get stuck during hibern8 sequence.
+This change allows this by using quirk.
+
+Reviewed-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/ufs/ufs_quirks.h |    9 +++++
+ drivers/scsi/ufs/ufshcd.c     |   73 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/scsi/ufs/unipro.h     |    4 ++
+ 3 files changed, 86 insertions(+)
+
+--- a/drivers/scsi/ufs/ufs_quirks.h
++++ b/drivers/scsi/ufs/ufs_quirks.h
+@@ -128,6 +128,13 @@ struct ufs_dev_fix {
+  */
+ #define UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM     (1 << 6)
++/*
++ * Some UFS devices require host PA_TACTIVATE to be lower than device
++ * PA_TACTIVATE, enabling this quirk ensure this.
++ */
++#define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE    (1 << 7)
++
++
+ struct ufs_hba;
+ void ufs_advertise_fixup_device(struct ufs_hba *hba);
+@@ -140,6 +147,8 @@ static struct ufs_dev_fix ufs_fixups[] =
+               UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
+       UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+               UFS_DEVICE_NO_FASTAUTO),
++      UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
++              UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
+       UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
+               UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
+       UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -4979,6 +4979,76 @@ out:
+       return ret;
+ }
++/**
++ * ufshcd_quirk_tune_host_pa_tactivate - Ensures that host PA_TACTIVATE is
++ * less than device PA_TACTIVATE time.
++ * @hba: per-adapter instance
++ *
++ * Some UFS devices require host PA_TACTIVATE to be lower than device
++ * PA_TACTIVATE, we need to enable UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE quirk
++ * for such devices.
++ *
++ * Returns zero on success, non-zero error value on failure.
++ */
++static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba)
++{
++      int ret = 0;
++      u32 granularity, peer_granularity;
++      u32 pa_tactivate, peer_pa_tactivate;
++      u32 pa_tactivate_us, peer_pa_tactivate_us;
++      u8 gran_to_us_table[] = {1, 4, 8, 16, 32, 100};
++
++      ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY),
++                                &granularity);
++      if (ret)
++              goto out;
++
++      ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY),
++                                &peer_granularity);
++      if (ret)
++              goto out;
++
++      if ((granularity < PA_GRANULARITY_MIN_VAL) ||
++          (granularity > PA_GRANULARITY_MAX_VAL)) {
++              dev_err(hba->dev, "%s: invalid host PA_GRANULARITY %d",
++                      __func__, granularity);
++              return -EINVAL;
++      }
++
++      if ((peer_granularity < PA_GRANULARITY_MIN_VAL) ||
++          (peer_granularity > PA_GRANULARITY_MAX_VAL)) {
++              dev_err(hba->dev, "%s: invalid device PA_GRANULARITY %d",
++                      __func__, peer_granularity);
++              return -EINVAL;
++      }
++
++      ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &pa_tactivate);
++      if (ret)
++              goto out;
++
++      ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_TACTIVATE),
++                                &peer_pa_tactivate);
++      if (ret)
++              goto out;
++
++      pa_tactivate_us = pa_tactivate * gran_to_us_table[granularity - 1];
++      peer_pa_tactivate_us = peer_pa_tactivate *
++                           gran_to_us_table[peer_granularity - 1];
++
++      if (pa_tactivate_us > peer_pa_tactivate_us) {
++              u32 new_peer_pa_tactivate;
++
++              new_peer_pa_tactivate = pa_tactivate_us /
++                                    gran_to_us_table[peer_granularity - 1];
++              new_peer_pa_tactivate++;
++              ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TACTIVATE),
++                                        new_peer_pa_tactivate);
++      }
++
++out:
++      return ret;
++}
++
+ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
+ {
+       if (ufshcd_is_unipro_pa_params_tuning_req(hba)) {
+@@ -4989,6 +5059,9 @@ static void ufshcd_tune_unipro_params(st
+       if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE)
+               /* set 1ms timeout for PA_TACTIVATE */
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10);
++
++      if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
++              ufshcd_quirk_tune_host_pa_tactivate(hba);
+ }
+ /**
+--- a/drivers/scsi/ufs/unipro.h
++++ b/drivers/scsi/ufs/unipro.h
+@@ -123,6 +123,7 @@
+ #define PA_MAXRXHSGEAR                0x1587
+ #define PA_RXHSUNTERMCAP      0x15A5
+ #define PA_RXLSTERMCAP                0x15A6
++#define PA_GRANULARITY                0x15AA
+ #define PA_PACPREQTIMEOUT     0x1590
+ #define PA_PACPREQEOBTIMEOUT  0x1591
+ #define PA_HIBERN8TIME                0x15A7
+@@ -158,6 +159,9 @@
+ #define VS_DEBUGOMC           0xD09E
+ #define VS_POWERSTATE         0xD083
++#define PA_GRANULARITY_MIN_VAL        1
++#define PA_GRANULARITY_MAX_VAL        6
++
+ /* PHY Adapter Protocol Constants */
+ #define PA_MAXDATALANES       4
diff --git a/queue-4.9/scsi-ufs-introduce-a-new-ufshcd_statea-ufshcd_state_eh_scheduled.patch b/queue-4.9/scsi-ufs-introduce-a-new-ufshcd_statea-ufshcd_state_eh_scheduled.patch
new file mode 100644 (file)
index 0000000..2cf1f1b
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:20 +0000
+Subject: scsi: ufs: introduce a new ufshcd_statea UFSHCD_STATE_EH_SCHEDULED
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-49-alexander.levin@verizon.com>
+
+From: Zang Leigang <zangleigang@hisilicon.com>
+
+[ Upstream commit 141f81651037ea109188a6bafdc5c9a318bd5a46 ]
+
+Add a new ufshcd_state, indicats that an err handler may get to run
+immediately. Use UFSHCD_STATE_ERROR here looks not literaly correct.
+
+Signed-off-by: Zang Leigang <zangleigang@hisilicon.com>
+Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/ufs/ufshcd.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -123,6 +123,7 @@ enum {
+       UFSHCD_STATE_RESET,
+       UFSHCD_STATE_ERROR,
+       UFSHCD_STATE_OPERATIONAL,
++      UFSHCD_STATE_EH_SCHEDULED,
+ };
+ /* UFSHCD error handling flags */
+@@ -1439,6 +1440,7 @@ static int ufshcd_queuecommand(struct Sc
+       switch (hba->ufshcd_state) {
+       case UFSHCD_STATE_OPERATIONAL:
+               break;
++      case UFSHCD_STATE_EH_SCHEDULED:
+       case UFSHCD_STATE_RESET:
+               err = SCSI_MLQUEUE_HOST_BUSY;
+               goto out_unlock;
+@@ -4196,7 +4198,7 @@ static void ufshcd_check_errors(struct u
+                       /* block commands from scsi mid-layer */
+                       scsi_block_requests(hba->host);
+-                      hba->ufshcd_state = UFSHCD_STATE_ERROR;
++                      hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED;
+                       schedule_work(&hba->eh_work);
+               }
+       }
diff --git a/queue-4.9/scsi-ufs-introduce-ufshcd_quirk_prdt_byte_gran-quirk.patch b/queue-4.9/scsi-ufs-introduce-ufshcd_quirk_prdt_byte_gran-quirk.patch
new file mode 100644 (file)
index 0000000..fa9f05f
--- /dev/null
@@ -0,0 +1,101 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:05 +0000
+Subject: scsi: ufs: introduce UFSHCD_QUIRK_PRDT_BYTE_GRAN quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-10-alexander.levin@verizon.com>
+
+From: Kiwoong Kim <kwmad.kim@samsung.com>
+
+[ Upstream commit 75b1cc4ad63afa28c1a045b5157c008f405f06a9 ]
+
+Some UFS host controllers may think granularities of PRDT length and
+offset as bytes, not double words.
+
+Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
+Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/ufs/ufshcd.c |   28 +++++++++++++++++++++-------
+ drivers/scsi/ufs/ufshcd.h |    6 ++++++
+ 2 files changed, 27 insertions(+), 7 deletions(-)
+
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -1088,7 +1088,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba,
+  *
+  * Returns 0 in case of success, non-zero value in case of failure
+  */
+-static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
++static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+ {
+       struct ufshcd_sg_entry *prd_table;
+       struct scatterlist *sg;
+@@ -1102,8 +1102,13 @@ static int ufshcd_map_sg(struct ufshcd_l
+               return sg_segments;
+       if (sg_segments) {
+-              lrbp->utr_descriptor_ptr->prd_table_length =
+-                                      cpu_to_le16((u16) (sg_segments));
++              if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
++                      lrbp->utr_descriptor_ptr->prd_table_length =
++                              cpu_to_le16((u16)(sg_segments *
++                                      sizeof(struct ufshcd_sg_entry)));
++              else
++                      lrbp->utr_descriptor_ptr->prd_table_length =
++                              cpu_to_le16((u16) (sg_segments));
+               prd_table = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr;
+@@ -1465,7 +1470,7 @@ static int ufshcd_queuecommand(struct Sc
+       ufshcd_comp_scsi_upiu(hba, lrbp);
+-      err = ufshcd_map_sg(lrbp);
++      err = ufshcd_map_sg(hba, lrbp);
+       if (err) {
+               lrbp->cmd = NULL;
+               clear_bit_unlock(tag, &hba->lrb_in_use);
+@@ -2320,12 +2325,21 @@ static void ufshcd_host_memory_configure
+                               cpu_to_le32(upper_32_bits(cmd_desc_element_addr));
+               /* Response upiu and prdt offset should be in double words */
+-              utrdlp[i].response_upiu_offset =
++              if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) {
++                      utrdlp[i].response_upiu_offset =
++                              cpu_to_le16(response_offset);
++                      utrdlp[i].prd_table_offset =
++                              cpu_to_le16(prdt_offset);
++                      utrdlp[i].response_upiu_length =
++                              cpu_to_le16(ALIGNED_UPIU_SIZE);
++              } else {
++                      utrdlp[i].response_upiu_offset =
+                               cpu_to_le16((response_offset >> 2));
+-              utrdlp[i].prd_table_offset =
++                      utrdlp[i].prd_table_offset =
+                               cpu_to_le16((prdt_offset >> 2));
+-              utrdlp[i].response_upiu_length =
++                      utrdlp[i].response_upiu_length =
+                               cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
++              }
+               hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
+               hba->lrb[i].ucd_req_ptr =
+--- a/drivers/scsi/ufs/ufshcd.h
++++ b/drivers/scsi/ufs/ufshcd.h
+@@ -474,6 +474,12 @@ struct ufs_hba {
+        */
+       #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION             UFS_BIT(5)
++      /*
++       * This quirk needs to be enabled if the host contoller regards
++       * resolution of the values of PRDTO and PRDTL in UTRD as byte.
++       */
++      #define UFSHCD_QUIRK_PRDT_BYTE_GRAN                     UFS_BIT(7)
++
+       unsigned int quirks;    /* Deviations from standard UFSHCI spec. */
+       /* Device deviations from standard UFS device spec. */
diff --git a/queue-4.9/scsi-ufs-issue-link-starup-2-times-if-device-isn-t-active.patch b/queue-4.9/scsi-ufs-issue-link-starup-2-times-if-device-isn-t-active.patch
new file mode 100644 (file)
index 0000000..5f963f8
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:20 +0000
+Subject: scsi: ufs: issue link starup 2 times if device isn't active
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-50-alexander.levin@verizon.com>
+
+From: "subhashj@codeaurora.org" <subhashj@codeaurora.org>
+
+[ Upstream commit 7caf489b99a42a9017ef3d733912aea8794677e7 ]
+
+If we issue the link startup to the device while its UniPro state is
+LinkDown (and device state is sleep/power-down) then link startup
+will not move the device state to Active. Device will only move to
+active state if the link starup is issued when its UniPro state is
+LinkUp. So in this case, we would have to issue the link startup 2
+times to make sure that device moves to active state.
+
+Reviewed-by: Gilad Broner <gbroner@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/ufs/ufshcd.c |   23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -3130,7 +3130,16 @@ static int ufshcd_link_startup(struct uf
+ {
+       int ret;
+       int retries = DME_LINKSTARTUP_RETRIES;
++      bool link_startup_again = false;
++      /*
++       * If UFS device isn't active then we will have to issue link startup
++       * 2 times to make sure the device state move to active.
++       */
++      if (!ufshcd_is_ufs_dev_active(hba))
++              link_startup_again = true;
++
++link_startup:
+       do {
+               ufshcd_vops_link_startup_notify(hba, PRE_CHANGE);
+@@ -3156,6 +3165,12 @@ static int ufshcd_link_startup(struct uf
+               /* failed to get the link up... retire */
+               goto out;
++      if (link_startup_again) {
++              link_startup_again = false;
++              retries = DME_LINKSTARTUP_RETRIES;
++              goto link_startup;
++      }
++
+       if (hba->quirks & UFSHCD_QUIRK_BROKEN_LCC) {
+               ret = ufshcd_disable_device_tx_lcc(hba);
+               if (ret)
+@@ -6630,10 +6645,12 @@ int ufshcd_init(struct ufs_hba *hba, voi
+       pm_runtime_get_sync(dev);
+       /*
+-       * The device-initialize-sequence hasn't been invoked yet.
+-       * Set the device to power-off state
++       * We are assuming that device wasn't put in sleep/power-down
++       * state exclusively during the boot stage before kernel.
++       * This assumption helps avoid doing link startup twice during
++       * ufshcd_probe_hba().
+        */
+-      ufshcd_set_ufs_dev_poweroff(hba);
++      ufshcd_set_ufs_dev_active(hba);
+       async_schedule(ufshcd_async_scan, hba);
diff --git a/queue-4.9/scsi-ufs-refactor-device-descriptor-reading.patch b/queue-4.9/scsi-ufs-refactor-device-descriptor-reading.patch
new file mode 100644 (file)
index 0000000..de4db82
--- /dev/null
@@ -0,0 +1,203 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:21 +0000
+Subject: scsi: ufs: refactor device descriptor reading
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-52-alexander.levin@verizon.com>
+
+From: Tomas Winkler <tomas.winkler@intel.com>
+
+[ Upstream commit 93fdd5ac64bbe80dac6416f048405362d7ef0945 ]
+
+Pull device descriptor reading out of ufs quirk so it can be used also
+for other purposes.
+
+Revamp the fixup setup:
+
+1. Rename ufs_device_info to ufs_dev_desc as very similar name
+   ufs_dev_info is already in use.
+
+2. Make the handlers static as they are not used out of the ufshdc.c
+   file.
+
+[mkp: applied by hand]
+
+Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
+Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/ufs/ufs.h        |   12 ++++++++++++
+ drivers/scsi/ufs/ufs_quirks.h |   28 ++++++----------------------
+ drivers/scsi/ufs/ufshcd.c     |   40 +++++++++++++++++++---------------------
+ 3 files changed, 37 insertions(+), 43 deletions(-)
+
+--- a/drivers/scsi/ufs/ufs.h
++++ b/drivers/scsi/ufs/ufs.h
+@@ -522,4 +522,16 @@ struct ufs_dev_info {
+       bool is_lu_power_on_wp;
+ };
++#define MAX_MODEL_LEN 16
++/**
++ * ufs_dev_desc - ufs device details from the device descriptor
++ *
++ * @wmanufacturerid: card details
++ * @model: card model
++ */
++struct ufs_dev_desc {
++      u16 wmanufacturerid;
++      char model[MAX_MODEL_LEN + 1];
++};
++
+ #endif /* End of Header */
+--- a/drivers/scsi/ufs/ufs_quirks.h
++++ b/drivers/scsi/ufs/ufs_quirks.h
+@@ -21,41 +21,28 @@
+ #define UFS_ANY_VENDOR 0xFFFF
+ #define UFS_ANY_MODEL  "ANY_MODEL"
+-#define MAX_MODEL_LEN 16
+-
+ #define UFS_VENDOR_TOSHIBA     0x198
+ #define UFS_VENDOR_SAMSUNG     0x1CE
+ #define UFS_VENDOR_SKHYNIX     0x1AD
+ /**
+- * ufs_device_info - ufs device details
+- * @wmanufacturerid: card details
+- * @model: card model
+- */
+-struct ufs_device_info {
+-      u16 wmanufacturerid;
+-      char model[MAX_MODEL_LEN + 1];
+-};
+-
+-/**
+  * ufs_dev_fix - ufs device quirk info
+  * @card: ufs card details
+  * @quirk: device quirk
+  */
+ struct ufs_dev_fix {
+-      struct ufs_device_info card;
++      struct ufs_dev_desc card;
+       unsigned int quirk;
+ };
+ #define END_FIX { { 0 }, 0 }
+ /* add specific device quirk */
+-#define UFS_FIX(_vendor, _model, _quirk) \
+-              {                                         \
+-                      .card.wmanufacturerid = (_vendor),\
+-                      .card.model = (_model),           \
+-                      .quirk = (_quirk),                \
+-              }
++#define UFS_FIX(_vendor, _model, _quirk) { \
++      .card.wmanufacturerid = (_vendor),\
++      .card.model = (_model),            \
++      .quirk = (_quirk),                 \
++}
+ /*
+  * If UFS device is having issue in processing LCC (Line Control
+@@ -144,7 +131,4 @@ struct ufs_dev_fix {
+  */
+ #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME       (1 << 8)
+-struct ufs_hba;
+-void ufs_advertise_fixup_device(struct ufs_hba *hba);
+-
+ #endif /* UFS_QUIRKS_H_ */
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -4874,8 +4874,8 @@ out:
+       return ret;
+ }
+-static int ufs_get_device_info(struct ufs_hba *hba,
+-                              struct ufs_device_info *card_data)
++static int ufs_get_device_desc(struct ufs_hba *hba,
++                             struct ufs_dev_desc *dev_desc)
+ {
+       int err;
+       u8 model_index;
+@@ -4894,7 +4894,7 @@ static int ufs_get_device_info(struct uf
+        * getting vendor (manufacturerID) and Bank Index in big endian
+        * format
+        */
+-      card_data->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
++      dev_desc->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
+                                    desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1];
+       model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
+@@ -4908,36 +4908,26 @@ static int ufs_get_device_info(struct uf
+       }
+       str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0';
+-      strlcpy(card_data->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
++      strlcpy(dev_desc->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
+               min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET],
+                     MAX_MODEL_LEN));
+       /* Null terminate the model string */
+-      card_data->model[MAX_MODEL_LEN] = '\0';
++      dev_desc->model[MAX_MODEL_LEN] = '\0';
+ out:
+       return err;
+ }
+-void ufs_advertise_fixup_device(struct ufs_hba *hba)
++static void ufs_fixup_device_setup(struct ufs_hba *hba,
++                                 struct ufs_dev_desc *dev_desc)
+ {
+-      int err;
+       struct ufs_dev_fix *f;
+-      struct ufs_device_info card_data;
+-
+-      card_data.wmanufacturerid = 0;
+-
+-      err = ufs_get_device_info(hba, &card_data);
+-      if (err) {
+-              dev_err(hba->dev, "%s: Failed getting device info. err = %d\n",
+-                      __func__, err);
+-              return;
+-      }
+       for (f = ufs_fixups; f->quirk; f++) {
+-              if (((f->card.wmanufacturerid == card_data.wmanufacturerid) ||
+-                  (f->card.wmanufacturerid == UFS_ANY_VENDOR)) &&
+-                  (STR_PRFX_EQUAL(f->card.model, card_data.model) ||
++              if ((f->card.wmanufacturerid == dev_desc->wmanufacturerid ||
++                   f->card.wmanufacturerid == UFS_ANY_VENDOR) &&
++                  (STR_PRFX_EQUAL(f->card.model, dev_desc->model) ||
+                    !strcmp(f->card.model, UFS_ANY_MODEL)))
+                       hba->dev_quirks |= f->quirk;
+       }
+@@ -5115,6 +5105,7 @@ static void ufshcd_tune_unipro_params(st
+  */
+ static int ufshcd_probe_hba(struct ufs_hba *hba)
+ {
++      struct ufs_dev_desc card = {0};
+       int ret;
+       ret = ufshcd_link_startup(hba);
+@@ -5138,7 +5129,14 @@ static int ufshcd_probe_hba(struct ufs_h
+       if (ret)
+               goto out;
+-      ufs_advertise_fixup_device(hba);
++      ret = ufs_get_device_desc(hba, &card);
++      if (ret) {
++              dev_err(hba->dev, "%s: Failed getting device info. err = %d\n",
++                      __func__, ret);
++              goto out;
++      }
++
++      ufs_fixup_device_setup(hba, &card);
+       ufshcd_tune_unipro_params(hba);
+       ret = ufshcd_set_vccq_rail_unused(hba,
diff --git a/queue-4.9/serial-8250_omap-add-omap_dma_tx_kick-quirk-for-am437x.patch b/queue-4.9/serial-8250_omap-add-omap_dma_tx_kick-quirk-for-am437x.patch
new file mode 100644 (file)
index 0000000..5174d1a
--- /dev/null
@@ -0,0 +1,57 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:22 +0000
+Subject: serial: 8250_omap: Add OMAP_DMA_TX_KICK quirk for AM437x
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-54-alexander.levin@verizon.com>
+
+From: Vignesh R <vigneshr@ti.com>
+
+[ Upstream commit b6ffcf21082300519bc4f9c3d24f61207cc9eae4 ]
+
+UART uses as EDMA as dma engine on AM437x SoC and therefore, requires
+OMAP_DMA_TX_KICK quirk just like AM33xx. So, enable OMAP_DMA_TX_KICK
+quirk for AM437x platform as well. While at that, drop use of
+of_machine_is_compatible() and instead pass quirks via device data.
+
+Signed-off-by: Vignesh R <vigneshr@ti.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/8250/8250_omap.c |    9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_omap.c
++++ b/drivers/tty/serial/8250/8250_omap.c
+@@ -1075,15 +1075,15 @@ static int omap8250_no_handle_irq(struct
+ }
+ static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
+-static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
++static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE;
+ static const struct of_device_id omap8250_dt_ids[] = {
+       { .compatible = "ti,omap2-uart" },
+       { .compatible = "ti,omap3-uart" },
+       { .compatible = "ti,omap4-uart" },
+       { .compatible = "ti,am3352-uart", .data = &am3352_habit, },
+-      { .compatible = "ti,am4372-uart", .data = &am4372_habit, },
+-      { .compatible = "ti,dra742-uart", .data = &am4372_habit, },
++      { .compatible = "ti,am4372-uart", .data = &am3352_habit, },
++      { .compatible = "ti,dra742-uart", .data = &dra742_habit, },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
+@@ -1218,9 +1218,6 @@ static int omap8250_probe(struct platfor
+                       priv->omap8250_dma.rx_size = RX_TRIGGER;
+                       priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
+                       priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
+-
+-                      if (of_machine_is_compatible("ti,am33xx"))
+-                              priv->habit |= OMAP_DMA_TX_KICK;
+                       /*
+                        * pause is currently not supported atleast on omap-sdma
+                        * and edma on most earlier kernels.
index 7cf475959e6b02ac99e60b0b463d16cc82c791eb..e431ee0b170a7af466e82a3ba455880e1010dbe3 100644 (file)
@@ -61,3 +61,94 @@ clk-lpc32xx-add-a-quirk-for-pwm-and-ms-clock-dividers.patch
 hid-usbhid-add-quirks-for-mayflash-dragonrise-gamecube-and-ps3-adapters.patch
 hid-i2c-hid-add-a-simple-quirk-to-fix-device-defects.patch
 usb-dwc3-gadget-delay-unmap-of-bounced-requests.patch
+asoc-intel-bytct_rt5640-change-default-capture-settings.patch
+arm64-dts-hisi-fix-hip06-sas-am-max-trans-quirk.patch
+net-mlx4_core-use-device-id-defines.patch
+clocksource-drivers-arm_arch_timer-don-t-assume-clock-runs-in-suspend.patch
+scsi-ufs-introduce-ufshcd_quirk_prdt_byte_gran-quirk.patch
+hid-sensor-hub-add-quirk-for-microsoft-surface-3.patch
+hid-sensor-hub-add-quirk-for-microchip-mm7150.patch
+hid-multitouch-enable-the-surface-3-type-cover-to-report-multitouch-data.patch
+hid-multitouch-do-not-retrieve-all-reports-for-all-devices.patch
+mmc-sdhci-msm-enable-few-quirks.patch
+scsi-ufs-ensure-that-host-pa_tactivate-is-higher-than-device.patch
+svcauth_gss-close-connection-when-dropping-an-incoming-message.patch
+x86-intel_idle-add-cpu-model-0x4a-atom-z34xx-series.patch
+arm64-pci-manage-controller-specific-data-on-per-controller-basis.patch
+arm64-pci-add-local-struct-device-pointers.patch
+arm64-pci-search-acpi-namespace-to-ensure-ecam-space-is-reserved.patch
+pci-acpi-extend-pci_mcfg_lookup-to-return-ecam-config-accessors.patch
+pci-acpi-check-for-platform-specific-mcfg-quirks.patch
+pci-add-mcfg-quirks-for-qualcomm-qdf2432-host-controller.patch
+pci-add-mcfg-quirks-for-hisilicon-hip05-06-07-host-controllers.patch
+pci-thunder-pem-factor-out-resource-lookup.patch
+pci-add-mcfg-quirks-for-cavium-thunderx-pass2.x-host-controller.patch
+pci-add-mcfg-quirks-for-cavium-thunderx-pass1.x-host-controller.patch
+pci-add-mcfg-quirks-for-x-gene-host-controller.patch
+pci-explain-arm64-acpi-mcfg-quirk-kconfig-and-build-strategy.patch
+scsi-ufs-add-quirk-to-increase-host-pa_saveconfigtime.patch
+alsa-usb-audio-add-implicit-fb-quirk-for-axe-fx-ii.patch
+pci-expand-vpd-access-disabled-quirk-message.patch
+alsa-usb-audio-add-native-dsd-support-for-teac-501-503-dac.patch
+platform-x86-acer-wmi-only-supports-amw0_guid1-on-acer-family.patch
+hid-asus-add-i2c-touchpad-support.patch
+hid-asus-fix-keyboard-support.patch
+hid-microsoft-add-surface-4-type-cover-pro-4-not-jp-versions.patch
+hid-multitouch-enable-the-surface-4-type-cover-pro-jp-to-report-multitouch-data.patch
+nvme-simplify-stripe-quirk.patch
+acpi-sysfs-provide-quirk-mechanism-to-prevent-gpe-flooding.patch
+hid-usbhid-add-quirk-for-the-futaba-tosd-5711bb-vfd.patch
+hid-usbhid-add-quirk-for-mayflash-dragonrise-dolphinbar.patch
+drm-edid-constify-edid-quirk-list.patch
+drm-i915-fix-intel_bdw_ids-definition.patch
+drm-i915-more-.is_mobile-cleanups-for-bdw.patch
+drm-i915-actually-drive-the-bdw-reserved-ids.patch
+asoc-intel-bytcr_rt5640-quirks-for-insyde-devices.patch
+scsi-ufs-introduce-a-new-ufshcd_statea-ufshcd_state_eh_scheduled.patch
+scsi-ufs-issue-link-starup-2-times-if-device-isn-t-active.patch
+arm-omap2-fix-init-for-multiple-quirks-for-the-same-soc.patch
+scsi-ufs-refactor-device-descriptor-reading.patch
+usb-chipidea-msm-rely-on-core-to-override-ahbburst.patch
+serial-8250_omap-add-omap_dma_tx_kick-quirk-for-am437x.patch
+input-gpio_keys-add-support-for-gpio-descriptors.patch
+amd-xgbe-prepare-for-working-with-more-than-one-type-of-phy.patch
+arm-davinci-pm-support-da8xx-dt-platforms.patch
+arm-davinci-add-skeleton-for-pdata-quirks.patch
+usb-xhci-add-quirk-flag-for-broken-ped-bits.patch
+usb-host-xhci-plat-enable-broken_ped-quirk-if-platform-requested.patch
+usb-dwc3-host-pass-quirk-broken-port-ped-property-for-known-broken-revisions.patch
+drm-mga-remove-device_is_agp-callback.patch
+arm-dts-stih407-family-set-snps-dis_u3_susphy_quirk.patch
+pci-add-acs-quirk-for-intel-union-point.patch
+pci-xgene-fix-double-free-on-init-error.patch
+rx51-broken-build.patch
+sata-ahci-da850-implement-a-workaround-for-the-softreset-quirk.patch
+acpi-button-change-default-behavior-to-lid_init_state-open.patch
+asoc-rt5670-add-missing-10ec5072-acpi-id.patch
+asoc-codecs-rt5670-add-quirk-for-lenovo-thinkpad-10.patch
+asoc-intel-baytrail-add-quirk-for-lenovo-thinkpad-10.patch
+asoc-intel-cht_bsw_rt5645-harden-acpi-device-detection.patch
+asoc-intel-cht_bsw_rt5645-add-baytrail-mclk-support.patch
+acpi-save-nvs-memory-for-lenovo-g50-45.patch
+usb-musb-da8xx-fix-host-mode-suspend.patch
+asoc-sun4i-i2s-add-quirks-to-handle-a31-compatible.patch
+hid-wacom-don-t-apply-generic-settings-to-old-devices.patch
+arm-kernel-add-smc-structure-parameter.patch
+firmware-qcom-scm-fix-interrupted-scm-calls.patch
+drm-msm-adreno-move-function-declarations-to-header-file.patch
+arm-smccc-update-hvc-comment-to-describe-new-quirk-parameter.patch
+pci-add-broadcom-northstar2-paxc-quirk-for-device-class-and-mpss.patch
+pci-disable-msi-for-hisilicon-hip06-hip07-root-ports.patch
+mmc-sdhci-of-esdhc-remove-default-broken-cd-for-arm.patch
+pci-sort-the-list-of-devices-with-d3-delay-quirk-by-id.patch
+pci-add-acs-quirk-for-qualcomm-qdf2400-and-qdf2432.patch
+watchdog-s3c2410-fix-infinite-interrupt-in-soft-mode.patch
+platform-x86-asus-wmi-set-specified-xusb2pr-value-for-x550lb.patch
+platform-x86-asus-wmi-detect-quirk_no_rfkill-from-the-dsdt.patch
+tools-power-turbostat-decode-baytrail-cc6-and-mc6-demotion-configuration.patch
+tools-power-turbostat-dump-atom-p-states-correctly.patch
+x86-reboot-quirks-add-asus-eeebook-x205ta-reboot-quirk.patch
+x86-reboot-quirks-add-asus-eeebook-x205ta-w-reboot-quirk.patch
+usb-storage-add-ignore-residue-quirk-for-initio-inic-3619.patch
+x86-reboot-quirks-fix-typo-in-asus-eeebook-x205ta-reboot-quirk.patch
+can-flexcan-add-quirk-flexcan_quirk_enable_eacen_rrs.patch
diff --git a/queue-4.9/svcauth_gss-close-connection-when-dropping-an-incoming-message.patch b/queue-4.9/svcauth_gss-close-connection-when-dropping-an-incoming-message.patch
new file mode 100644 (file)
index 0000000..607481a
--- /dev/null
@@ -0,0 +1,97 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:07 +0000
+Subject: svcauth_gss: Close connection when dropping an incoming message
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-17-alexander.levin@verizon.com>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 4d712ef1db05c3aa5c3b690a50c37ebad584c53f ]
+
+S5.3.3.1 of RFC 2203 requires that an incoming GSS-wrapped message
+whose sequence number lies outside the current window is dropped.
+The rationale is:
+
+  The reason for discarding requests silently is that the server
+  is unable to determine if the duplicate or out of range request
+  was due to a sequencing problem in the client, network, or the
+  operating system, or due to some quirk in routing, or a replay
+  attack by an intruder.  Discarding the request allows the client
+  to recover after timing out, if indeed the duplication was
+  unintentional or well intended.
+
+However, clients may rely on the server dropping the connection to
+indicate that a retransmit is needed. Without a connection reset, a
+client can wait forever without retransmitting, and the workload
+just stops dead. I've reproduced this behavior by running xfstests
+generic/323 on an NFSv4.0 mount with proto=rdma and sec=krb5i.
+
+To address this issue, have the server close the connection when it
+silently discards an incoming message due to a GSS sequence number
+problem.
+
+There are a few other places where the server will never reply.
+Change those spots in a similar fashion.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/auth_gss/svcauth_gss.c |    2 +-
+ net/sunrpc/svc.c                  |   14 +++++++++-----
+ 2 files changed, 10 insertions(+), 6 deletions(-)
+
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1548,7 +1548,7 @@ complete:
+       ret = SVC_COMPLETE;
+       goto out;
+ drop:
+-      ret = SVC_DROP;
++      ret = SVC_CLOSE;
+ out:
+       if (rsci)
+               cache_put(&rsci->h, sn->rsc_cache);
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -1155,8 +1155,7 @@ svc_process_common(struct svc_rqst *rqst
+       case SVC_DENIED:
+               goto err_bad_auth;
+       case SVC_CLOSE:
+-              if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
+-                      svc_close_xprt(rqstp->rq_xprt);
++              goto close;
+       case SVC_DROP:
+               goto dropit;
+       case SVC_COMPLETE:
+@@ -1246,7 +1245,7 @@ svc_process_common(struct svc_rqst *rqst
+  sendit:
+       if (svc_authorise(rqstp))
+-              goto dropit;
++              goto close;
+       return 1;               /* Caller can now send it */
+  dropit:
+@@ -1254,11 +1253,16 @@ svc_process_common(struct svc_rqst *rqst
+       dprintk("svc: svc_process dropit\n");
+       return 0;
++ close:
++      if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
++              svc_close_xprt(rqstp->rq_xprt);
++      dprintk("svc: svc_process close\n");
++      return 0;
++
+ err_short_len:
+       svc_printk(rqstp, "short len %Zd, dropping request\n",
+                       argv->iov_len);
+-
+-      goto dropit;                    /* drop request */
++      goto close;
+ err_bad_rpc:
+       serv->sv_stats->rpcbadfmt++;
diff --git a/queue-4.9/tools-power-turbostat-decode-baytrail-cc6-and-mc6-demotion-configuration.patch b/queue-4.9/tools-power-turbostat-decode-baytrail-cc6-and-mc6-demotion-configuration.patch
new file mode 100644 (file)
index 0000000..77a22d2
--- /dev/null
@@ -0,0 +1,92 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:36 +0000
+Subject: tools/power turbostat: decode Baytrail CC6 and MC6 demotion configuration
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-93-alexander.levin@verizon.com>
+
+From: Len Brown <len.brown@intel.com>
+
+[ Upstream commit 71616c8e936a6dd541f0627d7bf4ff09971d8ccb ]
+
+with --debug, see:
+
+cpu0: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x00000000 (DISable-CC6-Demotion)
+cpu0: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x00000000 (DISable-MC6-Demotion)
+
+Note that the hardware default is to enable demotion,
+and Linux started clearing these registers in 3.17.
+
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/power/x86/turbostat/turbostat.c |   42 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+--- a/tools/power/x86/turbostat/turbostat.c
++++ b/tools/power/x86/turbostat/turbostat.c
+@@ -2951,6 +2951,27 @@ int has_snb_msrs(unsigned int family, un
+ }
+ /*
++ * SLV client has supporet for unique MSRs:
++ *
++ * MSR_CC6_DEMOTION_POLICY_CONFIG
++ * MSR_MC6_DEMOTION_POLICY_CONFIG
++ */
++
++int has_slv_msrs(unsigned int family, unsigned int model)
++{
++      if (!genuine_intel)
++              return 0;
++
++      switch (model) {
++      case INTEL_FAM6_ATOM_SILVERMONT1:
++      case INTEL_FAM6_ATOM_MERRIFIELD:
++      case INTEL_FAM6_ATOM_MOOREFIELD:
++              return 1;
++      }
++      return 0;
++}
++
++/*
+  * HSW adds support for additional MSRs:
+  *
+  * MSR_PKG_C8_RESIDENCY               0x00000630
+@@ -3179,6 +3200,24 @@ void decode_misc_pwr_mgmt_msr(void)
+                       msr & (1 << 0) ? "DIS" : "EN",
+                       msr & (1 << 1) ? "EN" : "DIS");
+ }
++/*
++ * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
++ *
++ * This MSRs are present on Silvermont processors,
++ * Intel Atom processor E3000 series (Baytrail), and friends.
++ */
++void decode_c6_demotion_policy_msr(void)
++{
++      unsigned long long msr;
++
++      if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))
++              fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",
++                      base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
++
++      if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))
++              fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",
++                      base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
++}
+ void process_cpuid()
+ {
+@@ -3360,6 +3399,9 @@ void process_cpuid()
+       if (debug)
+               decode_misc_pwr_mgmt_msr();
++      if (debug && has_slv_msrs(family, model))
++              decode_c6_demotion_policy_msr();
++
+       rapl_probe(family, model);
+       perf_limit_reasons_probe(family, model);
diff --git a/queue-4.9/tools-power-turbostat-dump-atom-p-states-correctly.patch b/queue-4.9/tools-power-turbostat-dump-atom-p-states-correctly.patch
new file mode 100644 (file)
index 0000000..ca86e0c
--- /dev/null
@@ -0,0 +1,165 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:37 +0000
+Subject: tools/power turbostat: dump Atom P-states correctly
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-94-alexander.levin@verizon.com>
+
+From: Len Brown <len.brown@intel.com>
+
+[ Upstream commit 0f7887c49b0c454aef9936a6eadabe1c91b5af55 ]
+
+Turbostat dumps MSR_TURBO_RATIO_LIMIT on Core Architecture.
+But Atom Architecture uses MSR_ATOM_CORE_RATIOS and
+MSR_ATOM_CORE_TURBO_RATIOS.
+
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/power/x86/turbostat/turbostat.c |  103 +++++++++++++++++++++++++++-------
+ 1 file changed, 82 insertions(+), 21 deletions(-)
+
+--- a/tools/power/x86/turbostat/turbostat.c
++++ b/tools/power/x86/turbostat/turbostat.c
+@@ -1470,6 +1470,54 @@ dump_nhm_turbo_ratio_limits(void)
+ }
+ static void
++dump_atom_turbo_ratio_limits(void)
++{
++      unsigned long long msr;
++      unsigned int ratio;
++
++      get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);
++      fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
++
++      ratio = (msr >> 0) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n",
++                      ratio, bclk, ratio * bclk);
++
++      ratio = (msr >> 8) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n",
++                      ratio, bclk, ratio * bclk);
++
++      ratio = (msr >> 16) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
++                      ratio, bclk, ratio * bclk);
++
++      get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
++      fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
++
++      ratio = (msr >> 24) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
++                      ratio, bclk, ratio * bclk);
++
++      ratio = (msr >> 16) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
++                      ratio, bclk, ratio * bclk);
++
++      ratio = (msr >> 8) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
++                      ratio, bclk, ratio * bclk);
++
++      ratio = (msr >> 0) & 0x3F;
++      if (ratio)
++              fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n",
++                      ratio, bclk, ratio * bclk);
++}
++
++static void
+ dump_knl_turbo_ratio_limits(void)
+ {
+       const unsigned int buckets_no = 7;
+@@ -2230,8 +2278,32 @@ int probe_nhm_msrs(unsigned int family,
+       has_base_hz = 1;
+       return 1;
+ }
++/*
++ * SLV client has supporet for unique MSRs:
++ *
++ * MSR_CC6_DEMOTION_POLICY_CONFIG
++ * MSR_MC6_DEMOTION_POLICY_CONFIG
++ */
++
++int has_slv_msrs(unsigned int family, unsigned int model)
++{
++      if (!genuine_intel)
++              return 0;
++
++      switch (model) {
++      case INTEL_FAM6_ATOM_SILVERMONT1:
++      case INTEL_FAM6_ATOM_MERRIFIELD:
++      case INTEL_FAM6_ATOM_MOOREFIELD:
++              return 1;
++      }
++      return 0;
++}
++
+ int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
+ {
++      if (has_slv_msrs(family, model))
++              return 0;
++
+       switch (model) {
+       /* Nehalem compatible, but do not include turbo-ratio limit support */
+       case 0x2E:      /* Nehalem-EX Xeon - Beckton */
+@@ -2242,6 +2314,13 @@ int has_nhm_turbo_ratio_limit(unsigned i
+               return 1;
+       }
+ }
++int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
++{
++      if (has_slv_msrs(family, model))
++              return 1;
++
++      return 0;
++}
+ int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
+ {
+       if (!genuine_intel)
+@@ -2337,6 +2416,9 @@ dump_cstate_pstate_config_info(unsigned
+       if (has_nhm_turbo_ratio_limit(family, model))
+               dump_nhm_turbo_ratio_limits();
++      if (has_atom_turbo_ratio_limit(family, model))
++              dump_atom_turbo_ratio_limits();
++
+       if (has_knl_turbo_ratio_limit(family, model))
+               dump_knl_turbo_ratio_limits();
+@@ -2948,27 +3030,6 @@ int has_snb_msrs(unsigned int family, un
+               return 1;
+       }
+       return 0;
+-}
+-
+-/*
+- * SLV client has supporet for unique MSRs:
+- *
+- * MSR_CC6_DEMOTION_POLICY_CONFIG
+- * MSR_MC6_DEMOTION_POLICY_CONFIG
+- */
+-
+-int has_slv_msrs(unsigned int family, unsigned int model)
+-{
+-      if (!genuine_intel)
+-              return 0;
+-
+-      switch (model) {
+-      case INTEL_FAM6_ATOM_SILVERMONT1:
+-      case INTEL_FAM6_ATOM_MERRIFIELD:
+-      case INTEL_FAM6_ATOM_MOOREFIELD:
+-              return 1;
+-      }
+-      return 0;
+ }
+ /*
diff --git a/queue-4.9/usb-chipidea-msm-rely-on-core-to-override-ahbburst.patch b/queue-4.9/usb-chipidea-msm-rely-on-core-to-override-ahbburst.patch
new file mode 100644 (file)
index 0000000..cee7301
--- /dev/null
@@ -0,0 +1,49 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:21 +0000
+Subject: usb: chipidea: msm: Rely on core to override AHBBURST
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-53-alexander.levin@verizon.com>
+
+From: Stephen Boyd <stephen.boyd@linaro.org>
+
+[ Upstream commit dd3749099cfa2c80039193c438b90f3160eaf7f9 ]
+
+The core framework already handles setting this parameter with a
+platform quirk. Add the appropriate flag so that we always set
+AHBBURST to 0. Technically DT should be doing this, but we always
+do it for msm chipidea devices so setting the flag in the driver
+works just as well. If the burst needs to be anything besides 0,
+we expect the 'ahb-burst-config' dts property to be present.
+
+Acked-by: Peter Chen <peter.chen@nxp.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
+Signed-off-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/chipidea/ci_hdrc_msm.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/chipidea/ci_hdrc_msm.c
++++ b/drivers/usb/chipidea/ci_hdrc_msm.c
+@@ -24,7 +24,6 @@ static void ci_hdrc_msm_notify_event(str
+       switch (event) {
+       case CI_HDRC_CONTROLLER_RESET_EVENT:
+               dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
+-              writel(0, USB_AHBBURST);
+               /* use AHB transactor, allow posted data writes */
+               writel(0x8, USB_AHBMODE);
+               usb_phy_init(ci->usb_phy);
+@@ -47,7 +46,8 @@ static struct ci_hdrc_platform_data ci_h
+       .name                   = "ci_hdrc_msm",
+       .capoffset              = DEF_CAPOFFSET,
+       .flags                  = CI_HDRC_REGS_SHARED |
+-                                CI_HDRC_DISABLE_STREAMING,
++                                CI_HDRC_DISABLE_STREAMING |
++                                CI_HDRC_OVERRIDE_AHB_BURST,
+       .notify_event           = ci_hdrc_msm_notify_event,
+ };
diff --git a/queue-4.9/usb-dwc3-host-pass-quirk-broken-port-ped-property-for-known-broken-revisions.patch b/queue-4.9/usb-dwc3-host-pass-quirk-broken-port-ped-property-for-known-broken-revisions.patch
new file mode 100644 (file)
index 0000000..0cca630
--- /dev/null
@@ -0,0 +1,67 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:25 +0000
+Subject: usb: dwc3: host: pass quirk-broken-port-ped property for known broken revisions
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-62-alexander.levin@verizon.com>
+
+From: Felipe Balbi <felipe.balbi@linux.intel.com>
+
+[ Upstream commit e42a5dbb8a3d14f5a35bffa3bf7dcb87883f767a ]
+
+dwc3 revisions <=3.00a have a limitation where Port Disable command
+doesn't work. Set the quirk-broken-port-ped property for such
+controllers so XHCI core can do the necessary workaround.
+
+[rogerq@ti.com] Updated code from platform data to device property.
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/host.c |   21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -21,11 +21,12 @@
+ int dwc3_host_init(struct dwc3 *dwc)
+ {
+-      struct property_entry   props[2];
++      struct property_entry   props[3];
+       struct platform_device  *xhci;
+       int                     ret, irq;
+       struct resource         *res;
+       struct platform_device  *dwc3_pdev = to_platform_device(dwc->dev);
++      int                     prop_idx = 0;
+       irq = platform_get_irq_byname(dwc3_pdev, "host");
+       if (irq == -EPROBE_DEFER)
+@@ -89,8 +90,22 @@ int dwc3_host_init(struct dwc3 *dwc)
+       memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
+-      if (dwc->usb3_lpm_capable) {
+-              props[0].name = "usb3-lpm-capable";
++      if (dwc->usb3_lpm_capable)
++              props[prop_idx++].name = "usb3-lpm-capable";
++
++      /**
++       * WORKAROUND: dwc3 revisions <=3.00a have a limitation
++       * where Port Disable command doesn't work.
++       *
++       * The suggested workaround is that we avoid Port Disable
++       * completely.
++       *
++       * This following flag tells XHCI to do just that.
++       */
++      if (dwc->revision <= DWC3_REVISION_300A)
++              props[prop_idx++].name = "quirk-broken-port-ped";
++
++      if (prop_idx) {
+               ret = platform_device_add_properties(xhci, props);
+               if (ret) {
+                       dev_err(dwc->dev, "failed to add properties to xHCI\n");
diff --git a/queue-4.9/usb-host-xhci-plat-enable-broken_ped-quirk-if-platform-requested.patch b/queue-4.9/usb-host-xhci-plat-enable-broken_ped-quirk-if-platform-requested.patch
new file mode 100644 (file)
index 0000000..64037d1
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:24 +0000
+Subject: usb: host: xhci-plat: enable BROKEN_PED quirk if platform requested
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-61-alexander.levin@verizon.com>
+
+From: Felipe Balbi <balbi@ti.com>
+
+[ Upstream commit 21939f003ad09355d9c975735750bb22aa37d8de ]
+
+In case 'quirk-broken-port-ped' property is passed in via device property,
+we should enable the corresponding BROKEN_PED quirk flag for XHCI core.
+
+[rogerq@ti.com] Updated code from platform data to device property
+and added DT binding.
+
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/usb/usb-xhci.txt |    1 +
+ drivers/usb/host/xhci-plat.c                       |    3 +++
+ 2 files changed, 4 insertions(+)
+
+--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
++++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
+@@ -26,6 +26,7 @@ Required properties:
+ Optional properties:
+   - clocks: reference to a clock
+   - usb3-lpm-capable: determines if platform is USB3 LPM capable
++  - quirk-broken-port-ped: set if the controller has broken port disable mechanism
+ Example:
+       usb@f0931000 {
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -223,6 +223,9 @@ static int xhci_plat_probe(struct platfo
+       if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
+               xhci->quirks |= XHCI_LPM_SUPPORT;
++      if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped"))
++              xhci->quirks |= XHCI_BROKEN_PORT_PED;
++
+       hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
+       if (IS_ERR(hcd->usb_phy)) {
+               ret = PTR_ERR(hcd->usb_phy);
diff --git a/queue-4.9/usb-musb-da8xx-fix-host-mode-suspend.patch b/queue-4.9/usb-musb-da8xx-fix-host-mode-suspend.patch
new file mode 100644 (file)
index 0000000..ca7af0d
--- /dev/null
@@ -0,0 +1,39 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:30 +0000
+Subject: usb: musb: da8xx: Fix host mode suspend
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-76-alexander.levin@verizon.com>
+
+From: Alexandre Bailon <abailon@baylibre.com>
+
+[ Upstream commit 486fc20ac8391338a42b015801b846acda4db7b7 ]
+
+On da8xx, VBUS is not maintained during suspend when musb is in host mode.
+On resume, all the connected devices will be disconnected and then will
+be enumerated again.
+This happens because MUSB_DEVCTL is cleared during suspend.
+
+Use the quirk MUSB_PRESERVE_SESSION to preseve MUSB_DEVCTL during suspend.
+
+Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
+Signed-off-by: Bin Liu <b-liu@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/da8xx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/musb/da8xx.c
++++ b/drivers/usb/musb/da8xx.c
+@@ -434,7 +434,7 @@ static int da8xx_musb_exit(struct musb *
+ }
+ static const struct musb_platform_ops da8xx_ops = {
+-      .quirks         = MUSB_INDEXED_EP,
++      .quirks         = MUSB_INDEXED_EP | MUSB_PRESERVE_SESSION,
+       .init           = da8xx_musb_init,
+       .exit           = da8xx_musb_exit,
diff --git a/queue-4.9/usb-storage-add-ignore-residue-quirk-for-initio-inic-3619.patch b/queue-4.9/usb-storage-add-ignore-residue-quirk-for-initio-inic-3619.patch
new file mode 100644 (file)
index 0000000..fd07b2b
--- /dev/null
@@ -0,0 +1,52 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:38 +0000
+Subject: usb-storage: Add ignore-residue quirk for Initio INIC-3619
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-97-alexander.levin@verizon.com>
+
+From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
+
+[ Upstream commit d595259fbb7a7afed241b1afb2c4fe4b47de47fa ]
+
+This USB-SATA bridge chip is used in a StarTech enclosure for
+optical drives.
+
+Without the quirk MakeMKV fails during the key exchange with an
+installed BluRay drive:
+> Error 'Scsi error - ILLEGAL REQUEST:COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED'
+> occurred while issuing SCSI command AD010..080002400 to device 'SG:dev_11:2'
+
+Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/storage/unusual_devs.h |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -2071,6 +2071,20 @@ UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
++/*
++ * Reported by Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
++ * The INIC-3619 bridge is used in the StarTech SLSODDU33B
++ * SATA-USB enclosure for slimline optical drives.
++ *
++ * The quirk enables MakeMKV to properly exchange keys with
++ * an installed BD drive.
++ */
++UNUSUAL_DEV(  0x13fd, 0x3609, 0x0209, 0x0209,
++              "Initio Corporation",
++              "INIC-3619",
++              USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++              US_FL_IGNORE_RESIDUE ),
++
+ /* Reported by Qinglin Ye <yestyle@gmail.com> */
+ UNUSUAL_DEV(  0x13fe, 0x3600, 0x0100, 0x0100,
+               "Kingston",
diff --git a/queue-4.9/usb-xhci-add-quirk-flag-for-broken-ped-bits.patch b/queue-4.9/usb-xhci-add-quirk-flag-for-broken-ped-bits.patch
new file mode 100644 (file)
index 0000000..9d62dac
--- /dev/null
@@ -0,0 +1,67 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:24 +0000
+Subject: usb: xhci: add quirk flag for broken PED bits
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-60-alexander.levin@verizon.com>
+
+From: Felipe Balbi <balbi@ti.com>
+
+[ Upstream commit 41135de1e7fd14c6fcb9158404ba5c8fb97bf259 ]
+
+Some devices from Texas Instruments [1] suffer from
+a silicon bug where Port Enabled/Disabled bit
+should not be used to silence an erroneous device.
+
+The bug is so that if port is disabled with PED
+bit, an IRQ for device removal (or attachment)
+will never fire.
+
+Just for the sake of completeness, the actual
+problem lies with SNPS USB IP and this affects
+all known versions up to 3.00a. A separate
+patch will be added to dwc3 to enabled this
+quirk flag if version is <= 3.00a.
+
+[1] - AM572x Silicon Errata http://www.ti.com/lit/er/sprz429j/sprz429j.pdf
+Section i896— USB xHCI Port Disable Feature Does Not Work
+
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-hub.c |    6 ++++++
+ drivers/usb/host/xhci.h     |    3 +++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -458,6 +458,12 @@ static void xhci_disable_port(struct usb
+               return;
+       }
++      if (xhci->quirks & XHCI_BROKEN_PORT_PED) {
++              xhci_dbg(xhci,
++                       "Broken Port Enabled/Disabled, ignoring port disable request.\n");
++              return;
++      }
++
+       /* Write 1 to disable the port */
+       writel(port_status | PORT_PE, addr);
+       port_status = readl(addr);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1657,6 +1657,9 @@ struct xhci_hcd {
+ #define XHCI_SSIC_PORT_UNUSED (1 << 22)
+ #define XHCI_NO_64BIT_SUPPORT (1 << 23)
+ #define XHCI_MISSING_CAS      (1 << 24)
++/* For controller with a broken Port Disable implementation */
++#define XHCI_BROKEN_PORT_PED  (1 << 25)
++
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
+       /* There are two roothubs to keep track of bus suspend info for */
diff --git a/queue-4.9/watchdog-s3c2410-fix-infinite-interrupt-in-soft-mode.patch b/queue-4.9/watchdog-s3c2410-fix-infinite-interrupt-in-soft-mode.patch
new file mode 100644 (file)
index 0000000..2b37973
--- /dev/null
@@ -0,0 +1,130 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:35 +0000
+Subject: watchdog: s3c2410: Fix infinite interrupt in soft mode
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-90-alexander.levin@verizon.com>
+
+From: Krzysztof Kozlowski <krzk@kernel.org>
+
+[ Upstream commit 0b445549ea6f91ffea78a976fe89b932db6e077a ]
+
+In soft (no-reboot) mode, the driver self-pings watchdog upon expiration
+of an interrupt.  However the interrupt itself was not cleared thus on
+first hit, the system enters infinite interrupt handling loop.
+
+On Odroid U3 (Exynos4412), when booted with s3c2410_wdt.soft_noboot=1
+argument the console is flooded:
+       # killall -9 watchdog
+       [   60.523760] s3c2410-wdt 10060000.watchdog: watchdog timer expired (irq)
+       [   60.536744] s3c2410-wdt 10060000.watchdog: watchdog timer expired (irq)
+
+Fix this by writing something to the WTCLRINT register to clear the
+interrupt.  The register WTCLRINT however appeared in S3C6410 so a new
+watchdog quirk and flavor are needed.
+
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/watchdog/samsung-wdt.txt |    9 +++--
+ drivers/watchdog/s3c2410_wdt.c                             |   21 +++++++++++--
+ 2 files changed, 23 insertions(+), 7 deletions(-)
+
+--- a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
++++ b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
+@@ -6,10 +6,11 @@ occurred.
+ Required properties:
+ - compatible : should be one among the following
+-      (a) "samsung,s3c2410-wdt" for Exynos4 and previous SoCs
+-      (b) "samsung,exynos5250-wdt" for Exynos5250
+-      (c) "samsung,exynos5420-wdt" for Exynos5420
+-      (c) "samsung,exynos7-wdt" for Exynos7
++      - "samsung,s3c2410-wdt" for S3C2410
++      - "samsung,s3c6410-wdt" for S3C6410, S5PV210 and Exynos4
++      - "samsung,exynos5250-wdt" for Exynos5250
++      - "samsung,exynos5420-wdt" for Exynos5420
++      - "samsung,exynos7-wdt" for Exynos7
+ - reg : base physical address of the controller and length of memory mapped
+       region.
+--- a/drivers/watchdog/s3c2410_wdt.c
++++ b/drivers/watchdog/s3c2410_wdt.c
+@@ -46,6 +46,7 @@
+ #define S3C2410_WTCON         0x00
+ #define S3C2410_WTDAT         0x04
+ #define S3C2410_WTCNT         0x08
++#define S3C2410_WTCLRINT      0x0c
+ #define S3C2410_WTCNT_MAXCNT  0xffff
+@@ -72,6 +73,7 @@
+ #define EXYNOS5_WDT_MASK_RESET_REG_OFFSET     0x040c
+ #define QUIRK_HAS_PMU_CONFIG                  (1 << 0)
+ #define QUIRK_HAS_RST_STAT                    (1 << 1)
++#define QUIRK_HAS_WTCLRINT_REG                        (1 << 2)
+ /* These quirks require that we have a PMU register map */
+ #define QUIRKS_HAVE_PMUREG                    (QUIRK_HAS_PMU_CONFIG | \
+@@ -143,13 +145,18 @@ static const struct s3c2410_wdt_variant
+ };
+ #ifdef CONFIG_OF
++static const struct s3c2410_wdt_variant drv_data_s3c6410 = {
++      .quirks = QUIRK_HAS_WTCLRINT_REG,
++};
++
+ static const struct s3c2410_wdt_variant drv_data_exynos5250  = {
+       .disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET,
+       .mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET,
+       .mask_bit = 20,
+       .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
+       .rst_stat_bit = 20,
+-      .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT,
++      .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT \
++                | QUIRK_HAS_WTCLRINT_REG,
+ };
+ static const struct s3c2410_wdt_variant drv_data_exynos5420 = {
+@@ -158,7 +165,8 @@ static const struct s3c2410_wdt_variant
+       .mask_bit = 0,
+       .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
+       .rst_stat_bit = 9,
+-      .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT,
++      .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT \
++                | QUIRK_HAS_WTCLRINT_REG,
+ };
+ static const struct s3c2410_wdt_variant drv_data_exynos7 = {
+@@ -167,12 +175,15 @@ static const struct s3c2410_wdt_variant
+       .mask_bit = 23,
+       .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
+       .rst_stat_bit = 23,     /* A57 WDTRESET */
+-      .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT,
++      .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT \
++                | QUIRK_HAS_WTCLRINT_REG,
+ };
+ static const struct of_device_id s3c2410_wdt_match[] = {
+       { .compatible = "samsung,s3c2410-wdt",
+         .data = &drv_data_s3c2410 },
++      { .compatible = "samsung,s3c6410-wdt",
++        .data = &drv_data_s3c6410 },
+       { .compatible = "samsung,exynos5250-wdt",
+         .data = &drv_data_exynos5250 },
+       { .compatible = "samsung,exynos5420-wdt",
+@@ -418,6 +429,10 @@ static irqreturn_t s3c2410wdt_irq(int ir
+       dev_info(wdt->dev, "watchdog timer expired (irq)\n");
+       s3c2410wdt_keepalive(&wdt->wdt_device);
++
++      if (wdt->drv_data->quirks & QUIRK_HAS_WTCLRINT_REG)
++              writel(0x1, wdt->reg_base + S3C2410_WTCLRINT);
++
+       return IRQ_HANDLED;
+ }
diff --git a/queue-4.9/x86-intel_idle-add-cpu-model-0x4a-atom-z34xx-series.patch b/queue-4.9/x86-intel_idle-add-cpu-model-0x4a-atom-z34xx-series.patch
new file mode 100644 (file)
index 0000000..ba2dd55
--- /dev/null
@@ -0,0 +1,96 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:08 +0000
+Subject: x86/intel_idle: Add CPU model 0x4a (Atom Z34xx series)
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-18-alexander.levin@verizon.com>
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 5e7ec268fd48d63cfd0e3a9be6c6443f01673bd4 ]
+
+Add CPU ID for Atom Z34xx processors. Datasheets indicate support for this,
+detailed information about potential quirks or limitations are missing, though.
+So we just reuse the definition from official BSP code.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/idle/intel_idle.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -724,6 +724,50 @@ static struct cpuidle_state atom_cstates
+       {
+               .enter = NULL }
+ };
++static struct cpuidle_state tangier_cstates[] = {
++      {
++              .name = "C1-TNG",
++              .desc = "MWAIT 0x00",
++              .flags = MWAIT2flg(0x00),
++              .exit_latency = 1,
++              .target_residency = 4,
++              .enter = &intel_idle,
++              .enter_freeze = intel_idle_freeze, },
++      {
++              .name = "C4-TNG",
++              .desc = "MWAIT 0x30",
++              .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
++              .exit_latency = 100,
++              .target_residency = 400,
++              .enter = &intel_idle,
++              .enter_freeze = intel_idle_freeze, },
++      {
++              .name = "C6-TNG",
++              .desc = "MWAIT 0x52",
++              .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
++              .exit_latency = 140,
++              .target_residency = 560,
++              .enter = &intel_idle,
++              .enter_freeze = intel_idle_freeze, },
++      {
++              .name = "C7-TNG",
++              .desc = "MWAIT 0x60",
++              .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
++              .exit_latency = 1200,
++              .target_residency = 4000,
++              .enter = &intel_idle,
++              .enter_freeze = intel_idle_freeze, },
++      {
++              .name = "C9-TNG",
++              .desc = "MWAIT 0x64",
++              .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
++              .exit_latency = 10000,
++              .target_residency = 20000,
++              .enter = &intel_idle,
++              .enter_freeze = intel_idle_freeze, },
++      {
++              .enter = NULL }
++};
+ static struct cpuidle_state avn_cstates[] = {
+       {
+               .name = "C1-AVN",
+@@ -978,6 +1022,10 @@ static const struct idle_cpu idle_cpu_at
+       .state_table = atom_cstates,
+ };
++static const struct idle_cpu idle_cpu_tangier = {
++      .state_table = tangier_cstates,
++};
++
+ static const struct idle_cpu idle_cpu_lincroft = {
+       .state_table = atom_cstates,
+       .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
+@@ -1066,6 +1114,7 @@ static const struct x86_cpu_id intel_idl
+       ICPU(INTEL_FAM6_SANDYBRIDGE_X,          idle_cpu_snb),
+       ICPU(INTEL_FAM6_ATOM_CEDARVIEW,         idle_cpu_atom),
+       ICPU(INTEL_FAM6_ATOM_SILVERMONT1,       idle_cpu_byt),
++      ICPU(INTEL_FAM6_ATOM_MERRIFIELD,        idle_cpu_tangier),
+       ICPU(INTEL_FAM6_ATOM_AIRMONT,           idle_cpu_cht),
+       ICPU(INTEL_FAM6_IVYBRIDGE,              idle_cpu_ivb),
+       ICPU(INTEL_FAM6_IVYBRIDGE_X,            idle_cpu_ivt),
diff --git a/queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-reboot-quirk.patch b/queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-reboot-quirk.patch
new file mode 100644 (file)
index 0000000..9c6b582
--- /dev/null
@@ -0,0 +1,50 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:37 +0000
+Subject: x86/reboot/quirks: Add ASUS EeeBook X205TA reboot quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-95-alexander.levin@verizon.com>
+
+From: Matjaz Hegedic <matjaz.hegedic@gmail.com>
+
+[ Upstream commit 90b28ded88dda8bea82b4a86923e73ba0746d884 ]
+
+Without the parameter reboot=a, ASUS EeeBook X205TA will hang when it should reboot.
+
+This adds the appropriate quirk, thus fixing the problem.
+
+Signed-off-by: Matjaz Hegedic <matjaz.hegedic@gmail.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/reboot.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -223,6 +223,14 @@ static struct dmi_system_id __initdata r
+                       DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
+               },
+       },
++      {       /* Handle problems with rebooting on ASUS EeeBook X205TA */
++              .callback = set_acpi_reboot,
++              .ident = "ASUS EeeBook X205TA",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "X205TAW"),
++              },
++      },
+       /* Certec */
+       {       /* Handle problems with rebooting on Certec BPC600 */
diff --git a/queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-w-reboot-quirk.patch b/queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-w-reboot-quirk.patch
new file mode 100644 (file)
index 0000000..74ac2e2
--- /dev/null
@@ -0,0 +1,42 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:38 +0000
+Subject: x86/reboot/quirks: Add ASUS EeeBook X205TA/W reboot quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-96-alexander.levin@verizon.com>
+
+From: Matjaz Hegedic <matjaz.hegedic@gmail.com>
+
+[ Upstream commit 3b3e78552d3077ec70d2640e629e07e3ab416a6a ]
+
+Without the parameter reboot=a, ASUS EeeBook X205TA/W will hang
+when it should reboot. This adds the appropriate quirk, thus
+fixing the problem.
+
+Signed-off-by: Matjaz Hegedic <matjaz.hegedic@gmail.com>
+Link: http://lkml.kernel.org/r/1488737804-20681-1-git-send-email-matjaz.hegedic@gmail.com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/reboot.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -231,6 +231,14 @@ static struct dmi_system_id __initdata r
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X205TAW"),
+               },
+       },
++      {       /* Handle problems with rebooting on ASUS EeeBook X205TAW */
++              .callback = set_acpi_reboot,
++              .ident = "ASUS EeeBook X205TAW",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "X205TAW"),
++              },
++      },
+       /* Certec */
+       {       /* Handle problems with rebooting on Certec BPC600 */
diff --git a/queue-4.9/x86-reboot-quirks-fix-typo-in-asus-eeebook-x205ta-reboot-quirk.patch b/queue-4.9/x86-reboot-quirks-fix-typo-in-asus-eeebook-x205ta-reboot-quirk.patch
new file mode 100644 (file)
index 0000000..76eca43
--- /dev/null
@@ -0,0 +1,40 @@
+From foo@baz Mon Apr 10 17:43:56 CEST 2017
+From: alexander.levin@verizon.com
+Date: Tue, 4 Apr 2017 19:32:38 +0000
+Subject: x86/reboot/quirks: Fix typo in ASUS EeeBook X205TA reboot quirk
+To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
+Message-ID: <20170404193158.19041-98-alexander.levin@verizon.com>
+
+From: Matjaz Hegedic <matjaz.hegedic@gmail.com>
+
+[ Upstream commit bba8376aea1dcbbe22bbda118c52abee317c7609 ]
+
+The reboot quirk for ASUS EeeBook X205TA contains a typo in
+DMI_PRODUCT_NAME, improperly referring to X205TAW instead of
+X205TA, which prevents the quirk from being triggered. The
+model X205TAW already has a reboot quirk of its own.
+
+This fix simply removes the inappropriate final letter W.
+
+Fixes: 90b28ded88dd ("x86/reboot/quirks: Add ASUS EeeBook X205TA reboot quirk")
+Signed-off-by: Matjaz Hegedic <matjaz.hegedic@gmail.com>
+Link: http://lkml.kernel.org/r/1489064417-7445-1-git-send-email-matjaz.hegedic@gmail.com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/reboot.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -228,7 +228,7 @@ static struct dmi_system_id __initdata r
+               .ident = "ASUS EeeBook X205TA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+-                      DMI_MATCH(DMI_PRODUCT_NAME, "X205TAW"),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "X205TA"),
+               },
+       },
+       {       /* Handle problems with rebooting on ASUS EeeBook X205TAW */