From: Greg Kroah-Hartman Date: Mon, 10 Apr 2017 16:05:55 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.4.61~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1b722f1b9de6a687c75abb65246e3d65178cd12e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches 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 --- 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 index 00000000000..d0ea57593ed --- /dev/null +++ b/queue-4.9/acpi-button-change-default-behavior-to-lid_init_state-open.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-69-alexander.levin@verizon.com> + +From: Lv Zheng + +[ 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 +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dba79ccf4ec --- /dev/null +++ b/queue-4.9/acpi-save-nvs-memory-for-lenovo-g50-45.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-75-alexander.levin@verizon.com> + +From: Zhang Rui + +[ 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 +Signed-off-by: Zhang Rui +[ rjw: Drop unnecessary code ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3344b4170ac --- /dev/null +++ b/queue-4.9/acpi-sysfs-provide-quirk-mechanism-to-prevent-gpe-flooding.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-41-alexander.levin@verizon.com> + +From: Lv Zheng + +[ 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 +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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: ,... + ++ 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: ++ 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< +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-32-alexander.levin@verizon.com> + +From: Alberto Aguirre + +[ 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 +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..fcfd6646a1b --- /dev/null +++ b/queue-4.9/alsa-usb-audio-add-native-dsd-support-for-teac-501-503-dac.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-34-alexander.levin@verizon.com> + +From: Nobutaka Okabe + +[ 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 +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cfc0ad0d55c --- /dev/null +++ b/queue-4.9/amd-xgbe-prepare-for-working-with-more-than-one-type-of-phy.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-57-alexander.levin@verizon.com> + +From: "Lendacky, Thomas" + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 . ++ * ++ * 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 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 + + #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 index 00000000000..697196cf4b5 --- /dev/null +++ b/queue-4.9/arm-davinci-add-skeleton-for-pdata-quirks.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-59-alexander.levin@verizon.com> + +From: Kevin Hilman + +[ Upstream commit 9c9b1bc25291e275b04f758f2549c81e092954f5 ] + +Add skeleton pdata-quirks for davinci. + +Signed-off-by: Kevin Hilman +[nsekhar@ti.com: move changes to build pdata-quirks.c and call + to pdata_quirks_init() to this patch] +Signed-off-by: Sekhar Nori +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++#include ++ ++#include ++ ++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 index 00000000000..101a6daf535 --- /dev/null +++ b/queue-4.9/arm-davinci-pm-support-da8xx-dt-platforms.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-58-alexander.levin@verizon.com> + +From: Kevin Hilman + +[ Upstream commit 7e431af8fa0b9ed9d74378c99514856211cb9db8 ] + +Add PM support for DA850 device-tree boot. + +Signed-off-by: Kevin Hilman +Signed-off-by: Sekhar Nori +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..32545779d29 --- /dev/null +++ b/queue-4.9/arm-dts-stih407-family-set-snps-dis_u3_susphy_quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-64-alexander.levin@verizon.com> + +From: Patrice Chotard + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..33461f96198 --- /dev/null +++ b/queue-4.9/arm-kernel-add-smc-structure-parameter.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-79-alexander.levin@verizon.com> + +From: Andy Gross + +[ 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 +Reviewed-by: Will Deacon +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..e682940be85 --- /dev/null +++ b/queue-4.9/arm-omap2-fix-init-for-multiple-quirks-for-the-same-soc.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-51-alexander.levin@verizon.com> + +From: Tony Lindgren + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..8cdb44ea0a9 --- /dev/null +++ b/queue-4.9/arm-smccc-update-hvc-comment-to-describe-new-quirk-parameter.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-82-alexander.levin@verizon.com> + +From: Will Deacon + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..840205e07e4 --- /dev/null +++ b/queue-4.9/arm64-dts-hisi-fix-hip06-sas-am-max-trans-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-7-alexander.levin@verizon.com> + +From: John Garry + +[ Upstream commit f65e786604b34d0b599b8c01ecca28be2d746290 ] + +The string for the am max transmissions quirk property +is not correct -> fix it. + +Signed-off-by: John Garry +Reviewed-by: Xiang Chen +Signed-off-by: Wei Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a78a5c8f86f --- /dev/null +++ b/queue-4.9/arm64-pci-add-local-struct-device-pointers.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-20-alexander.levin@verizon.com> + +From: Bjorn Helgaas + +[ Upstream commit dfd1972c2b464c10fb585c4c60b594e09d181a01 ] + +Use a local "struct device *dev" for brevity. No functional change +intended. + +Signed-off-by: Bjorn Helgaas +Acked-by: Lorenzo Pieralisi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..90b56f1d8dc --- /dev/null +++ b/queue-4.9/arm64-pci-manage-controller-specific-data-on-per-controller-basis.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-19-alexander.levin@verizon.com> + +From: Tomasz Nowicki + +[ 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 +Signed-off-by: Bjorn Helgaas +Acked-by: Lorenzo Pieralisi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cb35a06af3c --- /dev/null +++ b/queue-4.9/arm64-pci-search-acpi-namespace-to-ensure-ecam-space-is-reserved.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-21-alexander.levin@verizon.com> + +From: Bjorn Helgaas + +[ 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 +Acked-by: Lorenzo Pieralisi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..221709cfdf9 --- /dev/null +++ b/queue-4.9/asoc-codecs-rt5670-add-quirk-for-lenovo-thinkpad-10.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-71-alexander.levin@verizon.com> + +From: Pierre-Louis Bossart + +[ Upstream commit 93ffeaa8ee3f10a0628ad135b552a2497e0bef2c ] + +the BIOS incorrectly reports this codec as 5640 but it is +really a rt5670 + +Signed-off-by: Pierre-Louis Bossart +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..9e12cdd53e4 --- /dev/null +++ b/queue-4.9/asoc-intel-baytrail-add-quirk-for-lenovo-thinkpad-10.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-72-alexander.levin@verizon.com> + +From: Pierre-Louis Bossart + +[ 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 +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..831758db8c2 --- /dev/null +++ b/queue-4.9/asoc-intel-bytcr_rt5640-quirks-for-insyde-devices.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-48-alexander.levin@verizon.com> + +From: youling257 + +[ 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 +Signed-off-by: Pierre-Louis Bossart +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..69808d2f122 --- /dev/null +++ b/queue-4.9/asoc-intel-bytct_rt5640-change-default-capture-settings.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-6-alexander.levin@verizon.com> + +From: Pierre-Louis Bossart + +[ 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 +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..9ace1e161ab --- /dev/null +++ b/queue-4.9/asoc-intel-cht_bsw_rt5645-add-baytrail-mclk-support.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-74-alexander.levin@verizon.com> + +From: Pierre-Louis Bossart + +[ 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 +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -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-: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 index 00000000000..71c87ca217b --- /dev/null +++ b/queue-4.9/asoc-intel-cht_bsw_rt5645-harden-acpi-device-detection.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-73-alexander.levin@verizon.com> + +From: Pierre-Louis Bossart + +[ 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 +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ab23037b88f --- /dev/null +++ b/queue-4.9/asoc-rt5670-add-missing-10ec5072-acpi-id.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-70-alexander.levin@verizon.com> + +From: Takashi Iwai + +[ 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 +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d84c6d11e7d --- /dev/null +++ b/queue-4.9/asoc-sun4i-i2s-add-quirks-to-handle-a31-compatible.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-77-alexander.levin@verizon.com> + +From: Mylène Josserand + +[ 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 +Acked-by: Maxime Ripard +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + #include ++#include + + #include + #include +@@ -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 index 00000000000..0b5cde6603a --- /dev/null +++ b/queue-4.9/can-flexcan-add-quirk-flexcan_quirk_enable_eacen_rrs.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-99-alexander.levin@verizon.com> + +From: Marc Kleine-Budde + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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, ®s->ctrl); + ++ if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) { ++ reg_ctrl2 = flexcan_read(®s->ctrl2); ++ reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS; ++ flexcan_write(reg_ctrl2, ®s->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 index 00000000000..ac4915c8b57 --- /dev/null +++ b/queue-4.9/clocksource-drivers-arm_arch_timer-don-t-assume-clock-runs-in-suspend.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-9-alexander.levin@verizon.com> + +From: Brian Norris + +[ 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 +Reviewed-by: Douglas Anderson +Acked-by: Marc Zyngier +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..bc8bd0b7ee7 --- /dev/null +++ b/queue-4.9/drm-edid-constify-edid-quirk-list.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-44-alexander.levin@verizon.com> + +From: Jani Nikula + +[ Upstream commit 23c4cfbdab494568600ae6073a2bf02be4b10f4e ] + +No reason not to be const. + +Reviewed-by: Daniel Vetter +Signed-off-by: Jani Nikula +Link: http://patchwork.freedesktop.org/patch/msgid/1482923186-22430-1-git-send-email-jani.nikula@intel.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..1321e9f7d3a --- /dev/null +++ b/queue-4.9/drm-i915-actually-drive-the-bdw-reserved-ids.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-47-alexander.levin@verizon.com> + +From: Paulo Zanoni + +[ 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 +Cc: Ben Widawsky +Cc: Jani Nikula +Signed-off-by: Paulo Zanoni +Reviewed-by: Rodrigo Vivi +Link: http://patchwork.freedesktop.org/patch/msgid/1483473860-17644-3-git-send-email-paulo.r.zanoni@intel.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..769f33dd2bb --- /dev/null +++ b/queue-4.9/drm-i915-fix-intel_bdw_ids-definition.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-45-alexander.levin@verizon.com> + +From: Paulo Zanoni + +[ 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 +Cc: Rodrigo Vivi +Signed-off-by: Paulo Zanoni +Reviewed-by: Rodrigo Vivi +Link: http://patchwork.freedesktop.org/patch/msgid/1483473860-17644-1-git-send-email-paulo.r.zanoni@intel.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..bd7297f1173 --- /dev/null +++ b/queue-4.9/drm-i915-more-.is_mobile-cleanups-for-bdw.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-46-alexander.levin@verizon.com> + +From: Paulo Zanoni + +[ 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 +Cc: Rodrigo Vivi +Signed-off-by: Paulo Zanoni +Reviewed-by: Rodrigo Vivi +Link: http://patchwork.freedesktop.org/patch/msgid/1483473860-17644-2-git-send-email-paulo.r.zanoni@intel.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a381c8e61b3 --- /dev/null +++ b/queue-4.9/drm-mga-remove-device_is_agp-callback.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-63-alexander.levin@verizon.com> + +From: Daniel Vetter + +[ 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 +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/20170125062657.19270-10-daniel.vetter@ffwll.ch +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + +-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 index 00000000000..4bfbec3a324 --- /dev/null +++ b/queue-4.9/drm-msm-adreno-move-function-declarations-to-header-file.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-81-alexander.levin@verizon.com> + +From: Baoyou Xie + +[ 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 +Reviewed-by: Arnd Bergmann +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/1477127865-9381-1-git-send-email-baoyou.xie@linaro.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a473376efc3 --- /dev/null +++ b/queue-4.9/firmware-qcom-scm-fix-interrupted-scm-calls.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-80-alexander.levin@verizon.com> + +From: Andy Gross + +[ 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 +Reviewed-by: Will Deacon +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++#include + #include + + .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 +-#include +- + /* + * 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 ++#include + /** + * 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 index 00000000000..2dce7c32e92 --- /dev/null +++ b/queue-4.9/hid-asus-add-i2c-touchpad-support.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-36-alexander.levin@verizon.com> + +From: Brendan McGrath + +[ 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 +Signed-off-by: Brendan McGrath +Signed-off-by: Victor Vlasenko +Signed-off-by: Frederik Wenigwieser +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + * Copyright (c) 2011 Jiri Kosina ++ * ++ * This module has been updated to add support for Asus i2c touchpad. ++ * ++ * Copyright (c) 2016 Brendan McGrath ++ * Copyright (c) 2016 Victor Vlasenko ++ * Copyright (c) 2016 Frederik Wenigwieser + */ + + /* +@@ -20,16 +26,287 @@ + * any later version. + */ + +-#include + #include + #include ++#include + + #include "hid-ids.h" + ++MODULE_AUTHOR("Yusuke Fujimaki "); ++MODULE_AUTHOR("Brendan McGrath "); ++MODULE_AUTHOR("Victor Vlasenko "); ++MODULE_AUTHOR("Frederik Wenigwieser "); ++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 index 00000000000..553ce26076e --- /dev/null +++ b/queue-4.9/hid-asus-fix-keyboard-support.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-37-alexander.levin@verizon.com> + +From: Brendan McGrath + +[ 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 +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 }, + { } diff --git a/queue-4.9/hid-i2c-hid-add-a-simple-quirk-to-fix-device-defects.patch b/queue-4.9/hid-i2c-hid-add-a-simple-quirk-to-fix-device-defects.patch index a06bca031ad..7fe32c355c8 100644 --- a/queue-4.9/hid-i2c-hid-add-a-simple-quirk-to-fix-device-defects.patch +++ b/queue-4.9/hid-i2c-hid-add-a-simple-quirk-to-fix-device-defects.patch @@ -19,7 +19,6 @@ device can be powered on afterwards. Signed-off-by: HungNien Chen Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina - Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- 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 index 00000000000..a4e93212d34 --- /dev/null +++ b/queue-4.9/hid-microsoft-add-surface-4-type-cover-pro-4-not-jp-versions.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-38-alexander.levin@verizon.com> + +From: Daniel Keller + +[ 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 +Signed-off-by: Daniel Keller +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..095153c952a --- /dev/null +++ b/queue-4.9/hid-multitouch-do-not-retrieve-all-reports-for-all-devices.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-14-alexander.levin@verizon.com> + +From: Benjamin Tissoires + +[ 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 +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..aef70fd3ea3 --- /dev/null +++ b/queue-4.9/hid-multitouch-enable-the-surface-3-type-cover-to-report-multitouch-data.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-13-alexander.levin@verizon.com> + +From: Benjamin Tissoires + +[ 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 +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c76e5c6dc11 --- /dev/null +++ b/queue-4.9/hid-multitouch-enable-the-surface-4-type-cover-pro-jp-to-report-multitouch-data.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-39-alexander.levin@verizon.com> + +From: Yuta Kobayashi + +[ 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 +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dc4c00bdeee --- /dev/null +++ b/queue-4.9/hid-sensor-hub-add-quirk-for-microchip-mm7150.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-12-alexander.levin@verizon.com> + +From: Benjamin Tissoires + +[ Upstream commit 5cc5084dd9afa2f9bf953b0217bdb1b7c2158be1 ] + +One more device requiring a quirk :/ + +Reported-by: Christian-Nils Boda +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d55320dafb6 --- /dev/null +++ b/queue-4.9/hid-sensor-hub-add-quirk-for-microsoft-surface-3.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-11-alexander.levin@verizon.com> + +From: Benjamin Tissoires + +[ Upstream commit da809197a919942ab6ee0d008c20a011872181b1 ] + +One more device requiring a quirk :/ + +[jkosina@suse.cz: update comment based on Bastien's remark] +Signed-off-by: Benjamin Tissoires +Tested-by: Bastien Nocera +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..1366778676f --- /dev/null +++ b/queue-4.9/hid-usbhid-add-quirk-for-mayflash-dragonrise-dolphinbar.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-43-alexander.levin@verizon.com> + +From: Marcel Hasler + +[ 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 +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cba53ce4564 --- /dev/null +++ b/queue-4.9/hid-usbhid-add-quirk-for-the-futaba-tosd-5711bb-vfd.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-42-alexander.levin@verizon.com> + +From: Alex Wood + +[ 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 +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3eadafd5ed9 --- /dev/null +++ b/queue-4.9/hid-wacom-don-t-apply-generic-settings-to-old-devices.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-78-alexander.levin@verizon.com> + +From: Ping Cheng + +[ 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 +Reviewed-by: Jason Gerecke +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..72603a2c3f3 --- /dev/null +++ b/queue-4.9/input-gpio_keys-add-support-for-gpio-descriptors.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-56-alexander.levin@verizon.com> + +From: Geert Uytterhoeven + +[ 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 +Reviewed-by: Linus Walleij +Tested-by: Mika Westerberg +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..b506f6a0f75 --- /dev/null +++ b/queue-4.9/mmc-sdhci-msm-enable-few-quirks.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-15-alexander.levin@verizon.com> + +From: Ritesh Harjani + +[ 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 +Signed-off-by: Ritesh Harjani +Acked-by: Adrian Hunter +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d096eeb3acc --- /dev/null +++ b/queue-4.9/mmc-sdhci-of-esdhc-remove-default-broken-cd-for-arm.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-85-alexander.levin@verizon.com> + +From: yangbo lu + +[ 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 +Acked-by: Adrian Hunter +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ba0fffcfe2c --- /dev/null +++ b/queue-4.9/net-mlx4_core-use-device-id-defines.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-8-alexander.levin@verizon.com> + +From: Bjorn Helgaas + +[ 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 +Acked-by: Tariq Toukan +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..0af4833b74d --- /dev/null +++ b/queue-4.9/nvme-simplify-stripe-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-40-alexander.levin@verizon.com> + +From: Keith Busch + +[ 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 +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cb56c225339 --- /dev/null +++ b/queue-4.9/pci-acpi-check-for-platform-specific-mcfg-quirks.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-23-alexander.levin@verizon.com> + +From: Tomasz Nowicki + +[ 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 +Signed-off-by: Dongdong Liu +Signed-off-by: Christopher Covington +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c7c1e8316d3 --- /dev/null +++ b/queue-4.9/pci-acpi-extend-pci_mcfg_lookup-to-return-ecam-config-accessors.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-22-alexander.levin@verizon.com> + +From: Tomasz Nowicki + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + /* 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 index 00000000000..1693c6c629e --- /dev/null +++ b/queue-4.9/pci-add-acs-quirk-for-intel-union-point.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-65-alexander.levin@verizon.com> + +From: Alex Williamson + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3ac71016cda --- /dev/null +++ b/queue-4.9/pci-add-acs-quirk-for-qualcomm-qdf2400-and-qdf2432.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-87-alexander.levin@verizon.com> + +From: Sinan Kaya + +[ 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 +Signed-off-by: Bjorn Helgaas +Reviewed-by: Alex Williamson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..9ef56070bba --- /dev/null +++ b/queue-4.9/pci-add-broadcom-northstar2-paxc-quirk-for-device-class-and-mpss.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-83-alexander.levin@verizon.com> + +From: Jon Mason + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..612ea735d58 --- /dev/null +++ b/queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass1.x-host-controller.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-28-alexander.levin@verizon.com> + +From: Tomasz Nowicki + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + ++#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 index 00000000000..3c5417e884c --- /dev/null +++ b/queue-4.9/pci-add-mcfg-quirks-for-cavium-thunderx-pass2.x-host-controller.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-27-alexander.levin@verizon.com> + +From: Tomasz Nowicki + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include ++#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 index 00000000000..d8d33e8fd18 --- /dev/null +++ b/queue-4.9/pci-add-mcfg-quirks-for-hisilicon-hip05-06-07-host-controllers.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-25-alexander.levin@verizon.com> + +From: Dongdong Liu + +[ 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 +Signed-off-by: Gabriele Paoloni +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include ++#include ++#include + #include ++#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 index 00000000000..63f0dd02699 --- /dev/null +++ b/queue-4.9/pci-add-mcfg-quirks-for-qualcomm-qdf2432-host-controller.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-24-alexander.levin@verizon.com> + +From: Christopher Covington + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c7b72d7ac40 --- /dev/null +++ b/queue-4.9/pci-add-mcfg-quirks-for-x-gene-host-controller.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-29-alexander.levin@verizon.com> + +From: Duc Dang + +[ 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 +Signed-off-by: Duc Dang +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 index 00000000000..9d7e56567e8 --- /dev/null +++ b/queue-4.9/pci-disable-msi-for-hisilicon-hip06-hip07-root-ports.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-84-alexander.levin@verizon.com> + +From: Dongdong Liu + +[ 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 +Signed-off-by: Bjorn Helgaas +Reviewed-by: Gabriele Paoloni +Reviewed-by: Zhou Wang +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d7a84eb982a --- /dev/null +++ b/queue-4.9/pci-expand-vpd-access-disabled-quirk-message.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-33-alexander.levin@verizon.com> + +From: Bjorn Helgaas + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a380b64cbf3 --- /dev/null +++ b/queue-4.9/pci-explain-arm64-acpi-mcfg-quirk-kconfig-and-build-strategy.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-30-alexander.levin@verizon.com> + +From: Bjorn Helgaas + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..0a2f779cdaa --- /dev/null +++ b/queue-4.9/pci-sort-the-list-of-devices-with-d3-delay-quirk-by-id.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-86-alexander.levin@verizon.com> + +From: Andy Shevchenko + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..e6513f1b16b --- /dev/null +++ b/queue-4.9/pci-thunder-pem-factor-out-resource-lookup.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-26-alexander.levin@verizon.com> + +From: Bjorn Helgaas + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..8fa42e10570 --- /dev/null +++ b/queue-4.9/pci-xgene-fix-double-free-on-init-error.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-66-alexander.levin@verizon.com> + +From: Dan Carpenter + +[ 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 +Signed-off-by: Dan Carpenter +Signed-off-by: Bjorn Helgaas +Acked-by: Tanmay Inamdar +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dca69401364 --- /dev/null +++ b/queue-4.9/platform-x86-acer-wmi-only-supports-amw0_guid1-on-acer-family.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-35-alexander.levin@verizon.com> + +From: "Lee, Chun-Yi" + +[ 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 +Signed-off-by: Lee, Chun-Yi +Signed-off-by: Darren Hart +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..691decfe0e8 --- /dev/null +++ b/queue-4.9/platform-x86-asus-wmi-detect-quirk_no_rfkill-from-the-dsdt.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-92-alexander.levin@verizon.com> + +From: João Paulo Rechi Vita + +[ 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 +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4e5f5e39f6f --- /dev/null +++ b/queue-4.9/platform-x86-asus-wmi-set-specified-xusb2pr-value-for-x550lb.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-91-alexander.levin@verizon.com> + +From: Kai-Chuan Hsieh + +[ 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 +Acked-by: Corentin Chary +Reviewed-by: Andy Shevchenko +[andy: resolve merge conflict in asus-wmi.h] +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2a3f443815e --- /dev/null +++ b/queue-4.9/rx51-broken-build.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-67-alexander.levin@verizon.com> + +From: Sean Young + +[ 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 +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5ad4acb2a63 --- /dev/null +++ b/queue-4.9/sata-ahci-da850-implement-a-workaround-for-the-softreset-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-68-alexander.levin@verizon.com> + +From: Bartosz Golaszewski + +[ 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 +Acked-by: Tejun Heo +Signed-off-by: Sekhar Nori +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a853d9f6047 --- /dev/null +++ b/queue-4.9/scsi-ufs-add-quirk-to-increase-host-pa_saveconfigtime.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-31-alexander.levin@verizon.com> + +From: Subhash Jadavani + +[ 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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ad090609bd0 --- /dev/null +++ b/queue-4.9/scsi-ufs-ensure-that-host-pa_tactivate-is-higher-than-device.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-16-alexander.levin@verizon.com> + +From: Subhash Jadavani + +[ 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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2cf1f1b60a6 --- /dev/null +++ b/queue-4.9/scsi-ufs-introduce-a-new-ufshcd_statea-ufshcd_state_eh_scheduled.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-49-alexander.levin@verizon.com> + +From: Zang Leigang + +[ 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 +Reviewed-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..fa9f05f5fbd --- /dev/null +++ b/queue-4.9/scsi-ufs-introduce-ufshcd_quirk_prdt_byte_gran-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-10-alexander.levin@verizon.com> + +From: Kiwoong Kim + +[ 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 +Reviewed-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5f963f8db68 --- /dev/null +++ b/queue-4.9/scsi-ufs-issue-link-starup-2-times-if-device-isn-t-active.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-50-alexander.levin@verizon.com> + +From: "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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..de4db827728 --- /dev/null +++ b/queue-4.9/scsi-ufs-refactor-device-descriptor-reading.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-52-alexander.levin@verizon.com> + +From: Tomas Winkler + +[ 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 +Reviewed-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5174d1a097c --- /dev/null +++ b/queue-4.9/serial-8250_omap-add-omap_dma_tx_kick-quirk-for-am437x.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-54-alexander.levin@verizon.com> + +From: Vignesh R + +[ 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 +Acked-by: Tony Lindgren +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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. diff --git a/queue-4.9/series b/queue-4.9/series index 7cf475959e6..e431ee0b170 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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 index 00000000000..607481a893a --- /dev/null +++ b/queue-4.9/svcauth_gss-close-connection-when-dropping-an-incoming-message.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-17-alexander.levin@verizon.com> + +From: Chuck Lever + +[ 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 +Signed-off-by: J. Bruce Fields +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..77a22d2ca62 --- /dev/null +++ b/queue-4.9/tools-power-turbostat-decode-baytrail-cc6-and-mc6-demotion-configuration.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-93-alexander.levin@verizon.com> + +From: Len Brown + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ca86e0c533e --- /dev/null +++ b/queue-4.9/tools-power-turbostat-dump-atom-p-states-correctly.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-94-alexander.levin@verizon.com> + +From: Len Brown + +[ 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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cee7301887c --- /dev/null +++ b/queue-4.9/usb-chipidea-msm-rely-on-core-to-override-ahbburst.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-53-alexander.levin@verizon.com> + +From: Stephen Boyd + +[ 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 +Cc: Greg Kroah-Hartman +Signed-off-by: Stephen Boyd +Signed-off-by: Peter Chen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..0cca6301469 --- /dev/null +++ b/queue-4.9/usb-dwc3-host-pass-quirk-broken-port-ped-property-for-known-broken-revisions.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-62-alexander.levin@verizon.com> + +From: Felipe Balbi + +[ 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 +Signed-off-by: Felipe Balbi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..64037d1613c --- /dev/null +++ b/queue-4.9/usb-host-xhci-plat-enable-broken_ped-quirk-if-platform-requested.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-61-alexander.levin@verizon.com> + +From: Felipe Balbi + +[ 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 +Signed-off-by: Roger Quadros +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ca7af0da366 --- /dev/null +++ b/queue-4.9/usb-musb-da8xx-fix-host-mode-suspend.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-76-alexander.levin@verizon.com> + +From: Alexandre Bailon + +[ 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 +Signed-off-by: Bin Liu +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..fd07b2bc4a2 --- /dev/null +++ b/queue-4.9/usb-storage-add-ignore-residue-quirk-for-initio-inic-3619.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-97-alexander.levin@verizon.com> + +From: Tobias Jakobi + +[ 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 +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++ * 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 */ + 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 index 00000000000..9d62dac5bbb --- /dev/null +++ b/queue-4.9/usb-xhci-add-quirk-flag-for-broken-ped-bits.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-60-alexander.levin@verizon.com> + +From: Felipe Balbi + +[ 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 +Signed-off-by: Roger Quadros +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2b379734930 --- /dev/null +++ b/queue-4.9/watchdog-s3c2410-fix-infinite-interrupt-in-soft-mode.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-90-alexander.levin@verizon.com> + +From: Krzysztof Kozlowski + +[ 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 +Reviewed-by: Guenter Roeck +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ba2dd559d7e --- /dev/null +++ b/queue-4.9/x86-intel_idle-add-cpu-model-0x4a-atom-z34xx-series.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-18-alexander.levin@verizon.com> + +From: Andy Shevchenko + +[ 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 +Signed-off-by: Len Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..9c6b582ba84 --- /dev/null +++ b/queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-reboot-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-95-alexander.levin@verizon.com> + +From: Matjaz Hegedic + +[ 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 +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..74ac2e24368 --- /dev/null +++ b/queue-4.9/x86-reboot-quirks-add-asus-eeebook-x205ta-w-reboot-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-96-alexander.levin@verizon.com> + +From: Matjaz Hegedic + +[ 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 +Link: http://lkml.kernel.org/r/1488737804-20681-1-git-send-email-matjaz.hegedic@gmail.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..76eca438c07 --- /dev/null +++ b/queue-4.9/x86-reboot-quirks-fix-typo-in-asus-eeebook-x205ta-reboot-quirk.patch @@ -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" +Cc: "stable@vger.kernel.org" +Message-ID: <20170404193158.19041-98-alexander.levin@verizon.com> + +From: Matjaz Hegedic + +[ 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 +Link: http://lkml.kernel.org/r/1489064417-7445-1-git-send-email-matjaz.hegedic@gmail.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 */