Merge 4.9.22 into android-4.9
Changes in 4.9.22: ppdev: check before attaching port ppdev: fix registering same device name drm/vmwgfx: Type-check lookups of fence objects drm/vmwgfx: NULL pointer dereference in vmw_surface_define_ioctl() drm/vmwgfx: avoid calling vzalloc with a 0 size in vmw_get_cap_3d_ioctl() drm/ttm, drm/vmwgfx: Relax permission checking when opening surfaces drm/vmwgfx: Remove getparam error message drm/vmwgfx: fix integer overflow in vmw_surface_define_ioctl() sysfs: be careful of error returns from ops->show() staging: android: ashmem: lseek failed due to no FMODE_LSEEK. arm/arm64: KVM: Take mmap_sem in stage2_unmap_vm arm/arm64: KVM: Take mmap_sem in kvm_arch_prepare_memory_region kvm: arm/arm64: Fix locking for kvm_free_stage2_pgd iio: bmg160: reset chip when probing arm64: mm: unaligned access by user-land should be received as SIGBUS cfg80211: check rdev resume callback only for registered wiphy Reset TreeId to zero on SMB2 TREE_CONNECT mm/page_alloc.c: fix print order in show_free_areas() ptrace: fix PTRACE_LISTEN race corrupting task->state dm verity fec: limit error correction recursion dm verity fec: fix bufio leaks ACPI / gpio: do not fall back to parsing _CRS when we get a deferral Kbuild: use cc-disable-warning consistently for maybe-uninitialized orangefs: move features validation to fix filesystem hang xfs: Honor FALLOC_FL_KEEP_SIZE when punching ends of files ring-buffer: Fix return value check in test_ringbuffer() mac80211: unconditionally start new netdev queues with iTXQ support brcmfmac: use local iftype avoiding use-after-free of virtual interface metag/usercopy: Drop unused macros metag/usercopy: Fix alignment error checking metag/usercopy: Add early abort to copy_to_user metag/usercopy: Zero rest of buffer from copy_from_user metag/usercopy: Set flags before ADDZ metag/usercopy: Fix src fixup in from user rapf loops metag/usercopy: Add missing fixups powerpc: Disable HFSCR[TM] if TM is not supported powerpc/mm: Add missing global TLB invalidate if cxl is active powerpc/64: Fix flush_(d|i)cache_range() called from modules powerpc: Don't try to fix up misaligned load-with-reservation instructions powerpc/crypto/crc32c-vpmsum: Fix missing preempt_disable() dm raid: fix NULL pointer dereference for raid1 without bitmap nios2: reserve boot memory for device tree xtensa: make __pa work with uncached KSEG addresses s390/decompressor: fix initrd corruption caused by bss clear s390/uaccess: get_user() should zero on failure (again) MIPS: Force o32 fp64 support on 32bit MIPS64r6 kernels MIPS: ralink: Fix typos in rt3883 pinctrl MIPS: End spinlocks with .insn MIPS: Lantiq: fix missing xbar kernel panic MIPS: Check TLB before handle_ri_rdhwr() for Loongson-3 MIPS: Add MIPS_CPU_FTLB for Loongson-3A R2 MIPS: Flush wrong invalid FTLB entry for huge page MIPS: c-r4k: Fix Loongson-3's vcache/scache waysize calculation Documentation: stable-kernel-rules: fix stable-tag format mm/mempolicy.c: fix error handling in set_mempolicy and mbind. random: use chacha20 for get_random_int/long drm/sun4i: tcon: Move SoC specific quirks to a DT matched data structure drm/sun4i: Add compatible strings for A31/A31s display pipelines drm/sun4i: Add compatible string for A31/A31s TCON (timing controller) clk: lpc32xx: add a quirk for PWM and MS clock dividers HID: usbhid: Add quirks for Mayflash/Dragonrise GameCube and PS3 adapters HID: i2c-hid: add a simple quirk to fix device defects usb: dwc3: gadget: delay unmap of bounced requests ASoC: Intel: bytct_rt5640: change default capture settings arm64: dts: hisi: fix hip06 sas am-max-trans quirk net/mlx4_core: Use device ID defines clocksource/drivers/arm_arch_timer: Don't assume clock runs in suspend scsi: ufs: introduce UFSHCD_QUIRK_PRDT_BYTE_GRAN quirk HID: sensor-hub add quirk for Microsoft Surface 3 HID: sensor-hub: add quirk for Microchip MM7150 HID: multitouch: enable the Surface 3 Type Cover to report multitouch data HID: multitouch: do not retrieve all reports for all devices mmc: sdhci-msm: Enable few quirks scsi: ufs: ensure that host pa_tactivate is higher than device svcauth_gss: Close connection when dropping an incoming message x86/intel_idle: Add CPU model 0x4a (Atom Z34xx series) arm64: PCI: Manage controller-specific data on per-controller basis arm64: PCI: Add local struct device pointers PCI: thunder-pem: Factor out resource lookup scsi: ufs: add quirk to increase host PA_SaveConfigTime ALSA: usb-audio: add implicit fb quirk for Axe-Fx II PCI: Expand "VPD access disabled" quirk message ALSA: usb-audio: Add native DSD support for TEAC 501/503 DAC platform/x86: acer-wmi: Only supports AMW0_GUID1 on acer family nvme: simplify stripe quirk ACPI / sysfs: Provide quirk mechanism to prevent GPE flooding HID: usbhid: Add quirk for the Futaba TOSD-5711BB VFD HID: usbhid: Add quirk for Mayflash/Dragonrise DolphinBar. drm/edid: constify edid quirk list drm/i915: fix INTEL_BDW_IDS definition drm/i915: more .is_mobile cleanups for BDW drm/i915: actually drive the BDW reserved IDs ASoC: Intel: bytcr_rt5640: quirks for Insyde devices scsi: ufs: introduce a new ufshcd_statea UFSHCD_STATE_EH_SCHEDULED scsi: ufs: issue link starup 2 times if device isn't active usb: chipidea: msm: Rely on core to override AHBBURST serial: 8250_omap: Add OMAP_DMA_TX_KICK quirk for AM437x Input: gpio_keys - add support for GPIO descriptors ARM: davinci: PM: support da8xx DT platforms usb: xhci: add quirk flag for broken PED bits usb: host: xhci-plat: enable BROKEN_PED quirk if platform requested usb: dwc3: host: pass quirk-broken-port-ped property for known broken revisions drm/mga: remove device_is_agp callback ARM: dts: STiH407-family: set snps,dis_u3_susphy_quirk PCI: Add ACS quirk for Intel Union Point sata: ahci-da850: implement a workaround for the softreset quirk ACPI / button: Change default behavior to lid_init_state=open ASoC: rt5670: Add missing 10EC5072 ACPI ID ASoC: codecs: rt5670: add quirk for Lenovo Thinkpad 10 ASoC: Intel: Baytrail: add quirk for Lenovo Thinkpad 10 ASoC: Intel: cht_bsw_rt5645: harden ACPI device detection ASoC: Intel: cht_bsw_rt5645: add Baytrail MCLK support ACPI: save NVS memory for Lenovo G50-45 ASoC: sun4i-i2s: Add quirks to handle a31 compatible HID: wacom: don't apply generic settings to old devices arm: kernel: Add SMC structure parameter firmware: qcom: scm: Fix interrupted SCM calls drm/msm/adreno: move function declarations to header file ARM: smccc: Update HVC comment to describe new quirk parameter PCI: Add Broadcom Northstar2 PAXC quirk for device class and MPSS PCI: Disable MSI for HiSilicon Hip06/Hip07 Root Ports mmc: sdhci-of-esdhc: remove default broken-cd for ARM PCI: Sort the list of devices with D3 delay quirk by ID PCI: Add ACS quirk for Qualcomm QDF2400 and QDF2432 watchdog: s3c2410: Fix infinite interrupt in soft mode platform/x86: asus-wmi: Set specified XUSB2PR value for X550LB platform/x86: asus-wmi: Detect quirk_no_rfkill from the DSDT x86/reboot/quirks: Add ASUS EeeBook X205TA reboot quirk x86/reboot/quirks: Add ASUS EeeBook X205TA/W reboot quirk usb-storage: Add ignore-residue quirk for Initio INIC-3619 x86/reboot/quirks: Fix typo in ASUS EeeBook X205TA reboot quirk Linux 4.9.22 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ The TCON acts as a timing controller for RGB, LVDS and TV interfaces.
|
||||
Required properties:
|
||||
- compatible: value must be either:
|
||||
* allwinner,sun5i-a13-tcon
|
||||
* allwinner,sun6i-a31-tcon
|
||||
* allwinner,sun6i-a31s-tcon
|
||||
* allwinner,sun8i-a33-tcon
|
||||
- reg: base address and size of memory-mapped region
|
||||
- interrupts: interrupt associated to this IP
|
||||
@@ -50,7 +52,7 @@ Required properties:
|
||||
second the block connected to the TCON channel 1 (usually the TV
|
||||
encoder)
|
||||
|
||||
On the A13, there is one more clock required:
|
||||
On SoCs other than the A33, there is one more clock required:
|
||||
- 'tcon-ch1': The clock driving the TCON channel 1
|
||||
|
||||
DRC
|
||||
@@ -87,6 +89,7 @@ system.
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun5i-a13-display-backend
|
||||
* allwinner,sun6i-a31-display-backend
|
||||
* allwinner,sun8i-a33-display-backend
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- clocks: phandles to the clocks feeding the frontend and backend
|
||||
@@ -117,6 +120,7 @@ deinterlacing and color space conversion.
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun5i-a13-display-frontend
|
||||
* allwinner,sun6i-a31-display-frontend
|
||||
* allwinner,sun8i-a33-display-frontend
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- interrupts: interrupt associated to this IP
|
||||
@@ -142,6 +146,8 @@ extra node.
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun5i-a13-display-engine
|
||||
* allwinner,sun6i-a31-display-engine
|
||||
* allwinner,sun6i-a31s-display-engine
|
||||
* allwinner,sun8i-a33-display-engine
|
||||
|
||||
- allwinner,pipelines: list of phandle to the display engine
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -306,6 +306,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
use by PCI
|
||||
Format: <irq>,<irq>...
|
||||
|
||||
acpi_mask_gpe= [HW,ACPI]
|
||||
Due to the existence of _Lxx/_Exx, some GPEs triggered
|
||||
by unsupported hardware/firmware features can result in
|
||||
GPE floodings that cannot be automatically disabled by
|
||||
the GPE dispatcher.
|
||||
This facility can be used to prevent such uncontrolled
|
||||
GPE floodings.
|
||||
Format: <int>
|
||||
Support masking of GPEs numbered from 0x00 to 0x7f.
|
||||
|
||||
acpi_no_auto_serialize [HW,ACPI]
|
||||
Disable auto-serialization of AML methods
|
||||
AML control methods that contain the opcodes to create
|
||||
|
||||
@@ -124,7 +124,7 @@ specified in the following format in the sign-off area:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
Cc: <stable@vger.kernel.org> # 3.3.x-
|
||||
Cc: <stable@vger.kernel.org> # 3.3.x
|
||||
|
||||
The tag has the meaning of:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 21
|
||||
SUBLEVEL = 22
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
@@ -370,7 +370,7 @@ LDFLAGS_MODULE =
|
||||
CFLAGS_KERNEL =
|
||||
AFLAGS_KERNEL =
|
||||
LDFLAGS_vmlinux =
|
||||
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im -Wno-maybe-uninitialized
|
||||
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage -fno-tree-loop-im $(call cc-disable-warning,maybe-uninitialized,)
|
||||
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
|
||||
|
||||
|
||||
|
||||
@@ -680,6 +680,7 @@
|
||||
phy-names = "usb2-phy", "usb3-phy";
|
||||
phys = <&usb2_picophy0>,
|
||||
<&phy_port2 PHY_TYPE_USB3>;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+20
-3
@@ -292,11 +292,18 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
|
||||
phys_addr_t addr = start, end = start + size;
|
||||
phys_addr_t next;
|
||||
|
||||
assert_spin_locked(&kvm->mmu_lock);
|
||||
pgd = kvm->arch.pgd + stage2_pgd_index(addr);
|
||||
do {
|
||||
next = stage2_pgd_addr_end(addr, end);
|
||||
if (!stage2_pgd_none(*pgd))
|
||||
unmap_stage2_puds(kvm, pgd, addr, next);
|
||||
/*
|
||||
* If the range is too large, release the kvm->mmu_lock
|
||||
* to prevent starvation and lockup detector warnings.
|
||||
*/
|
||||
if (next != end)
|
||||
cond_resched_lock(&kvm->mmu_lock);
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
@@ -803,6 +810,7 @@ void stage2_unmap_vm(struct kvm *kvm)
|
||||
int idx;
|
||||
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
spin_lock(&kvm->mmu_lock);
|
||||
|
||||
slots = kvm_memslots(kvm);
|
||||
@@ -810,6 +818,7 @@ void stage2_unmap_vm(struct kvm *kvm)
|
||||
stage2_unmap_memslot(kvm, memslot);
|
||||
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
}
|
||||
|
||||
@@ -829,7 +838,10 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
|
||||
if (kvm->arch.pgd == NULL)
|
||||
return;
|
||||
|
||||
spin_lock(&kvm->mmu_lock);
|
||||
unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
|
||||
/* Free the HW pgd, one page at a time */
|
||||
free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
|
||||
kvm->arch.pgd = NULL;
|
||||
@@ -1804,6 +1816,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
(KVM_PHYS_SIZE >> PAGE_SHIFT))
|
||||
return -EFAULT;
|
||||
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
/*
|
||||
* A memory region could potentially cover multiple VMAs, and any holes
|
||||
* between them, so iterate over all of them to find out if we can map
|
||||
@@ -1847,8 +1860,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
pa += vm_start - vma->vm_start;
|
||||
|
||||
/* IO region dirty page logging not allowed */
|
||||
if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES)
|
||||
return -EINVAL;
|
||||
if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = kvm_phys_addr_ioremap(kvm, gpa, pa,
|
||||
vm_end - vm_start,
|
||||
@@ -1860,7 +1875,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
} while (hva < reg_end);
|
||||
|
||||
if (change == KVM_MR_FLAGS_ONLY)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
spin_lock(&kvm->mmu_lock);
|
||||
if (ret)
|
||||
@@ -1868,6 +1883,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
else
|
||||
stage2_flush_memslot(kvm, memslot);
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
out:
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
|
||||
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 = {
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -143,8 +143,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));
|
||||
|
||||
+15
-13
@@ -121,6 +121,7 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|
||||
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_pci_root *root)
|
||||
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_pci_root *root)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -159,33 +158,36 @@ static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
.macro SMCCC instr
|
||||
@@ -20,24 +21,32 @@
|
||||
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
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
+24
-18
@@ -41,7 +41,20 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
static const char *fault_name(unsigned int esr);
|
||||
struct fault_info {
|
||||
int (*fn)(unsigned long addr, unsigned int esr,
|
||||
struct pt_regs *regs);
|
||||
int sig;
|
||||
int code;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct fault_info fault_info[];
|
||||
|
||||
static inline const struct fault_info *esr_to_fault_info(unsigned int esr)
|
||||
{
|
||||
return fault_info + (esr & 63);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr)
|
||||
@@ -196,10 +209,12 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct siginfo si;
|
||||
const struct fault_info *inf;
|
||||
|
||||
if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) {
|
||||
inf = esr_to_fault_info(esr);
|
||||
pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
|
||||
tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
|
||||
tsk->comm, task_pid_nr(tsk), inf->name, sig,
|
||||
addr, esr);
|
||||
show_pte(tsk->mm, addr);
|
||||
show_regs(regs);
|
||||
@@ -218,14 +233,16 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->active_mm;
|
||||
const struct fault_info *inf;
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we have no context to
|
||||
* handle this fault with.
|
||||
*/
|
||||
if (user_mode(regs))
|
||||
__do_user_fault(tsk, addr, esr, SIGSEGV, SEGV_MAPERR, regs);
|
||||
else
|
||||
if (user_mode(regs)) {
|
||||
inf = esr_to_fault_info(esr);
|
||||
__do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs);
|
||||
} else
|
||||
__do_kernel_fault(mm, addr, esr, regs);
|
||||
}
|
||||
|
||||
@@ -487,12 +504,7 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct fault_info {
|
||||
int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
|
||||
int sig;
|
||||
int code;
|
||||
const char *name;
|
||||
} fault_info[] = {
|
||||
static const struct fault_info fault_info[] = {
|
||||
{ do_bad, SIGBUS, 0, "ttbr address size fault" },
|
||||
{ do_bad, SIGBUS, 0, "level 1 address size fault" },
|
||||
{ do_bad, SIGBUS, 0, "level 2 address size fault" },
|
||||
@@ -559,19 +571,13 @@ static const struct fault_info {
|
||||
{ do_bad, SIGBUS, 0, "unknown 63" },
|
||||
};
|
||||
|
||||
static const char *fault_name(unsigned int esr)
|
||||
{
|
||||
const struct fault_info *inf = fault_info + (esr & 63);
|
||||
return inf->name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatch a data abort to the relevant handler.
|
||||
*/
|
||||
asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
const struct fault_info *inf = fault_info + (esr & 63);
|
||||
const struct fault_info *inf = esr_to_fault_info(esr);
|
||||
struct siginfo info;
|
||||
|
||||
if (!inf->fn(addr, esr, regs))
|
||||
|
||||
@@ -197,20 +197,21 @@ extern long __must_check strnlen_user(const char __user *src, long count);
|
||||
|
||||
#define strlen_user(str) strnlen_user(str, 32767)
|
||||
|
||||
extern unsigned long __must_check __copy_user_zeroing(void *to,
|
||||
const void __user *from,
|
||||
unsigned long n);
|
||||
extern unsigned long raw_copy_from_user(void *to, const void __user *from,
|
||||
unsigned long n);
|
||||
|
||||
static inline unsigned long
|
||||
copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
unsigned long res = n;
|
||||
if (likely(access_ok(VERIFY_READ, from, n)))
|
||||
return __copy_user_zeroing(to, from, n);
|
||||
memset(to, 0, n);
|
||||
return n;
|
||||
res = raw_copy_from_user(to, from, n);
|
||||
if (unlikely(res))
|
||||
memset(to + (n - res), 0, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
#define __copy_from_user(to, from, n) __copy_user_zeroing(to, from, n)
|
||||
#define __copy_from_user(to, from, n) raw_copy_from_user(to, from, n)
|
||||
#define __copy_from_user_inatomic __copy_from_user
|
||||
|
||||
extern unsigned long __must_check __copy_user(void __user *to,
|
||||
|
||||
+126
-198
@@ -29,7 +29,6 @@
|
||||
COPY \
|
||||
"1:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" MOV D1Ar1,#0\n" \
|
||||
FIXUP \
|
||||
" MOVT D1Ar1,#HI(1b)\n" \
|
||||
" JUMP D1Ar1,#LO(1b)\n" \
|
||||
@@ -260,27 +259,31 @@
|
||||
"MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"22:\n" \
|
||||
"MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #32\n" \
|
||||
"23:\n" \
|
||||
"MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"SUB %3, %3, #32\n" \
|
||||
"24:\n" \
|
||||
"MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"25:\n" \
|
||||
"MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"26:\n" \
|
||||
"SUB %3, %3, #32\n" \
|
||||
"DCACHE [%1+#-64], D0Ar6\n" \
|
||||
"BR $Lloop"id"\n" \
|
||||
\
|
||||
"MOV RAPF, %1\n" \
|
||||
"25:\n" \
|
||||
"MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"26:\n" \
|
||||
"MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #32\n" \
|
||||
"27:\n" \
|
||||
"MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"28:\n" \
|
||||
"MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %0, %0, #8\n" \
|
||||
"29:\n" \
|
||||
"SUB %3, %3, #32\n" \
|
||||
"30:\n" \
|
||||
"MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"31:\n" \
|
||||
"MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"32:\n" \
|
||||
"SUB %0, %0, #8\n" \
|
||||
"33:\n" \
|
||||
"SETL [%0++], D0.7, D1.7\n" \
|
||||
"SUB %3, %3, #32\n" \
|
||||
"1:" \
|
||||
@@ -312,11 +315,15 @@
|
||||
" .long 26b,3b\n" \
|
||||
" .long 27b,3b\n" \
|
||||
" .long 28b,3b\n" \
|
||||
" .long 29b,4b\n" \
|
||||
" .long 29b,3b\n" \
|
||||
" .long 30b,3b\n" \
|
||||
" .long 31b,3b\n" \
|
||||
" .long 32b,3b\n" \
|
||||
" .long 33b,4b\n" \
|
||||
" .previous\n" \
|
||||
: "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \
|
||||
: "0" (to), "1" (from), "2" (ret), "3" (n) \
|
||||
: "D1Ar1", "D0Ar2", "memory")
|
||||
: "D1Ar1", "D0Ar2", "cc", "memory")
|
||||
|
||||
/* rewind 'to' and 'from' pointers when a fault occurs
|
||||
*
|
||||
@@ -342,7 +349,7 @@
|
||||
#define __asm_copy_to_user_64bit_rapf_loop(to, from, ret, n, id)\
|
||||
__asm_copy_user_64bit_rapf_loop(to, from, ret, n, id, \
|
||||
"LSR D0Ar2, D0Ar2, #8\n" \
|
||||
"AND D0Ar2, D0Ar2, #0x7\n" \
|
||||
"ANDS D0Ar2, D0Ar2, #0x7\n" \
|
||||
"ADDZ D0Ar2, D0Ar2, #4\n" \
|
||||
"SUB D0Ar2, D0Ar2, #1\n" \
|
||||
"MOV D1Ar1, #4\n" \
|
||||
@@ -403,47 +410,55 @@
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"22:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"23:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"24:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"25:\n" \
|
||||
"24:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"26:\n" \
|
||||
"25:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"26:\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"27:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"28:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"29:\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"30:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"31:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"32:\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"DCACHE [%1+#-64], D0Ar6\n" \
|
||||
"BR $Lloop"id"\n" \
|
||||
\
|
||||
"MOV RAPF, %1\n" \
|
||||
"29:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"30:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"31:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"32:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"33:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"34:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"35:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"36:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"SUB %0, %0, #4\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"37:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"38:\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"39:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"40:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"41:\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"42:\n" \
|
||||
"MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \
|
||||
"43:\n" \
|
||||
"MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \
|
||||
"44:\n" \
|
||||
"SUB %0, %0, #4\n" \
|
||||
"45:\n" \
|
||||
"SETD [%0++], D0.7\n" \
|
||||
"SUB %3, %3, #16\n" \
|
||||
"1:" \
|
||||
@@ -483,11 +498,19 @@
|
||||
" .long 34b,3b\n" \
|
||||
" .long 35b,3b\n" \
|
||||
" .long 36b,3b\n" \
|
||||
" .long 37b,4b\n" \
|
||||
" .long 37b,3b\n" \
|
||||
" .long 38b,3b\n" \
|
||||
" .long 39b,3b\n" \
|
||||
" .long 40b,3b\n" \
|
||||
" .long 41b,3b\n" \
|
||||
" .long 42b,3b\n" \
|
||||
" .long 43b,3b\n" \
|
||||
" .long 44b,3b\n" \
|
||||
" .long 45b,4b\n" \
|
||||
" .previous\n" \
|
||||
: "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \
|
||||
: "0" (to), "1" (from), "2" (ret), "3" (n) \
|
||||
: "D1Ar1", "D0Ar2", "memory")
|
||||
: "D1Ar1", "D0Ar2", "cc", "memory")
|
||||
|
||||
/* rewind 'to' and 'from' pointers when a fault occurs
|
||||
*
|
||||
@@ -513,7 +536,7 @@
|
||||
#define __asm_copy_to_user_32bit_rapf_loop(to, from, ret, n, id)\
|
||||
__asm_copy_user_32bit_rapf_loop(to, from, ret, n, id, \
|
||||
"LSR D0Ar2, D0Ar2, #8\n" \
|
||||
"AND D0Ar2, D0Ar2, #0x7\n" \
|
||||
"ANDS D0Ar2, D0Ar2, #0x7\n" \
|
||||
"ADDZ D0Ar2, D0Ar2, #4\n" \
|
||||
"SUB D0Ar2, D0Ar2, #1\n" \
|
||||
"MOV D1Ar1, #4\n" \
|
||||
@@ -538,23 +561,31 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
|
||||
if ((unsigned long) src & 1) {
|
||||
__asm_copy_to_user_1(dst, src, retn);
|
||||
n--;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
if ((unsigned long) dst & 1) {
|
||||
/* Worst case - byte copy */
|
||||
while (n > 0) {
|
||||
__asm_copy_to_user_1(dst, src, retn);
|
||||
n--;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
if (((unsigned long) src & 2) && n >= 2) {
|
||||
__asm_copy_to_user_2(dst, src, retn);
|
||||
n -= 2;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
if ((unsigned long) dst & 2) {
|
||||
/* Second worst case - word copy */
|
||||
while (n >= 2) {
|
||||
__asm_copy_to_user_2(dst, src, retn);
|
||||
n -= 2;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,6 +600,8 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
|
||||
while (n >= 8) {
|
||||
__asm_copy_to_user_8x64(dst, src, retn);
|
||||
n -= 8;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
if (n >= RAPF_MIN_BUF_SIZE) {
|
||||
@@ -581,6 +614,8 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
|
||||
while (n >= 8) {
|
||||
__asm_copy_to_user_8x64(dst, src, retn);
|
||||
n -= 8;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -588,11 +623,15 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
|
||||
while (n >= 16) {
|
||||
__asm_copy_to_user_16(dst, src, retn);
|
||||
n -= 16;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
|
||||
while (n >= 4) {
|
||||
__asm_copy_to_user_4(dst, src, retn);
|
||||
n -= 4;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
|
||||
switch (n) {
|
||||
@@ -609,6 +648,10 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here, retn correctly reflects the number of failing
|
||||
* bytes.
|
||||
*/
|
||||
return retn;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_user);
|
||||
@@ -617,16 +660,14 @@ EXPORT_SYMBOL(__copy_user);
|
||||
__asm_copy_user_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"2: SETB [%0++],D1Ar1\n", \
|
||||
"3: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
"3: ADD %2,%2,#1\n", \
|
||||
" .long 2b,3b\n")
|
||||
|
||||
#define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_user_cont(to, from, ret, \
|
||||
" GETW D1Ar1,[%1++]\n" \
|
||||
"2: SETW [%0++],D1Ar1\n" COPY, \
|
||||
"3: ADD %2,%2,#2\n" \
|
||||
" SETW [%0++],D1Ar1\n" FIXUP, \
|
||||
"3: ADD %2,%2,#2\n" FIXUP, \
|
||||
" .long 2b,3b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_2(to, from, ret) \
|
||||
@@ -636,145 +677,26 @@ EXPORT_SYMBOL(__copy_user);
|
||||
__asm_copy_from_user_2x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"4: SETB [%0++],D1Ar1\n", \
|
||||
"5: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
"5: ADD %2,%2,#1\n", \
|
||||
" .long 4b,5b\n")
|
||||
|
||||
#define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_user_cont(to, from, ret, \
|
||||
" GETD D1Ar1,[%1++]\n" \
|
||||
"2: SETD [%0++],D1Ar1\n" COPY, \
|
||||
"3: ADD %2,%2,#4\n" \
|
||||
" SETD [%0++],D1Ar1\n" FIXUP, \
|
||||
"3: ADD %2,%2,#4\n" FIXUP, \
|
||||
" .long 2b,3b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_4(to, from, ret) \
|
||||
__asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_5(to, from, ret) \
|
||||
__asm_copy_from_user_4x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"4: SETB [%0++],D1Ar1\n", \
|
||||
"5: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
" .long 4b,5b\n")
|
||||
|
||||
#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_from_user_4x_cont(to, from, ret, \
|
||||
" GETW D1Ar1,[%1++]\n" \
|
||||
"4: SETW [%0++],D1Ar1\n" COPY, \
|
||||
"5: ADD %2,%2,#2\n" \
|
||||
" SETW [%0++],D1Ar1\n" FIXUP, \
|
||||
" .long 4b,5b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_6(to, from, ret) \
|
||||
__asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_7(to, from, ret) \
|
||||
__asm_copy_from_user_6x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"6: SETB [%0++],D1Ar1\n", \
|
||||
"7: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
" .long 6b,7b\n")
|
||||
|
||||
#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_from_user_4x_cont(to, from, ret, \
|
||||
" GETD D1Ar1,[%1++]\n" \
|
||||
"4: SETD [%0++],D1Ar1\n" COPY, \
|
||||
"5: ADD %2,%2,#4\n" \
|
||||
" SETD [%0++],D1Ar1\n" FIXUP, \
|
||||
" .long 4b,5b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_8(to, from, ret) \
|
||||
__asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_9(to, from, ret) \
|
||||
__asm_copy_from_user_8x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"6: SETB [%0++],D1Ar1\n", \
|
||||
"7: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
" .long 6b,7b\n")
|
||||
|
||||
#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_from_user_8x_cont(to, from, ret, \
|
||||
" GETW D1Ar1,[%1++]\n" \
|
||||
"6: SETW [%0++],D1Ar1\n" COPY, \
|
||||
"7: ADD %2,%2,#2\n" \
|
||||
" SETW [%0++],D1Ar1\n" FIXUP, \
|
||||
" .long 6b,7b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_10(to, from, ret) \
|
||||
__asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_11(to, from, ret) \
|
||||
__asm_copy_from_user_10x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"8: SETB [%0++],D1Ar1\n", \
|
||||
"9: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
" .long 8b,9b\n")
|
||||
|
||||
#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_from_user_8x_cont(to, from, ret, \
|
||||
" GETD D1Ar1,[%1++]\n" \
|
||||
"6: SETD [%0++],D1Ar1\n" COPY, \
|
||||
"7: ADD %2,%2,#4\n" \
|
||||
" SETD [%0++],D1Ar1\n" FIXUP, \
|
||||
" .long 6b,7b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_12(to, from, ret) \
|
||||
__asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_13(to, from, ret) \
|
||||
__asm_copy_from_user_12x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"8: SETB [%0++],D1Ar1\n", \
|
||||
"9: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
" .long 8b,9b\n")
|
||||
|
||||
#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_from_user_12x_cont(to, from, ret, \
|
||||
" GETW D1Ar1,[%1++]\n" \
|
||||
"8: SETW [%0++],D1Ar1\n" COPY, \
|
||||
"9: ADD %2,%2,#2\n" \
|
||||
" SETW [%0++],D1Ar1\n" FIXUP, \
|
||||
" .long 8b,9b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_14(to, from, ret) \
|
||||
__asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_15(to, from, ret) \
|
||||
__asm_copy_from_user_14x_cont(to, from, ret, \
|
||||
" GETB D1Ar1,[%1++]\n" \
|
||||
"10: SETB [%0++],D1Ar1\n", \
|
||||
"11: ADD %2,%2,#1\n" \
|
||||
" SETB [%0++],D1Ar1\n", \
|
||||
" .long 10b,11b\n")
|
||||
|
||||
#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
|
||||
__asm_copy_from_user_12x_cont(to, from, ret, \
|
||||
" GETD D1Ar1,[%1++]\n" \
|
||||
"8: SETD [%0++],D1Ar1\n" COPY, \
|
||||
"9: ADD %2,%2,#4\n" \
|
||||
" SETD [%0++],D1Ar1\n" FIXUP, \
|
||||
" .long 8b,9b\n" TENTRY)
|
||||
|
||||
#define __asm_copy_from_user_16(to, from, ret) \
|
||||
__asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
|
||||
|
||||
#define __asm_copy_from_user_8x64(to, from, ret) \
|
||||
asm volatile ( \
|
||||
" GETL D0Ar2,D1Ar1,[%1++]\n" \
|
||||
"2: SETL [%0++],D0Ar2,D1Ar1\n" \
|
||||
"1:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" MOV D1Ar1,#0\n" \
|
||||
" MOV D0Ar2,#0\n" \
|
||||
"3: ADD %2,%2,#8\n" \
|
||||
" SETL [%0++],D0Ar2,D1Ar1\n" \
|
||||
" MOVT D0Ar2,#HI(1b)\n" \
|
||||
" JUMP D0Ar2,#LO(1b)\n" \
|
||||
" .previous\n" \
|
||||
@@ -789,36 +711,57 @@ EXPORT_SYMBOL(__copy_user);
|
||||
*
|
||||
* Rationale:
|
||||
* A fault occurs while reading from user buffer, which is the
|
||||
* source. Since the fault is at a single address, we only
|
||||
* need to rewind by 8 bytes.
|
||||
* source.
|
||||
* Since we don't write to kernel buffer until we read first,
|
||||
* the kernel buffer is at the right state and needn't be
|
||||
* corrected.
|
||||
* corrected, but the source must be rewound to the beginning of
|
||||
* the block, which is LSM_STEP*8 bytes.
|
||||
* LSM_STEP is bits 10:8 in TXSTATUS which is already read
|
||||
* and stored in D0Ar2
|
||||
*
|
||||
* NOTE: If a fault occurs at the last operation in M{G,S}ETL
|
||||
* LSM_STEP will be 0. ie: we do 4 writes in our case, if
|
||||
* a fault happens at the 4th write, LSM_STEP will be 0
|
||||
* instead of 4. The code copes with that.
|
||||
*/
|
||||
#define __asm_copy_from_user_64bit_rapf_loop(to, from, ret, n, id) \
|
||||
__asm_copy_user_64bit_rapf_loop(to, from, ret, n, id, \
|
||||
"SUB %1, %1, #8\n")
|
||||
"LSR D0Ar2, D0Ar2, #5\n" \
|
||||
"ANDS D0Ar2, D0Ar2, #0x38\n" \
|
||||
"ADDZ D0Ar2, D0Ar2, #32\n" \
|
||||
"SUB %1, %1, D0Ar2\n")
|
||||
|
||||
/* rewind 'from' pointer when a fault occurs
|
||||
*
|
||||
* Rationale:
|
||||
* A fault occurs while reading from user buffer, which is the
|
||||
* source. Since the fault is at a single address, we only
|
||||
* need to rewind by 4 bytes.
|
||||
* source.
|
||||
* Since we don't write to kernel buffer until we read first,
|
||||
* the kernel buffer is at the right state and needn't be
|
||||
* corrected.
|
||||
* corrected, but the source must be rewound to the beginning of
|
||||
* the block, which is LSM_STEP*4 bytes.
|
||||
* LSM_STEP is bits 10:8 in TXSTATUS which is already read
|
||||
* and stored in D0Ar2
|
||||
*
|
||||
* NOTE: If a fault occurs at the last operation in M{G,S}ETL
|
||||
* LSM_STEP will be 0. ie: we do 4 writes in our case, if
|
||||
* a fault happens at the 4th write, LSM_STEP will be 0
|
||||
* instead of 4. The code copes with that.
|
||||
*/
|
||||
#define __asm_copy_from_user_32bit_rapf_loop(to, from, ret, n, id) \
|
||||
__asm_copy_user_32bit_rapf_loop(to, from, ret, n, id, \
|
||||
"SUB %1, %1, #4\n")
|
||||
"LSR D0Ar2, D0Ar2, #6\n" \
|
||||
"ANDS D0Ar2, D0Ar2, #0x1c\n" \
|
||||
"ADDZ D0Ar2, D0Ar2, #16\n" \
|
||||
"SUB %1, %1, D0Ar2\n")
|
||||
|
||||
|
||||
/* Copy from user to kernel, zeroing the bytes that were inaccessible in
|
||||
userland. The return-value is the number of bytes that were
|
||||
inaccessible. */
|
||||
unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
unsigned long n)
|
||||
/*
|
||||
* Copy from user to kernel. The return-value is the number of bytes that were
|
||||
* inaccessible.
|
||||
*/
|
||||
unsigned long raw_copy_from_user(void *pdst, const void __user *psrc,
|
||||
unsigned long n)
|
||||
{
|
||||
register char *dst asm ("A0.2") = pdst;
|
||||
register const char __user *src asm ("A1.2") = psrc;
|
||||
@@ -830,6 +773,8 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
if ((unsigned long) src & 1) {
|
||||
__asm_copy_from_user_1(dst, src, retn);
|
||||
n--;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
if ((unsigned long) dst & 1) {
|
||||
/* Worst case - byte copy */
|
||||
@@ -837,12 +782,14 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
__asm_copy_from_user_1(dst, src, retn);
|
||||
n--;
|
||||
if (retn)
|
||||
goto copy_exception_bytes;
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
if (((unsigned long) src & 2) && n >= 2) {
|
||||
__asm_copy_from_user_2(dst, src, retn);
|
||||
n -= 2;
|
||||
if (retn)
|
||||
return retn + n;
|
||||
}
|
||||
if ((unsigned long) dst & 2) {
|
||||
/* Second worst case - word copy */
|
||||
@@ -850,16 +797,10 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
__asm_copy_from_user_2(dst, src, retn);
|
||||
n -= 2;
|
||||
if (retn)
|
||||
goto copy_exception_bytes;
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
|
||||
/* We only need one check after the unalignment-adjustments,
|
||||
because if both adjustments were done, either both or
|
||||
neither reference had an exception. */
|
||||
if (retn != 0)
|
||||
goto copy_exception_bytes;
|
||||
|
||||
#ifdef USE_RAPF
|
||||
/* 64 bit copy loop */
|
||||
if (!(((unsigned long) src | (unsigned long) dst) & 7)) {
|
||||
@@ -872,7 +813,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
__asm_copy_from_user_8x64(dst, src, retn);
|
||||
n -= 8;
|
||||
if (retn)
|
||||
goto copy_exception_bytes;
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,7 +829,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
__asm_copy_from_user_8x64(dst, src, retn);
|
||||
n -= 8;
|
||||
if (retn)
|
||||
goto copy_exception_bytes;
|
||||
return retn + n;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -898,7 +839,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
n -= 4;
|
||||
|
||||
if (retn)
|
||||
goto copy_exception_bytes;
|
||||
return retn + n;
|
||||
}
|
||||
|
||||
/* If we get here, there were no memory read faults. */
|
||||
@@ -924,21 +865,8 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
|
||||
/* If we get here, retn correctly reflects the number of failing
|
||||
bytes. */
|
||||
return retn;
|
||||
|
||||
copy_exception_bytes:
|
||||
/* We already have "retn" bytes cleared, and need to clear the
|
||||
remaining "n" bytes. A non-optimized simple byte-for-byte in-line
|
||||
memset is preferred here, since this isn't speed-critical code and
|
||||
we'd rather have this a leaf-function than calling memset. */
|
||||
{
|
||||
char *endp;
|
||||
for (endp = dst + n; dst < endp; dst++)
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
return retn + n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_user_zeroing);
|
||||
EXPORT_SYMBOL(raw_copy_from_user);
|
||||
|
||||
#define __asm_clear_8x64(to, ret) \
|
||||
asm volatile ( \
|
||||
|
||||
+1
-1
@@ -1526,7 +1526,7 @@ config CPU_MIPS64_R6
|
||||
select CPU_SUPPORTS_HIGHMEM
|
||||
select CPU_SUPPORTS_MSA
|
||||
select GENERIC_CSUM
|
||||
select MIPS_O32_FP64_SUPPORT if MIPS32_O32
|
||||
select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32
|
||||
select HAVE_KVM
|
||||
help
|
||||
Choose this option to build a kernel for release 6 or later of the
|
||||
|
||||
@@ -127,7 +127,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
||||
" andi %[ticket], %[ticket], 0xffff \n"
|
||||
" bne %[ticket], %[my_ticket], 4f \n"
|
||||
" subu %[ticket], %[my_ticket], %[ticket] \n"
|
||||
"2: \n"
|
||||
"2: .insn \n"
|
||||
" .subsection 2 \n"
|
||||
"4: andi %[ticket], %[ticket], 0xffff \n"
|
||||
" sll %[ticket], 5 \n"
|
||||
@@ -202,7 +202,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
|
||||
" sc %[ticket], %[ticket_ptr] \n"
|
||||
" beqz %[ticket], 1b \n"
|
||||
" li %[ticket], 1 \n"
|
||||
"2: \n"
|
||||
"2: .insn \n"
|
||||
" .subsection 2 \n"
|
||||
"3: b 2b \n"
|
||||
" li %[ticket], 0 \n"
|
||||
@@ -382,7 +382,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
|
||||
" .set reorder \n"
|
||||
__WEAK_LLSC_MB
|
||||
" li %2, 1 \n"
|
||||
"2: \n"
|
||||
"2: .insn \n"
|
||||
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
||||
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||
: "memory");
|
||||
@@ -422,7 +422,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
|
||||
" lui %1, 0x8000 \n"
|
||||
" sc %1, %0 \n"
|
||||
" li %2, 1 \n"
|
||||
"2: \n"
|
||||
"2: .insn \n"
|
||||
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
|
||||
"=&r" (ret)
|
||||
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||
|
||||
@@ -1824,7 +1824,7 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
||||
}
|
||||
|
||||
decode_configs(c);
|
||||
c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
|
||||
c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
|
||||
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -448,7 +448,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
|
||||
BUILD_HANDLER reserved reserved sti verbose /* others */
|
||||
|
||||
.align 5
|
||||
LEAF(handle_ri_rdhwr_vivt)
|
||||
LEAF(handle_ri_rdhwr_tlbp)
|
||||
.set push
|
||||
.set noat
|
||||
.set noreorder
|
||||
@@ -467,7 +467,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
|
||||
.set pop
|
||||
bltz k1, handle_ri /* slow path */
|
||||
/* fall thru */
|
||||
END(handle_ri_rdhwr_vivt)
|
||||
END(handle_ri_rdhwr_tlbp)
|
||||
|
||||
LEAF(handle_ri_rdhwr)
|
||||
.set push
|
||||
|
||||
@@ -81,7 +81,7 @@ extern asmlinkage void handle_dbe(void);
|
||||
extern asmlinkage void handle_sys(void);
|
||||
extern asmlinkage void handle_bp(void);
|
||||
extern asmlinkage void handle_ri(void);
|
||||
extern asmlinkage void handle_ri_rdhwr_vivt(void);
|
||||
extern asmlinkage void handle_ri_rdhwr_tlbp(void);
|
||||
extern asmlinkage void handle_ri_rdhwr(void);
|
||||
extern asmlinkage void handle_cpu(void);
|
||||
extern asmlinkage void handle_ov(void);
|
||||
@@ -2352,9 +2352,18 @@ void __init trap_init(void)
|
||||
|
||||
set_except_vector(EXCCODE_SYS, handle_sys);
|
||||
set_except_vector(EXCCODE_BP, handle_bp);
|
||||
set_except_vector(EXCCODE_RI, rdhwr_noopt ? handle_ri :
|
||||
(cpu_has_vtag_icache ?
|
||||
handle_ri_rdhwr_vivt : handle_ri_rdhwr));
|
||||
|
||||
if (rdhwr_noopt)
|
||||
set_except_vector(EXCCODE_RI, handle_ri);
|
||||
else {
|
||||
if (cpu_has_vtag_icache)
|
||||
set_except_vector(EXCCODE_RI, handle_ri_rdhwr_tlbp);
|
||||
else if (current_cpu_type() == CPU_LOONGSON3)
|
||||
set_except_vector(EXCCODE_RI, handle_ri_rdhwr_tlbp);
|
||||
else
|
||||
set_except_vector(EXCCODE_RI, handle_ri_rdhwr);
|
||||
}
|
||||
|
||||
set_except_vector(EXCCODE_CPU, handle_cpu);
|
||||
set_except_vector(EXCCODE_OV, handle_ov);
|
||||
set_except_vector(EXCCODE_TR, handle_tr);
|
||||
|
||||
@@ -467,7 +467,7 @@ void __init ltq_soc_init(void)
|
||||
|
||||
if (!np_xbar)
|
||||
panic("Failed to load xbar nodes from devicetree");
|
||||
if (of_address_to_resource(np_pmu, 0, &res_xbar))
|
||||
if (of_address_to_resource(np_xbar, 0, &res_xbar))
|
||||
panic("Failed to get xbar resources");
|
||||
if (request_mem_region(res_xbar.start, resource_size(&res_xbar),
|
||||
res_xbar.name) < 0)
|
||||
|
||||
@@ -1558,6 +1558,7 @@ static void probe_vcache(void)
|
||||
vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz;
|
||||
|
||||
c->vcache.waybit = 0;
|
||||
c->vcache.waysize = vcache_size / c->vcache.ways;
|
||||
|
||||
pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
|
||||
vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
|
||||
@@ -1660,6 +1661,7 @@ static void __init loongson3_sc_init(void)
|
||||
/* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */
|
||||
scache_size *= 4;
|
||||
c->scache.waybit = 0;
|
||||
c->scache.waysize = scache_size / c->scache.ways;
|
||||
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
|
||||
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
|
||||
if (scache_size)
|
||||
|
||||
+21
-4
@@ -762,7 +762,8 @@ static void build_huge_update_entries(u32 **p, unsigned int pte,
|
||||
static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r,
|
||||
struct uasm_label **l,
|
||||
unsigned int pte,
|
||||
unsigned int ptr)
|
||||
unsigned int ptr,
|
||||
unsigned int flush)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
UASM_i_SC(p, pte, 0, ptr);
|
||||
@@ -771,6 +772,22 @@ static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r,
|
||||
#else
|
||||
UASM_i_SW(p, pte, 0, ptr);
|
||||
#endif
|
||||
if (cpu_has_ftlb && flush) {
|
||||
BUG_ON(!cpu_has_tlbinv);
|
||||
|
||||
UASM_i_MFC0(p, ptr, C0_ENTRYHI);
|
||||
uasm_i_ori(p, ptr, ptr, MIPS_ENTRYHI_EHINV);
|
||||
UASM_i_MTC0(p, ptr, C0_ENTRYHI);
|
||||
build_tlb_write_entry(p, l, r, tlb_indexed);
|
||||
|
||||
uasm_i_xori(p, ptr, ptr, MIPS_ENTRYHI_EHINV);
|
||||
UASM_i_MTC0(p, ptr, C0_ENTRYHI);
|
||||
build_huge_update_entries(p, pte, ptr);
|
||||
build_huge_tlb_write_entry(p, l, r, pte, tlb_random, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
build_huge_update_entries(p, pte, ptr);
|
||||
build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
|
||||
}
|
||||
@@ -2197,7 +2214,7 @@ static void build_r4000_tlb_load_handler(void)
|
||||
uasm_l_tlbl_goaround2(&l, p);
|
||||
}
|
||||
uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID));
|
||||
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
|
||||
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1);
|
||||
#endif
|
||||
|
||||
uasm_l_nopage_tlbl(&l, p);
|
||||
@@ -2252,7 +2269,7 @@ static void build_r4000_tlb_store_handler(void)
|
||||
build_tlb_probe_entry(&p);
|
||||
uasm_i_ori(&p, wr.r1, wr.r1,
|
||||
_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
|
||||
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
|
||||
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1);
|
||||
#endif
|
||||
|
||||
uasm_l_nopage_tlbs(&l, p);
|
||||
@@ -2308,7 +2325,7 @@ static void build_r4000_tlb_modify_handler(void)
|
||||
build_tlb_probe_entry(&p);
|
||||
uasm_i_ori(&p, wr.r1, wr.r1,
|
||||
_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
|
||||
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
|
||||
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 0);
|
||||
#endif
|
||||
|
||||
uasm_l_nopage_tlbm(&l, p);
|
||||
|
||||
@@ -36,7 +36,7 @@ static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) };
|
||||
static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) };
|
||||
static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) };
|
||||
static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) };
|
||||
static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) };
|
||||
static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) };
|
||||
static struct rt2880_pmx_func pci_func[] = {
|
||||
FUNC("pci-dev", 0, 40, 32),
|
||||
FUNC("pci-host2", 1, 40, 32),
|
||||
@@ -44,7 +44,7 @@ static struct rt2880_pmx_func pci_func[] = {
|
||||
FUNC("pci-fnc", 3, 40, 32)
|
||||
};
|
||||
static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) };
|
||||
static struct rt2880_pmx_func ge2_func[] = { FUNC("ge1", 0, 84, 12) };
|
||||
static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) };
|
||||
|
||||
static struct rt2880_pmx_group rt3883_pinmux_data[] = {
|
||||
GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C),
|
||||
|
||||
@@ -48,6 +48,13 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
||||
return alloc_bootmem_align(size, align);
|
||||
}
|
||||
|
||||
int __init early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
|
||||
bool nomap)
|
||||
{
|
||||
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init early_init_devtree(void *params)
|
||||
{
|
||||
__be32 *dtb = (u32 *)__dtb_start;
|
||||
|
||||
@@ -195,6 +195,9 @@ void __init setup_arch(char **cmdline_p)
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
early_init_fdt_reserve_self();
|
||||
early_init_fdt_scan_reserved_mem();
|
||||
|
||||
unflatten_and_copy_device_tree();
|
||||
|
||||
setup_cpuinfo();
|
||||
|
||||
@@ -33,10 +33,13 @@ static u32 crc32c_vpmsum(u32 crc, unsigned char const *p, size_t len)
|
||||
}
|
||||
|
||||
if (len & ~VMX_ALIGN_MASK) {
|
||||
preempt_disable();
|
||||
pagefault_disable();
|
||||
enable_kernel_altivec();
|
||||
crc = __crc32c_vpmsum(crc, p, len & ~VMX_ALIGN_MASK);
|
||||
disable_kernel_altivec();
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
tail = len & VMX_ALIGN_MASK;
|
||||
|
||||
@@ -807,14 +807,25 @@ int fix_alignment(struct pt_regs *regs)
|
||||
nb = aligninfo[instr].len;
|
||||
flags = aligninfo[instr].flags;
|
||||
|
||||
/* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */
|
||||
if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) {
|
||||
nb = 8;
|
||||
flags = LD+SW;
|
||||
} else if (IS_XFORM(instruction) &&
|
||||
((instruction >> 1) & 0x3ff) == 660) {
|
||||
nb = 8;
|
||||
flags = ST+SW;
|
||||
/*
|
||||
* Handle some cases which give overlaps in the DSISR values.
|
||||
*/
|
||||
if (IS_XFORM(instruction)) {
|
||||
switch (get_xop(instruction)) {
|
||||
case 532: /* ldbrx */
|
||||
nb = 8;
|
||||
flags = LD+SW;
|
||||
break;
|
||||
case 660: /* stdbrx */
|
||||
nb = 8;
|
||||
flags = ST+SW;
|
||||
break;
|
||||
case 20: /* lwarx */
|
||||
case 84: /* ldarx */
|
||||
case 116: /* lharx */
|
||||
case 276: /* lqarx */
|
||||
return 0; /* not emulated ever */
|
||||
}
|
||||
}
|
||||
|
||||
/* Byteswap little endian loads and stores */
|
||||
|
||||
@@ -67,7 +67,7 @@ PPC64_CACHES:
|
||||
* flush all bytes from start through stop-1 inclusive
|
||||
*/
|
||||
|
||||
_GLOBAL(flush_icache_range)
|
||||
_GLOBAL_TOC(flush_icache_range)
|
||||
BEGIN_FTR_SECTION
|
||||
PURGE_PREFETCHED_INS
|
||||
blr
|
||||
@@ -120,7 +120,7 @@ EXPORT_SYMBOL(flush_icache_range)
|
||||
*
|
||||
* flush all bytes from start to stop-1 inclusive
|
||||
*/
|
||||
_GLOBAL(flush_dcache_range)
|
||||
_GLOBAL_TOC(flush_dcache_range)
|
||||
|
||||
/*
|
||||
* Flush the data cache to memory
|
||||
|
||||
@@ -245,6 +245,15 @@ static void cpu_ready_for_interrupts(void)
|
||||
mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixup HFSCR:TM based on CPU features. The bit is set by our
|
||||
* early asm init because at that point we haven't updated our
|
||||
* CPU features from firmware and device-tree. Here we have,
|
||||
* so let's do it.
|
||||
*/
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP))
|
||||
mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM);
|
||||
|
||||
/* Set IR and DR in PACA MSR */
|
||||
get_paca()->kernel_msr = MSR_KERNEL;
|
||||
}
|
||||
|
||||
@@ -636,6 +636,10 @@ static void native_flush_hash_range(unsigned long number, int local)
|
||||
unsigned long psize = batch->psize;
|
||||
int ssize = batch->ssize;
|
||||
int i;
|
||||
unsigned int use_local;
|
||||
|
||||
use_local = local && mmu_has_feature(MMU_FTR_TLBIEL) &&
|
||||
mmu_psize_defs[psize].tlbiel && !cxl_ctx_in_use();
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
@@ -665,8 +669,7 @@ static void native_flush_hash_range(unsigned long number, int local)
|
||||
} pte_iterate_hashed_end();
|
||||
}
|
||||
|
||||
if (mmu_has_feature(MMU_FTR_TLBIEL) &&
|
||||
mmu_psize_defs[psize].tlbiel && local) {
|
||||
if (use_local) {
|
||||
asm volatile("ptesync":::"memory");
|
||||
for (i = 0; i < number; i++) {
|
||||
vpn = batch->vpn[i];
|
||||
|
||||
@@ -141,31 +141,34 @@ static void check_ipl_parmblock(void *start, unsigned long size)
|
||||
|
||||
unsigned long decompress_kernel(void)
|
||||
{
|
||||
unsigned long output_addr;
|
||||
unsigned char *output;
|
||||
void *output, *kernel_end;
|
||||
|
||||
output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL;
|
||||
check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start);
|
||||
memset(&_bss, 0, &_ebss - &_bss);
|
||||
free_mem_ptr = (unsigned long)&_end;
|
||||
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
|
||||
output = (unsigned char *) output_addr;
|
||||
output = (void *) ALIGN((unsigned long) &_end + HEAP_SIZE, PAGE_SIZE);
|
||||
kernel_end = output + SZ__bss_start;
|
||||
check_ipl_parmblock((void *) 0, (unsigned long) kernel_end);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
/*
|
||||
* Move the initrd right behind the end of the decompressed
|
||||
* kernel image.
|
||||
* kernel image. This also prevents initrd corruption caused by
|
||||
* bss clearing since kernel_end will always be located behind the
|
||||
* current bss section..
|
||||
*/
|
||||
if (INITRD_START && INITRD_SIZE &&
|
||||
INITRD_START < (unsigned long) output + SZ__bss_start) {
|
||||
check_ipl_parmblock(output + SZ__bss_start,
|
||||
INITRD_START + INITRD_SIZE);
|
||||
memmove(output + SZ__bss_start,
|
||||
(void *) INITRD_START, INITRD_SIZE);
|
||||
INITRD_START = (unsigned long) output + SZ__bss_start;
|
||||
if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) {
|
||||
check_ipl_parmblock(kernel_end, INITRD_SIZE);
|
||||
memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE);
|
||||
INITRD_START = (unsigned long) kernel_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Clear bss section. free_mem_ptr and free_mem_end_ptr need to be
|
||||
* initialized afterwards since they reside in bss.
|
||||
*/
|
||||
memset(&_bss, 0, &_ebss - &_bss);
|
||||
free_mem_ptr = (unsigned long) &_end;
|
||||
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
|
||||
|
||||
puts("Uncompressing Linux... ");
|
||||
__decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
|
||||
puts("Ok, booting the kernel.\n");
|
||||
|
||||
@@ -144,7 +144,7 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from,
|
||||
" jg 2b\n" \
|
||||
".popsection\n" \
|
||||
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
|
||||
: "=d" (__rc), "=Q" (*(to)) \
|
||||
: "=d" (__rc), "+Q" (*(to)) \
|
||||
: "d" (size), "Q" (*(from)), \
|
||||
"d" (__reg0), "K" (-EFAULT) \
|
||||
: "cc"); \
|
||||
|
||||
@@ -223,6 +223,22 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
|
||||
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, "X205TA"),
|
||||
},
|
||||
},
|
||||
{ /* 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 */
|
||||
|
||||
@@ -164,8 +164,21 @@ void copy_user_highpage(struct page *to, struct page *from,
|
||||
|
||||
#define ARCH_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
static inline unsigned long ___pa(unsigned long va)
|
||||
{
|
||||
unsigned long off = va - PAGE_OFFSET;
|
||||
|
||||
if (off >= XCHAL_KSEG_SIZE)
|
||||
off -= XCHAL_KSEG_SIZE;
|
||||
|
||||
return off + PHYS_OFFSET;
|
||||
}
|
||||
#define __pa(x) ___pa((unsigned long)(x))
|
||||
#else
|
||||
#define __pa(x) \
|
||||
((unsigned long) (x) - PAGE_OFFSET + PHYS_OFFSET)
|
||||
#endif
|
||||
#define __va(x) \
|
||||
((void *)((unsigned long) (x) - PHYS_OFFSET + PAGE_OFFSET))
|
||||
#define pfn_valid(pfn) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2044,6 +2044,7 @@ int __init acpi_scan_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
acpi_gpe_apply_masked_gpes();
|
||||
acpi_update_all_gpes();
|
||||
acpi_ec_ecdt_start();
|
||||
|
||||
|
||||
@@ -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_dmi_table[] __initdata = {
|
||||
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"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -708,6 +708,62 @@ end:
|
||||
return result ? result : size;
|
||||
}
|
||||
|
||||
/*
|
||||
* A Quirk Mechanism for GPE Flooding Prevention:
|
||||
*
|
||||
* Quirks may be needed to prevent GPE flooding on a specific GPE. The
|
||||
* flooding typically cannot be detected and automatically prevented by
|
||||
* ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
|
||||
* the AML tables. This normally indicates a feature gap in Linux, thus
|
||||
* instead of providing endless quirk tables, we provide a boot parameter
|
||||
* for those who want this quirk. For example, if the users want to prevent
|
||||
* the GPE flooding for GPE 00, they need to specify the following boot
|
||||
* parameter:
|
||||
* acpi_mask_gpe=0x00
|
||||
* The masking status can be modified by the following runtime controlling
|
||||
* interface:
|
||||
* echo unmask > /sys/firmware/acpi/interrupts/gpe00
|
||||
*/
|
||||
|
||||
/*
|
||||
* Currently, the GPE flooding prevention only supports to mask the GPEs
|
||||
* numbered from 00 to 7f.
|
||||
*/
|
||||
#define ACPI_MASKABLE_GPE_MAX 0x80
|
||||
|
||||
static u64 __initdata acpi_masked_gpes;
|
||||
|
||||
static int __init acpi_gpe_set_masked_gpes(char *val)
|
||||
{
|
||||
u8 gpe;
|
||||
|
||||
if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
|
||||
return -EINVAL;
|
||||
acpi_masked_gpes |= ((u64)1<<gpe);
|
||||
|
||||
return 1;
|
||||
}
|
||||
__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
|
||||
|
||||
void __init acpi_gpe_apply_masked_gpes(void)
|
||||
{
|
||||
acpi_handle handle;
|
||||
acpi_status status;
|
||||
u8 gpe;
|
||||
|
||||
for (gpe = 0;
|
||||
gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
|
||||
gpe++) {
|
||||
if (acpi_masked_gpes & ((u64)1<<gpe)) {
|
||||
status = acpi_get_gpe_device(gpe, &handle);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
pr_info("Masking GPE 0x%x.\n", gpe);
|
||||
(void)acpi_mask_gpe(handle, gpe, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void acpi_irq_stats_init(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
@@ -54,11 +54,42 @@ static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
|
||||
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 = {
|
||||
|
||||
+30
-3
@@ -84,8 +84,14 @@ struct pp_struct {
|
||||
struct ieee1284_info state;
|
||||
struct ieee1284_info saved_state;
|
||||
long default_inactivity;
|
||||
int index;
|
||||
};
|
||||
|
||||
/* should we use PARDEVICE_MAX here? */
|
||||
static struct device *devices[PARPORT_MAX];
|
||||
|
||||
static DEFINE_IDA(ida_index);
|
||||
|
||||
/* pp_struct.flags bitfields */
|
||||
#define PP_CLAIMED (1<<0)
|
||||
#define PP_EXCL (1<<1)
|
||||
@@ -287,6 +293,7 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||
struct pardevice *pdev = NULL;
|
||||
char *name;
|
||||
struct pardev_cb ppdev_cb;
|
||||
int index;
|
||||
|
||||
name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
|
||||
if (name == NULL)
|
||||
@@ -299,20 +306,23 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
|
||||
memset(&ppdev_cb, 0, sizeof(ppdev_cb));
|
||||
ppdev_cb.irq_func = pp_irq;
|
||||
ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
|
||||
ppdev_cb.private = pp;
|
||||
pdev = parport_register_dev_model(port, name, &ppdev_cb, minor);
|
||||
pdev = parport_register_dev_model(port, name, &ppdev_cb, index);
|
||||
parport_put_port(port);
|
||||
|
||||
if (!pdev) {
|
||||
printk(KERN_WARNING "%s: failed to register device!\n", name);
|
||||
ida_simple_remove(&ida_index, index);
|
||||
kfree(name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
pp->pdev = pdev;
|
||||
pp->index = index;
|
||||
dev_dbg(&pdev->dev, "registered pardevice\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -749,6 +759,7 @@ static int pp_release(struct inode *inode, struct file *file)
|
||||
|
||||
if (pp->pdev) {
|
||||
parport_unregister_device(pp->pdev);
|
||||
ida_simple_remove(&ida_index, pp->index);
|
||||
pp->pdev = NULL;
|
||||
pr_debug(CHRDEV "%x: unregistered pardevice\n", minor);
|
||||
}
|
||||
@@ -789,13 +800,29 @@ static const struct file_operations pp_fops = {
|
||||
|
||||
static void pp_attach(struct parport *port)
|
||||
{
|
||||
device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
|
||||
NULL, "parport%d", port->number);
|
||||
struct device *ret;
|
||||
|
||||
if (devices[port->number])
|
||||
return;
|
||||
|
||||
ret = device_create(ppdev_class, port->dev,
|
||||
MKDEV(PP_MAJOR, port->number), NULL,
|
||||
"parport%d", port->number);
|
||||
if (IS_ERR(ret)) {
|
||||
pr_err("Failed to create device parport%d\n",
|
||||
port->number);
|
||||
return;
|
||||
}
|
||||
devices[port->number] = ret;
|
||||
}
|
||||
|
||||
static void pp_detach(struct parport *port)
|
||||
{
|
||||
if (!devices[port->number])
|
||||
return;
|
||||
|
||||
device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
|
||||
devices[port->number] = NULL;
|
||||
}
|
||||
|
||||
static int pp_probe(struct pardevice *par_dev)
|
||||
|
||||
+46
-44
@@ -2042,64 +2042,66 @@ struct ctl_table random_table[] = {
|
||||
};
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
|
||||
|
||||
int random_int_secret_init(void)
|
||||
{
|
||||
get_random_bytes(random_int_secret, sizeof(random_int_secret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
|
||||
__aligned(sizeof(unsigned long));
|
||||
struct batched_entropy {
|
||||
union {
|
||||
unsigned long entropy_long[CHACHA20_BLOCK_SIZE / sizeof(unsigned long)];
|
||||
unsigned int entropy_int[CHACHA20_BLOCK_SIZE / sizeof(unsigned int)];
|
||||
};
|
||||
unsigned int position;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get a random word for internal kernel use only. Similar to urandom but
|
||||
* with the goal of minimal entropy pool depletion. As a result, the random
|
||||
* value is not cryptographically secure but for several uses the cost of
|
||||
* depleting entropy is too high
|
||||
*/
|
||||
unsigned int get_random_int(void)
|
||||
{
|
||||
__u32 *hash;
|
||||
unsigned int ret;
|
||||
|
||||
if (arch_get_random_int(&ret))
|
||||
return ret;
|
||||
|
||||
hash = get_cpu_var(get_random_int_hash);
|
||||
|
||||
hash[0] += current->pid + jiffies + random_get_entropy();
|
||||
md5_transform(hash, random_int_secret);
|
||||
ret = hash[0];
|
||||
put_cpu_var(get_random_int_hash);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(get_random_int);
|
||||
|
||||
/*
|
||||
* Same as get_random_int(), but returns unsigned long.
|
||||
* Get a random word for internal kernel use only. The quality of the random
|
||||
* number is either as good as RDRAND or as good as /dev/urandom, with the
|
||||
* goal of being quite fast and not depleting entropy.
|
||||
*/
|
||||
static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_long);
|
||||
unsigned long get_random_long(void)
|
||||
{
|
||||
__u32 *hash;
|
||||
unsigned long ret;
|
||||
struct batched_entropy *batch;
|
||||
|
||||
if (arch_get_random_long(&ret))
|
||||
return ret;
|
||||
|
||||
hash = get_cpu_var(get_random_int_hash);
|
||||
|
||||
hash[0] += current->pid + jiffies + random_get_entropy();
|
||||
md5_transform(hash, random_int_secret);
|
||||
ret = *(unsigned long *)hash;
|
||||
put_cpu_var(get_random_int_hash);
|
||||
|
||||
batch = &get_cpu_var(batched_entropy_long);
|
||||
if (batch->position % ARRAY_SIZE(batch->entropy_long) == 0) {
|
||||
extract_crng((u8 *)batch->entropy_long);
|
||||
batch->position = 0;
|
||||
}
|
||||
ret = batch->entropy_long[batch->position++];
|
||||
put_cpu_var(batched_entropy_long);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(get_random_long);
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
unsigned int get_random_int(void)
|
||||
{
|
||||
return get_random_long();
|
||||
}
|
||||
#else
|
||||
static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_int);
|
||||
unsigned int get_random_int(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
struct batched_entropy *batch;
|
||||
|
||||
if (arch_get_random_int(&ret))
|
||||
return ret;
|
||||
|
||||
batch = &get_cpu_var(batched_entropy_int);
|
||||
if (batch->position % ARRAY_SIZE(batch->entropy_int) == 0) {
|
||||
extract_crng((u8 *)batch->entropy_int);
|
||||
batch->position = 0;
|
||||
}
|
||||
ret = batch->entropy_int[batch->position++];
|
||||
put_cpu_var(batched_entropy_int);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
EXPORT_SYMBOL(get_random_int);
|
||||
|
||||
/**
|
||||
* randomize_page - Generate a random, page aligned address
|
||||
* @start: The smallest acceptable address the caller will take.
|
||||
|
||||
@@ -1282,13 +1282,13 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
|
||||
|
||||
LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0),
|
||||
LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
|
||||
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
|
||||
CLK_DIVIDER_ONE_BASED),
|
||||
LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0),
|
||||
LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE),
|
||||
|
||||
LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0),
|
||||
LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
|
||||
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
|
||||
CLK_DIVIDER_ONE_BASED),
|
||||
LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0),
|
||||
LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE),
|
||||
|
||||
@@ -1335,8 +1335,7 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
|
||||
LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0),
|
||||
LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE),
|
||||
|
||||
LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL,
|
||||
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
|
||||
LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED),
|
||||
LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9),
|
||||
0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops),
|
||||
LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE),
|
||||
@@ -1478,6 +1477,20 @@ static struct clk * __init lpc32xx_clk_register(u32 id)
|
||||
return clk;
|
||||
}
|
||||
|
||||
static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
regmap_read(clk_regmap, reg, &val);
|
||||
|
||||
if (!(val & div_mask)) {
|
||||
val &= ~gate;
|
||||
val |= BIT(__ffs(div_mask));
|
||||
}
|
||||
|
||||
regmap_update_bits(clk_regmap, reg, gate | div_mask, val);
|
||||
}
|
||||
|
||||
static void __init lpc32xx_clk_init(struct device_node *np)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -1517,6 +1530,17 @@ static void __init lpc32xx_clk_init(struct device_node *np)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Divider part of PWM and MS clocks requires a quirk to avoid
|
||||
* a misinterpretation of formally valid zero value in register
|
||||
* bitfield, which indicates another clock gate. Instead of
|
||||
* adding complexity to a gate clock ensure that zero value in
|
||||
* divider clock is never met in runtime.
|
||||
*/
|
||||
lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0));
|
||||
lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2));
|
||||
lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9));
|
||||
|
||||
for (i = 1; i < LPC32XX_CLK_MAX; i++) {
|
||||
clk[i] = lpc32xx_clk_register(i);
|
||||
if (IS_ERR(clk[i])) {
|
||||
|
||||
@@ -81,6 +81,7 @@ static struct clock_event_device __percpu *arch_timer_evt;
|
||||
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_counter = {
|
||||
.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(unsigned type)
|
||||
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(struct device_node *np)
|
||||
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);
|
||||
|
||||
@@ -91,6 +91,7 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
|
||||
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 *dev, u32 svc_id, u32 cmd_id,
|
||||
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);
|
||||
|
||||
@@ -571,8 +571,10 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
|
||||
}
|
||||
|
||||
desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
|
||||
if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
|
||||
if (!IS_ERR(desc))
|
||||
break;
|
||||
if (PTR_ERR(desc) == -EPROBE_DEFER)
|
||||
return ERR_CAST(desc);
|
||||
}
|
||||
|
||||
/* Then from plain _CRS GPIOs */
|
||||
|
||||
@@ -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 *edid, char *vendor)
|
||||
*/
|
||||
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++) {
|
||||
|
||||
@@ -417,6 +417,7 @@ static const struct pci_device_id pciidlist[] = {
|
||||
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),
|
||||
|
||||
@@ -392,6 +392,24 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
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(struct drm_device *dev,
|
||||
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;
|
||||
|
||||
@@ -37,8 +37,6 @@
|
||||
|
||||
#include <drm/drm_pciids.h>
|
||||
|
||||
static int mga_driver_device_is_agp(struct drm_device *dev);
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
mga_PCI_IDS
|
||||
};
|
||||
@@ -66,7 +64,6 @@ static struct drm_driver driver = {
|
||||
.lastclose = mga_driver_lastclose,
|
||||
.set_busid = drm_pci_set_busid,
|
||||
.dma_quiescent = mga_driver_dma_quiescent,
|
||||
.device_is_agp = mga_driver_device_is_agp,
|
||||
.get_vblank_counter = mga_get_vblank_counter,
|
||||
.enable_vblank = mga_enable_vblank,
|
||||
.disable_vblank = mga_disable_vblank,
|
||||
@@ -107,37 +104,3 @@ module_exit(mga_exit);
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
||||
/**
|
||||
* Determine if the device really is AGP or not.
|
||||
*
|
||||
* In addition to the usual tests performed by \c drm_device_is_agp, this
|
||||
* function detects PCI G450 cards that appear to the system exactly like
|
||||
* AGP G450 cards.
|
||||
*
|
||||
* \param dev The device to be tested.
|
||||
*
|
||||
* \returns
|
||||
* If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
|
||||
*/
|
||||
static int mga_driver_device_is_agp(struct drm_device *dev)
|
||||
{
|
||||
const struct pci_dev *const pdev = dev->pdev;
|
||||
|
||||
/* There are PCI versions of the G450. These cards have the
|
||||
* same PCI ID as the AGP G450, but have an additional PCI-to-PCI
|
||||
* bridge chip. We detect these cards, which are not currently
|
||||
* supported by this driver, by looking at the device ID of the
|
||||
* bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the
|
||||
* device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
|
||||
* device.
|
||||
*/
|
||||
|
||||
if ((pdev->device == 0x0525) && pdev->bus->self
|
||||
&& (pdev->bus->self->vendor == 0x3388)
|
||||
&& (pdev->bus->self->device == 0x0021)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -311,4 +311,7 @@ static inline void adreno_gpu_write(struct adreno_gpu *gpu,
|
||||
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__ */
|
||||
|
||||
@@ -408,6 +408,7 @@ static int sun4i_backend_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct of_device_id sun4i_backend_of_table[] = {
|
||||
{ .compatible = "allwinner,sun5i-a13-display-backend" },
|
||||
{ .compatible = "allwinner,sun6i-a31-display-backend" },
|
||||
{ .compatible = "allwinner,sun8i-a33-display-backend" },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -201,12 +201,15 @@ static const struct component_master_ops sun4i_drv_master_ops = {
|
||||
static bool sun4i_drv_node_is_frontend(struct device_node *node)
|
||||
{
|
||||
return of_device_is_compatible(node, "allwinner,sun5i-a13-display-frontend") ||
|
||||
of_device_is_compatible(node, "allwinner,sun6i-a31-display-frontend") ||
|
||||
of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend");
|
||||
}
|
||||
|
||||
static bool sun4i_drv_node_is_tcon(struct device_node *node)
|
||||
{
|
||||
return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
|
||||
of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
|
||||
of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
|
||||
of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
|
||||
}
|
||||
|
||||
@@ -322,6 +325,8 @@ static int sun4i_drv_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct of_device_id sun4i_drv_of_table[] = {
|
||||
{ .compatible = "allwinner,sun5i-a13-display-engine" },
|
||||
{ .compatible = "allwinner,sun6i-a31-display-engine" },
|
||||
{ .compatible = "allwinner,sun6i-a31s-display-engine" },
|
||||
{ .compatible = "allwinner,sun8i-a33-display-engine" },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/component.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -62,7 +63,7 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(!tcon->has_channel_1);
|
||||
WARN_ON(!tcon->quirks->has_channel_1);
|
||||
regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
|
||||
SUN4I_TCON1_CTL_TCON_ENABLE, 0);
|
||||
clk_disable_unprepare(tcon->sclk1);
|
||||
@@ -80,7 +81,7 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(!tcon->has_channel_1);
|
||||
WARN_ON(!tcon->quirks->has_channel_1);
|
||||
regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
|
||||
SUN4I_TCON1_CTL_TCON_ENABLE,
|
||||
SUN4I_TCON1_CTL_TCON_ENABLE);
|
||||
@@ -202,7 +203,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
||||
u8 clk_delay;
|
||||
u32 val;
|
||||
|
||||
WARN_ON(!tcon->has_channel_1);
|
||||
WARN_ON(!tcon->quirks->has_channel_1);
|
||||
|
||||
/* Adjust clock delay */
|
||||
clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
|
||||
@@ -266,7 +267,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
||||
/*
|
||||
* FIXME: Undocumented bits
|
||||
*/
|
||||
if (tcon->has_mux)
|
||||
if (tcon->quirks->has_unknown_mux)
|
||||
regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(sun4i_tcon1_mode_set);
|
||||
@@ -327,7 +328,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
|
||||
return PTR_ERR(tcon->sclk0);
|
||||
}
|
||||
|
||||
if (tcon->has_channel_1) {
|
||||
if (tcon->quirks->has_channel_1) {
|
||||
tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
|
||||
if (IS_ERR(tcon->sclk1)) {
|
||||
dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
|
||||
@@ -487,14 +488,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
|
||||
drv->tcon = tcon;
|
||||
tcon->drm = drm;
|
||||
tcon->dev = dev;
|
||||
|
||||
if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) {
|
||||
tcon->has_mux = true;
|
||||
tcon->has_channel_1 = true;
|
||||
} else {
|
||||
tcon->has_mux = false;
|
||||
tcon->has_channel_1 = false;
|
||||
}
|
||||
tcon->quirks = of_device_get_match_data(dev);
|
||||
|
||||
tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
|
||||
if (IS_ERR(tcon->lcd_rst)) {
|
||||
@@ -588,9 +582,28 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
|
||||
.has_unknown_mux = true,
|
||||
.has_channel_1 = true,
|
||||
};
|
||||
|
||||
static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
|
||||
.has_channel_1 = true,
|
||||
};
|
||||
|
||||
static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
|
||||
.has_channel_1 = true,
|
||||
};
|
||||
|
||||
static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
|
||||
/* nothing is supported */
|
||||
};
|
||||
|
||||
static const struct of_device_id sun4i_tcon_of_table[] = {
|
||||
{ .compatible = "allwinner,sun5i-a13-tcon" },
|
||||
{ .compatible = "allwinner,sun8i-a33-tcon" },
|
||||
{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
|
||||
{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
|
||||
{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
|
||||
{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
|
||||
|
||||
@@ -142,6 +142,11 @@
|
||||
|
||||
#define SUN4I_TCON_MAX_CHANNELS 2
|
||||
|
||||
struct sun4i_tcon_quirks {
|
||||
bool has_unknown_mux; /* sun5i has undocumented mux */
|
||||
bool has_channel_1; /* a33 does not have channel 1 */
|
||||
};
|
||||
|
||||
struct sun4i_tcon {
|
||||
struct device *dev;
|
||||
struct drm_device *drm;
|
||||
@@ -160,12 +165,10 @@ struct sun4i_tcon {
|
||||
/* Reset control */
|
||||
struct reset_control *lcd_rst;
|
||||
|
||||
/* Platform adjustments */
|
||||
bool has_mux;
|
||||
|
||||
struct drm_panel *panel;
|
||||
|
||||
bool has_channel_1;
|
||||
/* Platform adjustments */
|
||||
const struct sun4i_tcon_quirks *quirks;
|
||||
};
|
||||
|
||||
struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
|
||||
|
||||
@@ -179,7 +179,7 @@ int ttm_base_object_init(struct ttm_object_file *tfile,
|
||||
if (unlikely(ret != 0))
|
||||
goto out_err0;
|
||||
|
||||
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
|
||||
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_err1;
|
||||
|
||||
@@ -318,7 +318,8 @@ EXPORT_SYMBOL(ttm_ref_object_exists);
|
||||
|
||||
int ttm_ref_object_add(struct ttm_object_file *tfile,
|
||||
struct ttm_base_object *base,
|
||||
enum ttm_ref_type ref_type, bool *existed)
|
||||
enum ttm_ref_type ref_type, bool *existed,
|
||||
bool require_existed)
|
||||
{
|
||||
struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
|
||||
struct ttm_ref_object *ref;
|
||||
@@ -345,6 +346,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
if (require_existed)
|
||||
return -EPERM;
|
||||
|
||||
ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
|
||||
false, false);
|
||||
if (unlikely(ret != 0))
|
||||
@@ -635,7 +639,7 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
|
||||
prime = (struct ttm_prime_object *) dma_buf->priv;
|
||||
base = &prime->base;
|
||||
*handle = base->hash.key;
|
||||
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
|
||||
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
|
||||
|
||||
dma_buf_put(dma_buf);
|
||||
|
||||
|
||||
@@ -538,7 +538,7 @@ int vmw_fence_create(struct vmw_fence_manager *fman,
|
||||
struct vmw_fence_obj **p_fence)
|
||||
{
|
||||
struct vmw_fence_obj *fence;
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
|
||||
if (unlikely(fence == NULL))
|
||||
@@ -701,6 +701,41 @@ void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vmw_fence_obj_lookup - Look up a user-space fence object
|
||||
*
|
||||
* @tfile: A struct ttm_object_file identifying the caller.
|
||||
* @handle: A handle identifying the fence object.
|
||||
* @return: A struct vmw_user_fence base ttm object on success or
|
||||
* an error pointer on failure.
|
||||
*
|
||||
* The fence object is looked up and type-checked. The caller needs
|
||||
* to have opened the fence object first, but since that happens on
|
||||
* creation and fence objects aren't shareable, that's not an
|
||||
* issue currently.
|
||||
*/
|
||||
static struct ttm_base_object *
|
||||
vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle)
|
||||
{
|
||||
struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle);
|
||||
|
||||
if (!base) {
|
||||
pr_err("Invalid fence object handle 0x%08lx.\n",
|
||||
(unsigned long)handle);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (base->refcount_release != vmw_user_fence_base_release) {
|
||||
pr_err("Invalid fence object handle 0x%08lx.\n",
|
||||
(unsigned long)handle);
|
||||
ttm_base_object_unref(&base);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
@@ -726,13 +761,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
|
||||
arg->kernel_cookie = jiffies + wait_timeout;
|
||||
}
|
||||
|
||||
base = ttm_base_object_lookup(tfile, arg->handle);
|
||||
if (unlikely(base == NULL)) {
|
||||
printk(KERN_ERR "Wait invalid fence object handle "
|
||||
"0x%08lx.\n",
|
||||
(unsigned long)arg->handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
base = vmw_fence_obj_lookup(tfile, arg->handle);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
fence = &(container_of(base, struct vmw_user_fence, base)->fence);
|
||||
|
||||
@@ -771,13 +802,9 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
|
||||
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
|
||||
struct vmw_private *dev_priv = vmw_priv(dev);
|
||||
|
||||
base = ttm_base_object_lookup(tfile, arg->handle);
|
||||
if (unlikely(base == NULL)) {
|
||||
printk(KERN_ERR "Fence signaled invalid fence object handle "
|
||||
"0x%08lx.\n",
|
||||
(unsigned long)arg->handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
base = vmw_fence_obj_lookup(tfile, arg->handle);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
fence = &(container_of(base, struct vmw_user_fence, base)->fence);
|
||||
fman = fman_from_fence(fence);
|
||||
@@ -1024,6 +1051,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
|
||||
(struct drm_vmw_fence_event_arg *) data;
|
||||
struct vmw_fence_obj *fence = NULL;
|
||||
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
|
||||
struct ttm_object_file *tfile = vmw_fp->tfile;
|
||||
struct drm_vmw_fence_rep __user *user_fence_rep =
|
||||
(struct drm_vmw_fence_rep __user *)(unsigned long)
|
||||
arg->fence_rep;
|
||||
@@ -1037,24 +1065,18 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
|
||||
*/
|
||||
if (arg->handle) {
|
||||
struct ttm_base_object *base =
|
||||
ttm_base_object_lookup_for_ref(dev_priv->tdev,
|
||||
arg->handle);
|
||||
vmw_fence_obj_lookup(tfile, arg->handle);
|
||||
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
if (unlikely(base == NULL)) {
|
||||
DRM_ERROR("Fence event invalid fence object handle "
|
||||
"0x%08lx.\n",
|
||||
(unsigned long)arg->handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
fence = &(container_of(base, struct vmw_user_fence,
|
||||
base)->fence);
|
||||
(void) vmw_fence_obj_reference(fence);
|
||||
|
||||
if (user_fence_rep != NULL) {
|
||||
bool existed;
|
||||
|
||||
ret = ttm_ref_object_add(vmw_fp->tfile, base,
|
||||
TTM_REF_USAGE, &existed);
|
||||
TTM_REF_USAGE, NULL, false);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed to reference a fence "
|
||||
"object.\n");
|
||||
@@ -1097,8 +1119,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
out_no_create:
|
||||
if (user_fence_rep != NULL)
|
||||
ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
|
||||
handle, TTM_REF_USAGE);
|
||||
ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
|
||||
out_no_ref_obj:
|
||||
vmw_fence_obj_unreference(&fence);
|
||||
return ret;
|
||||
|
||||
@@ -114,8 +114,6 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
param->value = dev_priv->has_dx;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Illegal vmwgfx get param request: %d\n",
|
||||
param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -186,7 +184,7 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
|
||||
bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
|
||||
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
|
||||
|
||||
if (unlikely(arg->pad64 != 0)) {
|
||||
if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
|
||||
DRM_ERROR("Illegal GET_3D_CAP argument.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -589,7 +589,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,
|
||||
return ret;
|
||||
|
||||
ret = ttm_ref_object_add(tfile, &user_bo->prime.base,
|
||||
TTM_REF_SYNCCPU_WRITE, &existed);
|
||||
TTM_REF_SYNCCPU_WRITE, &existed, false);
|
||||
if (ret != 0 || existed)
|
||||
ttm_bo_synccpu_write_release(&user_bo->dma.base);
|
||||
|
||||
@@ -773,7 +773,7 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
|
||||
|
||||
*handle = user_bo->prime.base.hash.key;
|
||||
return ttm_ref_object_add(tfile, &user_bo->prime.base,
|
||||
TTM_REF_USAGE, NULL);
|
||||
TTM_REF_USAGE, NULL, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -713,11 +713,14 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
128;
|
||||
|
||||
num_sizes = 0;
|
||||
for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
|
||||
for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
|
||||
if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
|
||||
return -EINVAL;
|
||||
num_sizes += req->mip_levels[i];
|
||||
}
|
||||
|
||||
if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
|
||||
DRM_VMW_MAX_MIP_LEVELS)
|
||||
if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
|
||||
num_sizes == 0)
|
||||
return -EINVAL;
|
||||
|
||||
size = vmw_user_surface_size + 128 +
|
||||
@@ -891,17 +894,16 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
|
||||
uint32_t handle;
|
||||
struct ttm_base_object *base;
|
||||
int ret;
|
||||
bool require_exist = false;
|
||||
|
||||
if (handle_type == DRM_VMW_HANDLE_PRIME) {
|
||||
ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
|
||||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
} else {
|
||||
if (unlikely(drm_is_render_client(file_priv))) {
|
||||
DRM_ERROR("Render client refused legacy "
|
||||
"surface reference.\n");
|
||||
return -EACCES;
|
||||
}
|
||||
if (unlikely(drm_is_render_client(file_priv)))
|
||||
require_exist = true;
|
||||
|
||||
if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {
|
||||
DRM_ERROR("Locked master refused legacy "
|
||||
"surface reference.\n");
|
||||
@@ -929,17 +931,14 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
|
||||
|
||||
/*
|
||||
* Make sure the surface creator has the same
|
||||
* authenticating master.
|
||||
* authenticating master, or is already registered with us.
|
||||
*/
|
||||
if (drm_is_primary_client(file_priv) &&
|
||||
user_srf->master != file_priv->master) {
|
||||
DRM_ERROR("Trying to reference surface outside of"
|
||||
" master domain.\n");
|
||||
ret = -EACCES;
|
||||
goto out_bad_resource;
|
||||
}
|
||||
user_srf->master != file_priv->master)
|
||||
require_exist = true;
|
||||
|
||||
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
|
||||
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
|
||||
require_exist);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Could not add a reference to a surface.\n");
|
||||
goto out_bad_resource;
|
||||
|
||||
@@ -728,7 +728,6 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
|
||||
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_have_special_driver[] = {
|
||||
{ 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) },
|
||||
|
||||
+12
-3
@@ -318,8 +318,11 @@
|
||||
#define USB_VENDOR_ID_DMI 0x0c0b
|
||||
#define USB_DEVICE_ID_DMI_ENC 0x5fab
|
||||
|
||||
#define USB_VENDOR_ID_DRAGONRISE 0x0079
|
||||
#define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800
|
||||
#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
|
||||
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
|
||||
@@ -365,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
|
||||
|
||||
@@ -722,7 +728,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
|
||||
@@ -1037,6 +1042,10 @@
|
||||
#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500
|
||||
#define USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET 0x0502
|
||||
|
||||
#define USB_VENDOR_ID_WEIDA 0x2575
|
||||
#define USB_DEVICE_ID_WEIDA_8752 0xC300
|
||||
#define USB_DEVICE_ID_WEIDA_8755 0xC301
|
||||
|
||||
#define USB_VENDOR_ID_WISEGROUP 0x0925
|
||||
#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005
|
||||
#define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888
|
||||
|
||||
@@ -282,8 +282,6 @@ static const struct hid_device_id ms_devices[] = {
|
||||
.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),
|
||||
|
||||
@@ -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_device *hdev, struct hid_report *report)
|
||||
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);
|
||||
@@ -842,7 +840,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
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;
|
||||
|
||||
/*
|
||||
@@ -1083,36 +1083,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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");
|
||||
@@ -1136,6 +1106,39 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
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;
|
||||
@@ -1204,8 +1207,11 @@ static int mt_resume(struct hid_device *hdev)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -796,6 +796,12 @@ static const struct hid_device_id sensor_hub_devices[] = {
|
||||
{ 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_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},
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
|
||||
#include <linux/i2c/i2c-hid.h>
|
||||
|
||||
#include "../hid-ids.h"
|
||||
|
||||
/* quirks to control the device */
|
||||
#define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0)
|
||||
|
||||
/* flags */
|
||||
#define I2C_HID_STARTED 0
|
||||
#define I2C_HID_RESET_PENDING 1
|
||||
@@ -143,6 +148,7 @@ struct i2c_hid {
|
||||
char *argsbuf; /* Command arguments buffer */
|
||||
|
||||
unsigned long flags; /* device flags */
|
||||
unsigned long quirks; /* Various quirks */
|
||||
|
||||
wait_queue_head_t wait; /* For waiting the interrupt */
|
||||
struct gpio_desc *desc;
|
||||
@@ -154,6 +160,39 @@ struct i2c_hid {
|
||||
struct mutex reset_lock;
|
||||
};
|
||||
|
||||
static const struct i2c_hid_quirks {
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u32 quirks;
|
||||
} i2c_hid_quirks[] = {
|
||||
{ USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8752,
|
||||
I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
|
||||
{ USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8755,
|
||||
I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* i2c_hid_lookup_quirk: return any quirks associated with a I2C HID device
|
||||
* @idVendor: the 16-bit vendor ID
|
||||
* @idProduct: the 16-bit product ID
|
||||
*
|
||||
* Returns: a u32 quirks value.
|
||||
*/
|
||||
static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
|
||||
{
|
||||
u32 quirks = 0;
|
||||
int n;
|
||||
|
||||
for (n = 0; i2c_hid_quirks[n].idVendor; n++)
|
||||
if (i2c_hid_quirks[n].idVendor == idVendor &&
|
||||
(i2c_hid_quirks[n].idProduct == (__u16)HID_ANY_ID ||
|
||||
i2c_hid_quirks[n].idProduct == idProduct))
|
||||
quirks = i2c_hid_quirks[n].quirks;
|
||||
|
||||
return quirks;
|
||||
}
|
||||
|
||||
static int __i2c_hid_command(struct i2c_client *client,
|
||||
const struct i2c_hid_cmd *command, u8 reportID,
|
||||
u8 reportType, u8 *args, int args_len,
|
||||
@@ -346,11 +385,27 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
|
||||
|
||||
i2c_hid_dbg(ihid, "%s\n", __func__);
|
||||
|
||||
/*
|
||||
* Some devices require to send a command to wakeup before power on.
|
||||
* The call will get a return value (EREMOTEIO) but device will be
|
||||
* triggered and activated. After that, it goes like a normal device.
|
||||
*/
|
||||
if (power_state == I2C_HID_PWR_ON &&
|
||||
ihid->quirks & I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV) {
|
||||
ret = i2c_hid_command(client, &hid_set_power_cmd, NULL, 0);
|
||||
|
||||
/* Device was already activated */
|
||||
if (!ret)
|
||||
goto set_pwr_exit;
|
||||
}
|
||||
|
||||
ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
|
||||
0, NULL, 0, NULL, 0);
|
||||
|
||||
if (ret)
|
||||
dev_err(&client->dev, "failed to change power setting.\n");
|
||||
|
||||
set_pwr_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1050,6 +1105,8 @@ static int i2c_hid_probe(struct i2c_client *client,
|
||||
client->name, hid->vendor, hid->product);
|
||||
strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
|
||||
|
||||
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
if (ret != -ENODEV)
|
||||
|
||||
@@ -83,10 +83,14 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
@@ -103,7 +107,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 },
|
||||
|
||||
@@ -2896,6 +2896,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
@@ -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_atom = {
|
||||
.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_idle_ids[] __initconst = {
|
||||
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),
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/delay.h>
|
||||
#include "bmg160.h"
|
||||
|
||||
#define BMG160_IRQ_NAME "bmg160_event"
|
||||
@@ -52,6 +53,9 @@
|
||||
#define BMG160_DEF_BW 100
|
||||
#define BMG160_REG_PMU_BW_RES BIT(7)
|
||||
|
||||
#define BMG160_GYRO_REG_RESET 0x14
|
||||
#define BMG160_GYRO_RESET_VAL 0xb6
|
||||
|
||||
#define BMG160_REG_INT_MAP_0 0x17
|
||||
#define BMG160_INT_MAP_0_BIT_ANY BIT(1)
|
||||
|
||||
@@ -236,6 +240,14 @@ static int bmg160_chip_init(struct bmg160_data *data)
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
/*
|
||||
* Reset chip to get it in a known good state. A delay of 30ms after
|
||||
* reset is required according to the datasheet.
|
||||
*/
|
||||
regmap_write(data->regmap, BMG160_GYRO_REG_RESET,
|
||||
BMG160_GYRO_RESET_VAL);
|
||||
usleep_range(30000, 30700);
|
||||
|
||||
ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Error reading reg_chip_id\n");
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_gpio.h>
|
||||
@@ -35,6 +36,7 @@
|
||||
struct gpio_button_data {
|
||||
const struct gpio_keys_button *button;
|
||||
struct input_dev *input;
|
||||
struct gpio_desc *gpiod;
|
||||
|
||||
struct timer_list release_timer;
|
||||
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
|
||||
@@ -140,7 +142,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
|
||||
*/
|
||||
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(struct gpio_button_data *bdata)
|
||||
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 *data)
|
||||
{
|
||||
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 platform_device *pdev,
|
||||
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;
|
||||
|
||||
error = devm_gpio_request_one(&pdev->dev, button->gpio,
|
||||
GPIOF_IN, desc);
|
||||
if (button->active_low)
|
||||
flags |= GPIOF_ACTIVE_LOW;
|
||||
|
||||
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 platform_device *pdev,
|
||||
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(struct gpio_keys_drvdata *ddata)
|
||||
|
||||
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);
|
||||
|
||||
@@ -3589,7 +3589,7 @@ static int raid_preresume(struct dm_target *ti)
|
||||
return r;
|
||||
|
||||
/* Resize bitmap to adjust to changed region size (aka MD bitmap chunksize) */
|
||||
if (test_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags) &&
|
||||
if (test_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags) && mddev->bitmap &&
|
||||
mddev->bitmap_info.chunksize != to_bytes(rs->requested_bitmap_chunk_sectors)) {
|
||||
r = bitmap_resize(mddev->bitmap, mddev->dev_sectors,
|
||||
to_bytes(rs->requested_bitmap_chunk_sectors), 0);
|
||||
|
||||
@@ -147,8 +147,6 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
|
||||
block = fec_buffer_rs_block(v, fio, n, i);
|
||||
res = fec_decode_rs8(v, fio, block, &par[offset], neras);
|
||||
if (res < 0) {
|
||||
dm_bufio_release(buf);
|
||||
|
||||
r = res;
|
||||
goto error;
|
||||
}
|
||||
@@ -173,6 +171,8 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
|
||||
done:
|
||||
r = corrected;
|
||||
error:
|
||||
dm_bufio_release(buf);
|
||||
|
||||
if (r < 0 && neras)
|
||||
DMERR_LIMIT("%s: FEC %llu: failed to correct: %d",
|
||||
v->data_dev->name, (unsigned long long)rsb, r);
|
||||
@@ -272,7 +272,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
|
||||
&is_zero) == 0) {
|
||||
/* skip known zero blocks entirely */
|
||||
if (is_zero)
|
||||
continue;
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* skip if we have already found the theoretical
|
||||
|
||||
@@ -524,7 +524,9 @@ static const struct sdhci_ops sdhci_msm_ops = {
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
@@ -559,16 +559,19 @@ static const struct sdhci_ops sdhci_esdhc_le_ops = {
|
||||
};
|
||||
|
||||
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 platform_device *pdev)
|
||||
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"))
|
||||
|
||||
@@ -4020,49 +4020,51 @@ int mlx4_restart_one(struct pci_dev *pdev)
|
||||
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, }
|
||||
};
|
||||
|
||||
|
||||
@@ -2238,14 +2238,16 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
|
||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
enum nl80211_iftype iftype;
|
||||
bool wait_for_disable = false;
|
||||
int err;
|
||||
|
||||
brcmf_dbg(TRACE, "delete P2P vif\n");
|
||||
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
||||
|
||||
iftype = vif->wdev.iftype;
|
||||
brcmf_cfg80211_arm_vif_event(cfg, vif);
|
||||
switch (vif->wdev.iftype) {
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
|
||||
wait_for_disable = true;
|
||||
@@ -2275,7 +2277,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
BRCMF_P2P_DISABLE_TIMEOUT);
|
||||
|
||||
err = 0;
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) {
|
||||
if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
|
||||
brcmf_vif_clear_mgmt_ies(vif);
|
||||
err = brcmf_p2p_release_p2p_if(vif);
|
||||
}
|
||||
@@ -2291,7 +2293,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
brcmf_remove_interface(vif->ifp, true);
|
||||
|
||||
brcmf_cfg80211_arm_vif_event(cfg, NULL);
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
|
||||
if (iftype != NL80211_IFTYPE_P2P_DEVICE)
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
|
||||
|
||||
return err;
|
||||
|
||||
@@ -1204,8 +1204,8 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
|
||||
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)
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -284,35 +284,16 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
|
||||
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_config_window *cfg)
|
||||
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,
|
||||
|
||||
+84
-17
@@ -1634,6 +1634,7 @@ static void quirk_pcie_mch(struct pci_dev *pdev)
|
||||
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);
|
||||
|
||||
|
||||
/*
|
||||
@@ -2156,7 +2157,7 @@ static void quirk_blacklist_vpd(struct pci_dev *dev)
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2240,6 +2241,27 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_BROADCOM,
|
||||
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
|
||||
@@ -3114,30 +3136,32 @@ static void quirk_remove_d3_delay(struct pci_dev *dev)
|
||||
{
|
||||
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);
|
||||
/* 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, 0x8c2d, 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, 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, 0x8c26, 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
|
||||
@@ -4136,6 +4160,26 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
|
||||
return acs_flags & ~flags ? 0 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
@@ -4151,15 +4195,35 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
|
||||
*
|
||||
* 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)
|
||||
@@ -4272,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 },
|
||||
|
||||
@@ -355,6 +355,32 @@ static const struct dmi_system_id acer_blacklist[] __initconst = {
|
||||
{}
|
||||
};
|
||||
|
||||
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_quirks[] __initconst = {
|
||||
},
|
||||
.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;
|
||||
}
|
||||
@@ -2107,6 +2145,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.
|
||||
*/
|
||||
|
||||
@@ -116,6 +116,10 @@ static struct quirk_entry quirk_asus_ux303ub = {
|
||||
.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_quirks[] = {
|
||||
},
|
||||
.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,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -156,6 +156,11 @@ 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
|
||||
|
||||
static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
|
||||
|
||||
struct bios_args {
|
||||
u32 arg0;
|
||||
u32 arg1;
|
||||
@@ -1080,6 +1085,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
|
||||
*/
|
||||
@@ -2025,6 +2053,16 @@ static int asus_wmi_fan_init(struct asus_wmi *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
|
||||
*/
|
||||
@@ -2069,6 +2107,13 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
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)
|
||||
@@ -2087,6 +2132,9 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
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)
|
||||
@@ -2105,10 +2153,6 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_hba_qcom_vops = {
|
||||
.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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -128,26 +128,23 @@ 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)
|
||||
|
||||
/*
|
||||
* 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_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_ */
|
||||
|
||||
+143
-11
@@ -124,6 +124,7 @@ enum {
|
||||
UFSHCD_STATE_RESET,
|
||||
UFSHCD_STATE_ERROR,
|
||||
UFSHCD_STATE_OPERATIONAL,
|
||||
UFSHCD_STATE_EH_SCHEDULED,
|
||||
};
|
||||
|
||||
/* UFSHCD error handling flags */
|
||||
@@ -189,6 +190,30 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl)
|
||||
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);
|
||||
@@ -1089,7 +1114,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
|
||||
*
|
||||
* 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;
|
||||
@@ -1103,8 +1128,13 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
|
||||
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;
|
||||
|
||||
@@ -1411,6 +1441,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
||||
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;
|
||||
@@ -1477,7 +1508,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
||||
|
||||
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);
|
||||
@@ -2332,12 +2363,21 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
|
||||
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 =
|
||||
@@ -3102,7 +3142,16 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -3128,6 +3177,12 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
|
||||
/* 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)
|
||||
@@ -4187,7 +4242,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba)
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
@@ -4994,6 +5049,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)) {
|
||||
@@ -5004,6 +5129,11 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
|
||||
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);
|
||||
|
||||
ufshcd_vops_apply_dev_quirks(hba);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6595,10 +6725,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
|
||||
ufshcd_init_latency_hist(hba);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -474,6 +476,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. */
|
||||
@@ -801,6 +809,13 @@ static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1075,15 +1075,15 @@ static int omap8250_no_handle_irq(struct uart_port *port)
|
||||
}
|
||||
|
||||
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 platform_device *pdev)
|
||||
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.
|
||||
|
||||
@@ -24,7 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
|
||||
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_hdrc_msm_platdata = {
|
||||
.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,
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user