Merge tag 'ASB-2024-09-05_4.19-stable' of https://android.googlesource.com/kernel/common into android13-4.19-kona
https://source.android.com/docs/security/bulletin/2024-09-01 CVE-2024-36972 * tag 'ASB-2024-09-05_4.19-stable' of https://android.googlesource.com/kernel/common: (331 commits) Linux 4.19.321 drm/fb-helper: set x/yres_virtual in drm_fb_helper_check_var ipc: remove memcg accounting for sops objects in do_semtimedop() scsi: aacraid: Fix double-free on probe failure usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in remove_power_attributes() usb: dwc3: st: fix probed platform device ref count on probe error path usb: dwc3: core: Prevent USB core invalid event buffer address access usb: dwc3: omap: add missing depopulate in probe error path USB: serial: option: add MeiG Smart SRM825L cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller net: busy-poll: use ktime_get_ns() instead of local_clock() gtp: fix a potential NULL pointer dereference soundwire: stream: fix programming slave ports for non-continous port maps net: prevent mss overflow in skb_segment() ida: Fix crash in ida_free when the bitmap is empty net:rds: Fix possible deadlock in rds_message_put fbmem: Check virtual screen sizes in fb_set_var() fbcon: Prevent that screen size is smaller than font size memcg: enable accounting of ipc resources cgroup/cpuset: Prevent UAF in proc_cpuset_show() ... Conflicts: Documentation/arm64/silicon-errata.txt arch/arm64/include/asm/cpucaps.h arch/arm64/kernel/cpu_errata.c drivers/mmc/core/mmc_test.c Change-Id: Ibfaed509d545f9895e5d515f4e237d9c97c2086d
This commit is contained in:
@@ -61,8 +61,26 @@ stable kernels.
|
||||
| ARM | Cortex-A73 | #858921 | ARM64_ERRATUM_858921 |
|
||||
| ARM | Cortex-A55 | #1024718 | ARM64_ERRATUM_1024718 |
|
||||
| ARM | Cortex-A76 | #1463225 | ARM64_ERRATUM_1463225 |
|
||||
| ARM | Cortex-A76 | #3324349 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A77 | #3324348 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A78 | #3324344 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A78C | #3324346,3324347| ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-X1C | #3324346 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-X2 | #3324338 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-X3 | #3324335 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-X4 | #3194386 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-X925 | #3324334 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Cortex-A77 | #1542418 | ARM64_ERRATUM_1542418 |
|
||||
| ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 |
|
||||
| ARM | Neoverse-N1 | #3324349 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 |
|
||||
| ARM | MMU-500 | #841119,#826419 | N/A |
|
||||
| | | | |
|
||||
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
|
||||
|
||||
@@ -299,17 +299,25 @@ functions is used.
|
||||
The header file linux/hwmon-sysfs.h provides a number of useful macros to
|
||||
declare and use hardware monitoring sysfs attributes.
|
||||
|
||||
In many cases, you can use the exsting define DEVICE_ATTR to declare such
|
||||
attributes. This is feasible if an attribute has no additional context. However,
|
||||
in many cases there will be additional information such as a sensor index which
|
||||
will need to be passed to the sysfs attribute handling function.
|
||||
In many cases, you can use the exsting define DEVICE_ATTR or its variants
|
||||
DEVICE_ATTR_{RW,RO,WO} to declare such attributes. This is feasible if an
|
||||
attribute has no additional context. However, in many cases there will be
|
||||
additional information such as a sensor index which will need to be passed
|
||||
to the sysfs attribute handling function.
|
||||
|
||||
SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 can be used to define attributes
|
||||
which need such additional context information. SENSOR_DEVICE_ATTR requires
|
||||
one additional argument, SENSOR_DEVICE_ATTR_2 requires two.
|
||||
|
||||
SENSOR_DEVICE_ATTR defines a struct sensor_device_attribute variable.
|
||||
This structure has the following fields.
|
||||
Simplified variants of SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 are available
|
||||
and should be used if standard attribute permissions and function names are
|
||||
feasible. Standard permissions are 0644 for SENSOR_DEVICE_ATTR[_2]_RW,
|
||||
0444 for SENSOR_DEVICE_ATTR[_2]_RO, and 0200 for SENSOR_DEVICE_ATTR[_2]_WO.
|
||||
Standard functions, similar to DEVICE_ATTR_{RW,RO,WO}, have _show and _store
|
||||
appended to the provided function name.
|
||||
|
||||
SENSOR_DEVICE_ATTR and its variants define a struct sensor_device_attribute
|
||||
variable. This structure has the following fields.
|
||||
|
||||
struct sensor_device_attribute {
|
||||
struct device_attribute dev_attr;
|
||||
@@ -320,8 +328,8 @@ You can use to_sensor_dev_attr to get the pointer to this structure from the
|
||||
attribute read or write function. Its parameter is the device to which the
|
||||
attribute is attached.
|
||||
|
||||
SENSOR_DEVICE_ATTR_2 defines a struct sensor_device_attribute_2 variable,
|
||||
which is defined as follows.
|
||||
SENSOR_DEVICE_ATTR_2 and its variants define a struct sensor_device_attribute_2
|
||||
variable, which is defined as follows.
|
||||
|
||||
struct sensor_device_attribute_2 {
|
||||
struct device_attribute dev_attr;
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 19
|
||||
SUBLEVEL = 318
|
||||
SUBLEVEL = 321
|
||||
EXTRAVERSION =
|
||||
NAME = "People's Front"
|
||||
|
||||
|
||||
@@ -145,16 +145,6 @@ extern int __get_user_64t_1(void *);
|
||||
extern int __get_user_64t_2(void *);
|
||||
extern int __get_user_64t_4(void *);
|
||||
|
||||
#define __GUP_CLOBBER_1 "lr", "cc"
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
#define __GUP_CLOBBER_2 "ip", "lr", "cc"
|
||||
#else
|
||||
#define __GUP_CLOBBER_2 "lr", "cc"
|
||||
#endif
|
||||
#define __GUP_CLOBBER_4 "lr", "cc"
|
||||
#define __GUP_CLOBBER_32t_8 "lr", "cc"
|
||||
#define __GUP_CLOBBER_8 "lr", "cc"
|
||||
|
||||
#define __get_user_x(__r2, __p, __e, __l, __s) \
|
||||
__asm__ __volatile__ ( \
|
||||
__asmeq("%0", "r0") __asmeq("%1", "r2") \
|
||||
@@ -162,7 +152,7 @@ extern int __get_user_64t_4(void *);
|
||||
"bl __get_user_" #__s \
|
||||
: "=&r" (__e), "=r" (__r2) \
|
||||
: "0" (__p), "r" (__l) \
|
||||
: __GUP_CLOBBER_##__s)
|
||||
: "ip", "lr", "cc")
|
||||
|
||||
/* narrowing a double-word get into a single 32bit word register: */
|
||||
#ifdef __ARMEB__
|
||||
@@ -184,7 +174,7 @@ extern int __get_user_64t_4(void *);
|
||||
"bl __get_user_64t_" #__s \
|
||||
: "=&r" (__e), "=r" (__r2) \
|
||||
: "0" (__p), "r" (__l) \
|
||||
: __GUP_CLOBBER_##__s)
|
||||
: "ip", "lr", "cc")
|
||||
#else
|
||||
#define __get_user_x_64t __get_user_x
|
||||
#endif
|
||||
|
||||
@@ -579,6 +579,44 @@ config ARM64_ERRATUM_1742098
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_ERRATUM_3194386
|
||||
bool "Cortex-*/Neoverse-*: workaround for MSR SSBS not self-synchronizing"
|
||||
default y
|
||||
help
|
||||
This option adds the workaround for the following errata:
|
||||
|
||||
* ARM Cortex-A76 erratum 3324349
|
||||
* ARM Cortex-A77 erratum 3324348
|
||||
* ARM Cortex-A78 erratum 3324344
|
||||
* ARM Cortex-A78C erratum 3324346
|
||||
* ARM Cortex-A78C erratum 3324347
|
||||
* ARM Cortex-A710 erratam 3324338
|
||||
* ARM Cortex-A720 erratum 3456091
|
||||
* ARM Cortex-A725 erratum 3456106
|
||||
* ARM Cortex-X1 erratum 3324344
|
||||
* ARM Cortex-X1C erratum 3324346
|
||||
* ARM Cortex-X2 erratum 3324338
|
||||
* ARM Cortex-X3 erratum 3324335
|
||||
* ARM Cortex-X4 erratum 3194386
|
||||
* ARM Cortex-X925 erratum 3324334
|
||||
* ARM Neoverse-N1 erratum 3324349
|
||||
* ARM Neoverse N2 erratum 3324339
|
||||
* ARM Neoverse-V1 erratum 3324341
|
||||
* ARM Neoverse V2 erratum 3324336
|
||||
* ARM Neoverse-V3 erratum 3312417
|
||||
|
||||
On affected cores "MSR SSBS, #0" instructions may not affect
|
||||
subsequent speculative instructions, which may permit unexepected
|
||||
speculative store bypassing.
|
||||
|
||||
Work around this problem by placing a Speculation Barrier (SB) or
|
||||
Instruction Synchronization Barrier (ISB) after kernel changes to
|
||||
SSBS. The presence of the SSBS special-purpose register is hidden
|
||||
from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such that userspace
|
||||
will use the PR_SPEC_STORE_BYPASS prctl to change SSBS.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CAVIUM_ERRATUM_22375
|
||||
bool "Cavium erratum 22375, 24313"
|
||||
default y
|
||||
|
||||
@@ -649,8 +649,8 @@
|
||||
<0>, <24000000>,
|
||||
<24000000>, <24000000>,
|
||||
<15000000>, <15000000>,
|
||||
<100000000>, <100000000>,
|
||||
<100000000>, <100000000>,
|
||||
<300000000>, <100000000>,
|
||||
<400000000>, <100000000>,
|
||||
<50000000>, <100000000>,
|
||||
<100000000>, <100000000>,
|
||||
<50000000>, <50000000>,
|
||||
|
||||
@@ -147,6 +147,19 @@
|
||||
hint #22
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Speculation barrier
|
||||
*/
|
||||
.macro sb
|
||||
alternative_if_not ARM64_HAS_SB
|
||||
dsb nsh
|
||||
isb
|
||||
alternative_else
|
||||
SB_BARRIER_INSN
|
||||
nop
|
||||
alternative_endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Sanitise a 64-bit bounded index wrt speculation, returning zero if out
|
||||
* of bounds.
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
#define psb_csync() asm volatile("hint #17" : : : "memory")
|
||||
#define csdb() asm volatile("hint #20" : : : "memory")
|
||||
|
||||
#define spec_bar() asm volatile(ALTERNATIVE("dsb nsh\nisb\n", \
|
||||
SB_BARRIER_INSN"nop\n", \
|
||||
ARM64_HAS_SB))
|
||||
|
||||
#define mb() dsb(sy)
|
||||
#define rmb() dsb(ld)
|
||||
#define wmb() dsb(st)
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
#define ARM64_WORKAROUND_1542419 37
|
||||
#define ARM64_SPECTRE_BHB 38
|
||||
#define ARM64_WORKAROUND_1742098 39
|
||||
#define ARM64_HAS_SB 40
|
||||
#define ARM64_WORKAROUND_SPECULATIVE_SSBS 41
|
||||
|
||||
/* kabi: reserve 40 - 62 for future cpu capabilities */
|
||||
#define ARM64_NCAPS 62
|
||||
|
||||
@@ -101,6 +101,14 @@
|
||||
#define ARM_CPU_PART_CORTEX_X2 0xD48
|
||||
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
|
||||
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
|
||||
#define ARM_CPU_PART_CORTEX_X1C 0xD4C
|
||||
#define ARM_CPU_PART_CORTEX_X3 0xD4E
|
||||
#define ARM_CPU_PART_NEOVERSE_V2 0xD4F
|
||||
#define ARM_CPU_PART_CORTEX_A720 0xD81
|
||||
#define ARM_CPU_PART_CORTEX_X4 0xD82
|
||||
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
|
||||
#define ARM_CPU_PART_CORTEX_X925 0xD85
|
||||
#define ARM_CPU_PART_CORTEX_A725 0xD87
|
||||
|
||||
#define APM_CPU_PART_POTENZA 0x000
|
||||
|
||||
@@ -147,6 +155,14 @@
|
||||
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
|
||||
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
|
||||
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
|
||||
#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
|
||||
#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3)
|
||||
#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2)
|
||||
#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720)
|
||||
#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4)
|
||||
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
|
||||
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
|
||||
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
|
||||
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
|
||||
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
|
||||
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
|
||||
|
||||
@@ -107,6 +107,11 @@
|
||||
#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift))
|
||||
#define SET_PSTATE_SSBS(x) __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift))
|
||||
|
||||
#define __SYS_BARRIER_INSN(CRm, op2, Rt) \
|
||||
__emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f))
|
||||
|
||||
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
|
||||
|
||||
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
|
||||
#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
|
||||
#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
|
||||
@@ -538,6 +543,7 @@
|
||||
#define ID_AA64ISAR0_AES_SHIFT 4
|
||||
|
||||
/* id_aa64isar1 */
|
||||
#define ID_AA64ISAR1_SB_SHIFT 36
|
||||
#define ID_AA64ISAR1_LRCPC_SHIFT 20
|
||||
#define ID_AA64ISAR1_FCMA_SHIFT 16
|
||||
#define ID_AA64ISAR1_JSCVT_SHIFT 12
|
||||
|
||||
@@ -46,8 +46,7 @@ static inline void set_fs(mm_segment_t fs)
|
||||
* Prevent a mispredicted conditional call to set_fs from forwarding
|
||||
* the wrong address limit to access_ok under speculation.
|
||||
*/
|
||||
dsb(nsh);
|
||||
isb();
|
||||
spec_bar();
|
||||
|
||||
/* On user-mode return, check fs is correct */
|
||||
set_thread_flag(TIF_FSCHECK);
|
||||
|
||||
@@ -49,5 +49,6 @@
|
||||
#define HWCAP_ILRCPC (1 << 26)
|
||||
#define HWCAP_FLAGM (1 << 27)
|
||||
#define HWCAP_SSBS (1 << 28)
|
||||
#define HWCAP_SB (1 << 29)
|
||||
|
||||
#endif /* _UAPI__ASM_HWCAP_H */
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <asm/numa.h>
|
||||
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE };
|
||||
|
||||
int __init acpi_numa_get_nid(unsigned int cpu)
|
||||
{
|
||||
|
||||
@@ -345,6 +345,19 @@ void arm64_set_ssbd_mitigation(bool state)
|
||||
asm volatile(SET_PSTATE_SSBS(0));
|
||||
else
|
||||
asm volatile(SET_PSTATE_SSBS(1));
|
||||
|
||||
/*
|
||||
* SSBS is self-synchronizing and is intended to affect
|
||||
* subsequent speculative instructions, but some CPUs can
|
||||
* speculate with a stale value of SSBS.
|
||||
*
|
||||
* Mitigate this with an unconditional speculation barrier, as
|
||||
* CPUs could mis-speculate branches and bypass a conditional
|
||||
* barrier.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386))
|
||||
spec_bar();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -743,6 +756,30 @@ static struct midr_range broken_aarch32_aes[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_3194386
|
||||
static const struct midr_range erratum_spec_ssbs_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A725),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
#if defined(CONFIG_ARM64_ERRATUM_826319) || \
|
||||
defined(CONFIG_ARM64_ERRATUM_827319) || \
|
||||
@@ -964,6 +1001,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
CAP_MIDR_RANGE_LIST(broken_aarch32_aes),
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_3194386
|
||||
{
|
||||
.desc = "SSBS not fully self-synchronizing",
|
||||
.capability = ARM64_WORKAROUND_SPECULATIVE_SSBS,
|
||||
ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
|
||||
},
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_SB_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
|
||||
@@ -273,6 +274,30 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_mvfr0[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPROUND_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSHVEC_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSQRT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDIVIDE_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPTRAP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_SIMD_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_mvfr1[] = {
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDFMAC_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPHP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDHP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDSP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDINT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDLS_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPDNAN_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPFTZ_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_mvfr2[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* FPMisc */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* SIMDMisc */
|
||||
@@ -288,10 +313,10 @@ static const struct arm64_ftr_bits ftr_dczid[] = {
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_isar5[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
@@ -331,7 +356,7 @@ static const struct arm64_ftr_bits ftr_zcr[] = {
|
||||
* Common ftr bits for a 32bit register with all hidden, strict
|
||||
* attributes, with 4bit feature fields and a default safe value of
|
||||
* 0. Covers the following 32bit registers:
|
||||
* id_isar[0-4], id_mmfr[1-3], id_pfr1, mvfr[0-1]
|
||||
* id_isar[1-3], id_mmfr[1-3]
|
||||
*/
|
||||
static const struct arm64_ftr_bits ftr_generic_32bits[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0),
|
||||
@@ -386,8 +411,8 @@ static const struct __ftr_reg_entry {
|
||||
ARM64_FTR_REG(SYS_ID_MMFR4_EL1, ftr_id_mmfr4),
|
||||
|
||||
/* Op1 = 0, CRn = 0, CRm = 3 */
|
||||
ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits),
|
||||
ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits),
|
||||
ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_mvfr0),
|
||||
ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_mvfr1),
|
||||
ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2),
|
||||
|
||||
/* Op1 = 0, CRn = 0, CRm = 4 */
|
||||
@@ -826,17 +851,39 @@ feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
|
||||
return val >= entry->min_field_value;
|
||||
}
|
||||
|
||||
static u64
|
||||
read_scoped_sysreg(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
|
||||
if (scope == SCOPE_SYSTEM)
|
||||
return read_sanitised_ftr_reg(entry->sys_reg);
|
||||
else
|
||||
return __read_sysreg_by_encoding(entry->sys_reg);
|
||||
}
|
||||
|
||||
static bool
|
||||
has_user_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
int mask;
|
||||
struct arm64_ftr_reg *regp;
|
||||
u64 val = read_scoped_sysreg(entry, scope);
|
||||
|
||||
regp = get_arm64_ftr_reg(entry->sys_reg);
|
||||
if (!regp)
|
||||
return false;
|
||||
|
||||
mask = cpuid_feature_extract_unsigned_field(regp->user_mask,
|
||||
entry->field_pos);
|
||||
if (!mask)
|
||||
return false;
|
||||
|
||||
return feature_matches(val, entry);
|
||||
}
|
||||
|
||||
static bool
|
||||
has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
|
||||
if (scope == SCOPE_SYSTEM)
|
||||
val = read_sanitised_ftr_reg(entry->sys_reg);
|
||||
else
|
||||
val = __read_sysreg_by_encoding(entry->sys_reg);
|
||||
|
||||
u64 val = read_scoped_sysreg(entry, scope);
|
||||
return feature_matches(val, entry);
|
||||
}
|
||||
|
||||
@@ -1157,6 +1204,17 @@ static void cpu_enable_ssbs(const struct arm64_cpu_capabilities *__unused)
|
||||
}
|
||||
#endif /* CONFIG_ARM64_SSBD */
|
||||
|
||||
static void user_feature_fixup(void)
|
||||
{
|
||||
if (cpus_have_cap(ARM64_WORKAROUND_SPECULATIVE_SSBS)) {
|
||||
struct arm64_ftr_reg *regp;
|
||||
|
||||
regp = get_arm64_ftr_reg(SYS_ID_AA64PFR1_EL1);
|
||||
if (regp)
|
||||
regp->user_mask &= ~GENMASK(7, 4); /* SSBS */
|
||||
}
|
||||
}
|
||||
|
||||
static void elf_hwcap_fixup(void)
|
||||
{
|
||||
#ifdef CONFIG_ARM64_ERRATUM_1742098
|
||||
@@ -1363,12 +1421,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
.cpu_enable = cpu_enable_ssbs,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.desc = "Speculation barrier (SB)",
|
||||
.capability = ARM64_HAS_SB,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64ISAR1_EL1,
|
||||
.field_pos = ID_AA64ISAR1_SB_SHIFT,
|
||||
.sign = FTR_UNSIGNED,
|
||||
.min_field_value = 1,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
#define HWCAP_CPUID_MATCH(reg, field, s, min_value) \
|
||||
.matches = has_cpuid_feature, \
|
||||
.matches = has_user_cpuid_feature, \
|
||||
.sys_reg = reg, \
|
||||
.field_pos = field, \
|
||||
.sign = s, \
|
||||
@@ -1417,6 +1484,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FCMA),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_ILRCPC),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_SB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SB),
|
||||
HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_USCAT),
|
||||
#ifdef CONFIG_ARM64_SVE
|
||||
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_SVE_SHIFT, FTR_UNSIGNED, ID_AA64PFR0_SVE, CAP_HWCAP, HWCAP_SVE),
|
||||
@@ -1811,6 +1879,7 @@ void __init setup_cpu_features(void)
|
||||
|
||||
setup_system_capabilities();
|
||||
mark_const_caps_ready();
|
||||
user_feature_fixup();
|
||||
setup_elf_hwcaps(arm64_elf_hwcaps);
|
||||
|
||||
if (system_supports_32bit_el0()) {
|
||||
@@ -1844,7 +1913,7 @@ cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused)
|
||||
|
||||
/*
|
||||
* We emulate only the following system register space.
|
||||
* Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 4 - 7]
|
||||
* Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 2 - 7]
|
||||
* See Table C5-6 System instruction encodings for System register accesses,
|
||||
* ARMv8 ARM(ARM DDI 0487A.f) for more details.
|
||||
*/
|
||||
@@ -1854,7 +1923,7 @@ static inline bool __attribute_const__ is_emulated(u32 id)
|
||||
sys_reg_CRn(id) == 0x0 &&
|
||||
sys_reg_Op1(id) == 0x0 &&
|
||||
(sys_reg_CRm(id) == 0 ||
|
||||
((sys_reg_CRm(id) >= 4) && (sys_reg_CRm(id) <= 7))));
|
||||
((sys_reg_CRm(id) >= 2) && (sys_reg_CRm(id) <= 7))));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -89,6 +89,7 @@ static const char *const hwcap_str[] = {
|
||||
"ilrcpc",
|
||||
"flagm",
|
||||
"ssbs",
|
||||
"sb",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -181,6 +181,15 @@ int __init amiga_parse_bootinfo(const struct bi_record *record)
|
||||
dev->slotsize = be16_to_cpu(cd->cd_SlotSize);
|
||||
dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
|
||||
dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
|
||||
|
||||
/* CS-LAB Warp 1260 workaround */
|
||||
if (be16_to_cpu(dev->rom.er_Manufacturer) == ZORRO_MANUF(ZORRO_PROD_CSLAB_WARP_1260) &&
|
||||
dev->rom.er_Product == ZORRO_PROD(ZORRO_PROD_CSLAB_WARP_1260)) {
|
||||
|
||||
/* turn off all interrupts */
|
||||
pr_info("Warp 1260 card detected: applying interrupt storm workaround\n");
|
||||
*(uint32_t *)(dev->boardaddr + 0x1000) = 0xfff;
|
||||
}
|
||||
} else
|
||||
pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n");
|
||||
#endif /* CONFIG_ZORRO */
|
||||
|
||||
@@ -302,11 +302,7 @@ void __init atari_init_IRQ(void)
|
||||
|
||||
if (ATARIHW_PRESENT(SCU)) {
|
||||
/* init the SCU if present */
|
||||
tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and
|
||||
* disable HSYNC interrupts (who
|
||||
* needs them?) MFP and SCC are
|
||||
* enabled in VME mask
|
||||
*/
|
||||
tt_scu.sys_mask = 0x0; /* disable all interrupts */
|
||||
tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */
|
||||
} else {
|
||||
/* If no SCU and no Hades, the HSYNC interrupt needs to be
|
||||
|
||||
@@ -33,7 +33,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
|
||||
x = tmp;
|
||||
break;
|
||||
default:
|
||||
tmp = __invalid_xchg_size(x, ptr, size);
|
||||
x = __invalid_xchg_size(x, ptr, size);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,10 @@ GCR_ACCESSOR_RO(32, 0x0d0, gic_status)
|
||||
GCR_ACCESSOR_RO(32, 0x0f0, cpc_status)
|
||||
#define CM_GCR_CPC_STATUS_EX BIT(0)
|
||||
|
||||
/* GCR_ACCESS - Controls core/IOCU access to GCRs */
|
||||
GCR_ACCESSOR_RW(32, 0x120, access_cm3)
|
||||
#define CM_GCR_ACCESS_ACCESSEN GENMASK(7, 0)
|
||||
|
||||
/* GCR_L2_CONFIG - Indicates L2 cache configuration when Config5.L2C=1 */
|
||||
GCR_ACCESSOR_RW(32, 0x130, l2_config)
|
||||
#define CM_GCR_L2_CONFIG_BYPASS BIT(20)
|
||||
|
||||
@@ -233,7 +233,10 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
|
||||
write_gcr_co_reset_ext_base(CM_GCR_Cx_RESET_EXT_BASE_UEB);
|
||||
|
||||
/* Ensure the core can access the GCRs */
|
||||
if (mips_cm_revision() < CM_REV_CM3)
|
||||
set_gcr_access(1 << core);
|
||||
else
|
||||
set_gcr_access_cm3(1 << core);
|
||||
|
||||
if (mips_cpc_present()) {
|
||||
/* Reset the core */
|
||||
|
||||
0
arch/mips/pci/pcie-octeon.c
Executable file → Normal file
0
arch/mips/pci/pcie-octeon.c
Executable file → Normal file
@@ -287,6 +287,9 @@ void calibrate_delay(void)
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
/* setup memblock allocator */
|
||||
setup_memory();
|
||||
|
||||
unflatten_and_copy_device_tree();
|
||||
|
||||
setup_cpuinfo();
|
||||
@@ -311,9 +314,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
initrd_below_start_ok = 1;
|
||||
#endif
|
||||
|
||||
/* setup memblock allocator */
|
||||
setup_memory();
|
||||
|
||||
/* paging_init() sets up the MMU and marks all pages as reserved */
|
||||
paging_init();
|
||||
|
||||
|
||||
@@ -524,7 +524,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
local_irq_disable();
|
||||
irq_enter();
|
||||
irq_enter_rcu();
|
||||
|
||||
eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
|
||||
if (!eirr_val)
|
||||
@@ -559,7 +559,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
|
||||
#endif /* CONFIG_IRQSTACKS */
|
||||
|
||||
out:
|
||||
irq_exit();
|
||||
irq_exit_rcu();
|
||||
set_irq_regs(old_regs);
|
||||
return;
|
||||
|
||||
|
||||
@@ -114,8 +114,11 @@ static void *simple_realloc(void *ptr, unsigned long size)
|
||||
return ptr;
|
||||
|
||||
new = simple_malloc(size);
|
||||
if (new) {
|
||||
memcpy(new, ptr, p->size);
|
||||
simple_free(ptr);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,6 +240,8 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr,
|
||||
rname = kasprintf(GFP_KERNEL, "CPU %d [0x%x] Interrupt Presentation",
|
||||
cpu, hw_id);
|
||||
|
||||
if (!rname)
|
||||
return -ENOMEM;
|
||||
if (!request_mem_region(addr, size, rname)) {
|
||||
pr_warn("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n",
|
||||
cpu, hw_id);
|
||||
|
||||
@@ -133,32 +133,21 @@ int print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
||||
bool insn_is_short;
|
||||
ppc_cpu_t dialect;
|
||||
|
||||
dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON
|
||||
| PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
|
||||
dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER5))
|
||||
dialect |= PPC_OPCODE_POWER5;
|
||||
if (IS_ENABLED(CONFIG_PPC64))
|
||||
dialect |= PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_CELL |
|
||||
PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 |
|
||||
PPC_OPCODE_POWER9;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_CELL))
|
||||
dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
|
||||
if (cpu_has_feature(CPU_FTR_TM))
|
||||
dialect |= PPC_OPCODE_HTM;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER6))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
|
||||
if (cpu_has_feature(CPU_FTR_ALTIVEC))
|
||||
dialect |= PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER7))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
|
||||
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER8))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
|
||||
| PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
|
||||
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER9))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
|
||||
| PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
|
||||
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
|
||||
| PPC_OPCODE_VSX | PPC_OPCODE_VSX3);
|
||||
if (cpu_has_feature(CPU_FTR_VSX))
|
||||
dialect |= PPC_OPCODE_VSX | PPC_OPCODE_VSX3;
|
||||
|
||||
/* Get the major opcode of the insn. */
|
||||
opcode = NULL;
|
||||
|
||||
@@ -247,6 +247,7 @@ void prom_sun4v_guest_soft_state(void);
|
||||
int prom_ihandle2path(int handle, char *buffer, int bufsize);
|
||||
|
||||
/* Client interface level routines. */
|
||||
void prom_cif_init(void *cif_handler);
|
||||
void p1275_cmd_direct(unsigned long *);
|
||||
|
||||
#endif /* !(__SPARC64_OPLIB_H) */
|
||||
|
||||
@@ -26,9 +26,6 @@ phandle prom_chosen_node;
|
||||
* routines in the prom library.
|
||||
* It gets passed the pointer to the PROM vector.
|
||||
*/
|
||||
|
||||
extern void prom_cif_init(void *);
|
||||
|
||||
void __init prom_init(void *cif_handler)
|
||||
{
|
||||
phandle node;
|
||||
|
||||
@@ -49,7 +49,7 @@ void p1275_cmd_direct(unsigned long *args)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void prom_cif_init(void *cif_handler, void *cif_stack)
|
||||
void prom_cif_init(void *cif_handler)
|
||||
{
|
||||
p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ static struct pt_cap_desc {
|
||||
PT_CAP(psb_periods, 1, CPUID_EBX, 0xffff0000),
|
||||
};
|
||||
|
||||
static u32 pt_cap_get(enum pt_capabilities cap)
|
||||
u32 intel_pt_validate_hw_cap(enum pt_capabilities cap)
|
||||
{
|
||||
struct pt_cap_desc *cd = &pt_caps[cap];
|
||||
u32 c = pt_pmu.caps[cd->leaf * PT_CPUID_REGS_NUM + cd->reg];
|
||||
@@ -83,6 +83,7 @@ static u32 pt_cap_get(enum pt_capabilities cap)
|
||||
|
||||
return (c & cd->mask) >> shift;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pt_validate_hw_cap);
|
||||
|
||||
static ssize_t pt_cap_show(struct device *cdev,
|
||||
struct device_attribute *attr,
|
||||
@@ -92,7 +93,7 @@ static ssize_t pt_cap_show(struct device *cdev,
|
||||
container_of(attr, struct dev_ext_attribute, attr);
|
||||
enum pt_capabilities cap = (long)ea->var;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%x\n", pt_cap_get(cap));
|
||||
return snprintf(buf, PAGE_SIZE, "%x\n", intel_pt_validate_hw_cap(cap));
|
||||
}
|
||||
|
||||
static struct attribute_group pt_cap_group = {
|
||||
@@ -310,16 +311,16 @@ static bool pt_event_valid(struct perf_event *event)
|
||||
return false;
|
||||
|
||||
if (config & RTIT_CTL_CYC_PSB) {
|
||||
if (!pt_cap_get(PT_CAP_psb_cyc))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_psb_cyc))
|
||||
return false;
|
||||
|
||||
allowed = pt_cap_get(PT_CAP_psb_periods);
|
||||
allowed = intel_pt_validate_hw_cap(PT_CAP_psb_periods);
|
||||
requested = (config & RTIT_CTL_PSB_FREQ) >>
|
||||
RTIT_CTL_PSB_FREQ_OFFSET;
|
||||
if (requested && (!(allowed & BIT(requested))))
|
||||
return false;
|
||||
|
||||
allowed = pt_cap_get(PT_CAP_cycle_thresholds);
|
||||
allowed = intel_pt_validate_hw_cap(PT_CAP_cycle_thresholds);
|
||||
requested = (config & RTIT_CTL_CYC_THRESH) >>
|
||||
RTIT_CTL_CYC_THRESH_OFFSET;
|
||||
if (requested && (!(allowed & BIT(requested))))
|
||||
@@ -334,10 +335,10 @@ static bool pt_event_valid(struct perf_event *event)
|
||||
* Spec says that setting mtc period bits while mtc bit in
|
||||
* CPUID is 0 will #GP, so better safe than sorry.
|
||||
*/
|
||||
if (!pt_cap_get(PT_CAP_mtc))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_mtc))
|
||||
return false;
|
||||
|
||||
allowed = pt_cap_get(PT_CAP_mtc_periods);
|
||||
allowed = intel_pt_validate_hw_cap(PT_CAP_mtc_periods);
|
||||
if (!allowed)
|
||||
return false;
|
||||
|
||||
@@ -349,11 +350,11 @@ static bool pt_event_valid(struct perf_event *event)
|
||||
}
|
||||
|
||||
if (config & RTIT_CTL_PWR_EVT_EN &&
|
||||
!pt_cap_get(PT_CAP_power_event_trace))
|
||||
!intel_pt_validate_hw_cap(PT_CAP_power_event_trace))
|
||||
return false;
|
||||
|
||||
if (config & RTIT_CTL_PTW) {
|
||||
if (!pt_cap_get(PT_CAP_ptwrite))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_ptwrite))
|
||||
return false;
|
||||
|
||||
/* FUPonPTW without PTW doesn't make sense */
|
||||
@@ -545,16 +546,8 @@ static void pt_config_buffer(void *buf, unsigned int topa_idx,
|
||||
wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep ToPA table-related metadata on the same page as the actual table,
|
||||
* taking up a few words from the top
|
||||
*/
|
||||
|
||||
#define TENTS_PER_PAGE (((PAGE_SIZE - 40) / sizeof(struct topa_entry)) - 1)
|
||||
|
||||
/**
|
||||
* struct topa - page-sized ToPA table with metadata at the top
|
||||
* @table: actual ToPA table entries, as understood by PT hardware
|
||||
* struct topa - ToPA metadata
|
||||
* @list: linkage to struct pt_buffer's list of tables
|
||||
* @phys: physical address of this page
|
||||
* @offset: offset of the first entry in this table in the buffer
|
||||
@@ -562,7 +555,6 @@ static void pt_config_buffer(void *buf, unsigned int topa_idx,
|
||||
* @last: index of the last initialized entry in this table
|
||||
*/
|
||||
struct topa {
|
||||
struct topa_entry table[TENTS_PER_PAGE];
|
||||
struct list_head list;
|
||||
u64 phys;
|
||||
u64 offset;
|
||||
@@ -570,8 +562,40 @@ struct topa {
|
||||
int last;
|
||||
};
|
||||
|
||||
/*
|
||||
* Keep ToPA table-related metadata on the same page as the actual table,
|
||||
* taking up a few words from the top
|
||||
*/
|
||||
|
||||
#define TENTS_PER_PAGE \
|
||||
((PAGE_SIZE - sizeof(struct topa)) / sizeof(struct topa_entry))
|
||||
|
||||
/**
|
||||
* struct topa_page - page-sized ToPA table with metadata at the top
|
||||
* @table: actual ToPA table entries, as understood by PT hardware
|
||||
* @topa: metadata
|
||||
*/
|
||||
struct topa_page {
|
||||
struct topa_entry table[TENTS_PER_PAGE];
|
||||
struct topa topa;
|
||||
};
|
||||
|
||||
static inline struct topa_page *topa_to_page(struct topa *topa)
|
||||
{
|
||||
return container_of(topa, struct topa_page, topa);
|
||||
}
|
||||
|
||||
static inline struct topa_page *topa_entry_to_page(struct topa_entry *te)
|
||||
{
|
||||
return (struct topa_page *)((unsigned long)te & PAGE_MASK);
|
||||
}
|
||||
|
||||
/* make -1 stand for the last table entry */
|
||||
#define TOPA_ENTRY(t, i) ((i) == -1 ? &(t)->table[(t)->last] : &(t)->table[(i)])
|
||||
#define TOPA_ENTRY(t, i) \
|
||||
((i) == -1 \
|
||||
? &topa_to_page(t)->table[(t)->last] \
|
||||
: &topa_to_page(t)->table[(i)])
|
||||
#define TOPA_ENTRY_SIZE(t, i) (sizes(TOPA_ENTRY((t), (i))->size))
|
||||
|
||||
/**
|
||||
* topa_alloc() - allocate page-sized ToPA table
|
||||
@@ -583,27 +607,27 @@ struct topa {
|
||||
static struct topa *topa_alloc(int cpu, gfp_t gfp)
|
||||
{
|
||||
int node = cpu_to_node(cpu);
|
||||
struct topa *topa;
|
||||
struct topa_page *tp;
|
||||
struct page *p;
|
||||
|
||||
p = alloc_pages_node(node, gfp | __GFP_ZERO, 0);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
topa = page_address(p);
|
||||
topa->last = 0;
|
||||
topa->phys = page_to_phys(p);
|
||||
tp = page_address(p);
|
||||
tp->topa.last = 0;
|
||||
tp->topa.phys = page_to_phys(p);
|
||||
|
||||
/*
|
||||
* In case of singe-entry ToPA, always put the self-referencing END
|
||||
* link as the 2nd entry in the table
|
||||
*/
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries)) {
|
||||
TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT;
|
||||
TOPA_ENTRY(topa, 1)->end = 1;
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
|
||||
TOPA_ENTRY(&tp->topa, 1)->base = tp->topa.phys;
|
||||
TOPA_ENTRY(&tp->topa, 1)->end = 1;
|
||||
}
|
||||
|
||||
return topa;
|
||||
return &tp->topa;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -638,7 +662,7 @@ static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
|
||||
topa->offset = last->offset + last->size;
|
||||
buf->last = topa;
|
||||
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
|
||||
return;
|
||||
|
||||
BUG_ON(last->last != TENTS_PER_PAGE - 1);
|
||||
@@ -654,7 +678,7 @@ static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
|
||||
static bool topa_table_full(struct topa *topa)
|
||||
{
|
||||
/* single-entry ToPA is a special case */
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
|
||||
return !!topa->last;
|
||||
|
||||
return topa->last == TENTS_PER_PAGE - 1;
|
||||
@@ -690,7 +714,8 @@ static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp)
|
||||
|
||||
TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT;
|
||||
TOPA_ENTRY(topa, -1)->size = order;
|
||||
if (!buf->snapshot && !pt_cap_get(PT_CAP_topa_multiple_entries)) {
|
||||
if (!buf->snapshot &&
|
||||
!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
|
||||
TOPA_ENTRY(topa, -1)->intr = 1;
|
||||
TOPA_ENTRY(topa, -1)->stop = 1;
|
||||
}
|
||||
@@ -712,22 +737,23 @@ static void pt_topa_dump(struct pt_buffer *buf)
|
||||
struct topa *topa;
|
||||
|
||||
list_for_each_entry(topa, &buf->tables, list) {
|
||||
struct topa_page *tp = topa_to_page(topa);
|
||||
int i;
|
||||
|
||||
pr_debug("# table @%p (%016Lx), off %llx size %zx\n", topa->table,
|
||||
pr_debug("# table @%p (%016Lx), off %llx size %zx\n", tp->table,
|
||||
topa->phys, topa->offset, topa->size);
|
||||
for (i = 0; i < TENTS_PER_PAGE; i++) {
|
||||
pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n",
|
||||
&topa->table[i],
|
||||
(unsigned long)topa->table[i].base << TOPA_SHIFT,
|
||||
sizes(topa->table[i].size),
|
||||
topa->table[i].end ? 'E' : ' ',
|
||||
topa->table[i].intr ? 'I' : ' ',
|
||||
topa->table[i].stop ? 'S' : ' ',
|
||||
*(u64 *)&topa->table[i]);
|
||||
if ((pt_cap_get(PT_CAP_topa_multiple_entries) &&
|
||||
topa->table[i].stop) ||
|
||||
topa->table[i].end)
|
||||
&tp->table[i],
|
||||
(unsigned long)tp->table[i].base << TOPA_SHIFT,
|
||||
sizes(tp->table[i].size),
|
||||
tp->table[i].end ? 'E' : ' ',
|
||||
tp->table[i].intr ? 'I' : ' ',
|
||||
tp->table[i].stop ? 'S' : ' ',
|
||||
*(u64 *)&tp->table[i]);
|
||||
if ((intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) &&
|
||||
tp->table[i].stop) ||
|
||||
tp->table[i].end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -770,7 +796,7 @@ static void pt_update_head(struct pt *pt)
|
||||
|
||||
/* offset of the current output region within this table */
|
||||
for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++)
|
||||
base += sizes(buf->cur->table[topa_idx].size);
|
||||
base += TOPA_ENTRY_SIZE(buf->cur, topa_idx);
|
||||
|
||||
if (buf->snapshot) {
|
||||
local_set(&buf->data_size, base);
|
||||
@@ -790,7 +816,7 @@ static void pt_update_head(struct pt *pt)
|
||||
*/
|
||||
static void *pt_buffer_region(struct pt_buffer *buf)
|
||||
{
|
||||
return phys_to_virt(buf->cur->table[buf->cur_idx].base << TOPA_SHIFT);
|
||||
return phys_to_virt((phys_addr_t)TOPA_ENTRY(buf->cur, buf->cur_idx)->base << TOPA_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -799,7 +825,7 @@ static void *pt_buffer_region(struct pt_buffer *buf)
|
||||
*/
|
||||
static size_t pt_buffer_region_size(struct pt_buffer *buf)
|
||||
{
|
||||
return sizes(buf->cur->table[buf->cur_idx].size);
|
||||
return TOPA_ENTRY_SIZE(buf->cur, buf->cur_idx);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -828,8 +854,8 @@ static void pt_handle_status(struct pt *pt)
|
||||
* means we are already losing data; need to let the decoder
|
||||
* know.
|
||||
*/
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries) ||
|
||||
buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) ||
|
||||
buf->output_off == pt_buffer_region_size(buf)) {
|
||||
perf_aux_output_flag(&pt->handle,
|
||||
PERF_AUX_FLAG_TRUNCATED);
|
||||
advance++;
|
||||
@@ -840,7 +866,8 @@ static void pt_handle_status(struct pt *pt)
|
||||
* Also on single-entry ToPA implementations, interrupt will come
|
||||
* before the output reaches its output region's boundary.
|
||||
*/
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries) && !buf->snapshot &&
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) &&
|
||||
!buf->snapshot &&
|
||||
pt_buffer_region_size(buf) - buf->output_off <= TOPA_PMI_MARGIN) {
|
||||
void *head = pt_buffer_region(buf);
|
||||
|
||||
@@ -866,9 +893,11 @@ static void pt_handle_status(struct pt *pt)
|
||||
static void pt_read_offset(struct pt_buffer *buf)
|
||||
{
|
||||
u64 offset, base_topa;
|
||||
struct topa_page *tp;
|
||||
|
||||
rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa);
|
||||
buf->cur = phys_to_virt(base_topa);
|
||||
tp = phys_to_virt(base_topa);
|
||||
buf->cur = &tp->topa;
|
||||
|
||||
rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
|
||||
/* offset within current output region */
|
||||
@@ -923,15 +952,14 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
|
||||
unsigned long idx, npages, wakeup;
|
||||
|
||||
/* can't stop in the middle of an output region */
|
||||
if (buf->output_off + handle->size + 1 <
|
||||
sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
|
||||
if (buf->output_off + handle->size + 1 < pt_buffer_region_size(buf)) {
|
||||
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
/* single entry ToPA is handled by marking all regions STOP=1 INT=1 */
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
|
||||
return 0;
|
||||
|
||||
/* clear STOP and INT from current entry */
|
||||
@@ -1019,6 +1047,7 @@ static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
|
||||
*/
|
||||
static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
|
||||
{
|
||||
struct topa_page *cur_tp;
|
||||
int pg;
|
||||
|
||||
if (buf->snapshot)
|
||||
@@ -1027,10 +1056,10 @@ static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
|
||||
pg = (head >> PAGE_SHIFT) & (buf->nr_pages - 1);
|
||||
pg = pt_topa_next_entry(buf, pg);
|
||||
|
||||
buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK);
|
||||
buf->cur_idx = ((unsigned long)buf->topa_index[pg] -
|
||||
(unsigned long)buf->cur) / sizeof(struct topa_entry);
|
||||
buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1);
|
||||
cur_tp = topa_entry_to_page(buf->topa_index[pg]);
|
||||
buf->cur = &cur_tp->topa;
|
||||
buf->cur_idx = buf->topa_index[pg] - TOPA_ENTRY(buf->cur, 0);
|
||||
buf->output_off = head & (pt_buffer_region_size(buf) - 1);
|
||||
|
||||
local64_set(&buf->head, head);
|
||||
local_set(&buf->data_size, 0);
|
||||
@@ -1082,7 +1111,7 @@ static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
|
||||
pt_buffer_setup_topa_index(buf);
|
||||
|
||||
/* link last table to the first one, unless we're double buffering */
|
||||
if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
|
||||
if (intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
|
||||
TOPA_ENTRY(buf->last, -1)->base = buf->first->phys >> TOPA_SHIFT;
|
||||
TOPA_ENTRY(buf->last, -1)->end = 1;
|
||||
}
|
||||
@@ -1154,7 +1183,7 @@ static int pt_addr_filters_init(struct perf_event *event)
|
||||
struct pt_filters *filters;
|
||||
int node = event->cpu == -1 ? -1 : cpu_to_node(event->cpu);
|
||||
|
||||
if (!pt_cap_get(PT_CAP_num_address_ranges))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_num_address_ranges))
|
||||
return 0;
|
||||
|
||||
filters = kzalloc_node(sizeof(struct pt_filters), GFP_KERNEL, node);
|
||||
@@ -1203,7 +1232,7 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (++range > pt_cap_get(PT_CAP_num_address_ranges))
|
||||
if (++range > intel_pt_validate_hw_cap(PT_CAP_num_address_ranges))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@@ -1294,7 +1323,7 @@ void intel_pt_interrupt(void)
|
||||
return;
|
||||
}
|
||||
|
||||
pt_config_buffer(buf->cur->table, buf->cur_idx,
|
||||
pt_config_buffer(topa_to_page(buf->cur)->table, buf->cur_idx,
|
||||
buf->output_off);
|
||||
pt_config(event);
|
||||
}
|
||||
@@ -1359,7 +1388,7 @@ static void pt_event_start(struct perf_event *event, int mode)
|
||||
WRITE_ONCE(pt->handle_nmi, 1);
|
||||
hwc->state = 0;
|
||||
|
||||
pt_config_buffer(buf->cur->table, buf->cur_idx,
|
||||
pt_config_buffer(topa_to_page(buf->cur)->table, buf->cur_idx,
|
||||
buf->output_off);
|
||||
pt_config(event);
|
||||
|
||||
@@ -1509,12 +1538,12 @@ static __init int pt_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!pt_cap_get(PT_CAP_topa_output)) {
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_output)) {
|
||||
pr_warn("ToPA output is not supported on this CPU\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!pt_cap_get(PT_CAP_topa_multiple_entries))
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
|
||||
pt_pmu.pmu.capabilities =
|
||||
PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;
|
||||
|
||||
@@ -1532,7 +1561,7 @@ static __init int pt_init(void)
|
||||
pt_pmu.pmu.addr_filters_sync = pt_event_addr_filters_sync;
|
||||
pt_pmu.pmu.addr_filters_validate = pt_event_addr_filters_validate;
|
||||
pt_pmu.pmu.nr_addr_filters =
|
||||
pt_cap_get(PT_CAP_num_address_ranges);
|
||||
intel_pt_validate_hw_cap(PT_CAP_num_address_ranges);
|
||||
|
||||
ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);
|
||||
|
||||
|
||||
@@ -78,34 +78,13 @@ struct topa_entry {
|
||||
u64 rsvd2 : 1;
|
||||
u64 size : 4;
|
||||
u64 rsvd3 : 2;
|
||||
u64 base : 36;
|
||||
u64 rsvd4 : 16;
|
||||
u64 base : 40;
|
||||
u64 rsvd4 : 12;
|
||||
};
|
||||
|
||||
#define PT_CPUID_LEAVES 2
|
||||
#define PT_CPUID_REGS_NUM 4 /* number of regsters (eax, ebx, ecx, edx) */
|
||||
|
||||
/* TSC to Core Crystal Clock Ratio */
|
||||
#define CPUID_TSC_LEAF 0x15
|
||||
|
||||
enum pt_capabilities {
|
||||
PT_CAP_max_subleaf = 0,
|
||||
PT_CAP_cr3_filtering,
|
||||
PT_CAP_psb_cyc,
|
||||
PT_CAP_ip_filtering,
|
||||
PT_CAP_mtc,
|
||||
PT_CAP_ptwrite,
|
||||
PT_CAP_power_event_trace,
|
||||
PT_CAP_topa_output,
|
||||
PT_CAP_topa_multiple_entries,
|
||||
PT_CAP_single_range_output,
|
||||
PT_CAP_payloads_lip,
|
||||
PT_CAP_num_address_ranges,
|
||||
PT_CAP_mtc_periods,
|
||||
PT_CAP_cycle_thresholds,
|
||||
PT_CAP_psb_periods,
|
||||
};
|
||||
|
||||
struct pt_pmu {
|
||||
struct pmu pmu;
|
||||
u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
|
||||
|
||||
@@ -2,10 +2,33 @@
|
||||
#ifndef _ASM_X86_INTEL_PT_H
|
||||
#define _ASM_X86_INTEL_PT_H
|
||||
|
||||
#define PT_CPUID_LEAVES 2
|
||||
#define PT_CPUID_REGS_NUM 4 /* number of regsters (eax, ebx, ecx, edx) */
|
||||
|
||||
enum pt_capabilities {
|
||||
PT_CAP_max_subleaf = 0,
|
||||
PT_CAP_cr3_filtering,
|
||||
PT_CAP_psb_cyc,
|
||||
PT_CAP_ip_filtering,
|
||||
PT_CAP_mtc,
|
||||
PT_CAP_ptwrite,
|
||||
PT_CAP_power_event_trace,
|
||||
PT_CAP_topa_output,
|
||||
PT_CAP_topa_multiple_entries,
|
||||
PT_CAP_single_range_output,
|
||||
PT_CAP_payloads_lip,
|
||||
PT_CAP_num_address_ranges,
|
||||
PT_CAP_mtc_periods,
|
||||
PT_CAP_cycle_thresholds,
|
||||
PT_CAP_psb_periods,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
|
||||
void cpu_emergency_stop_pt(void);
|
||||
extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap);
|
||||
#else
|
||||
static inline void cpu_emergency_stop_pt(void) {}
|
||||
static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_INTEL_PT_H */
|
||||
|
||||
@@ -819,7 +819,7 @@ void mtrr_save_state(void)
|
||||
{
|
||||
int first_cpu;
|
||||
|
||||
if (!mtrr_enabled())
|
||||
if (!mtrr_enabled() || !mtrr_state.have_fixed)
|
||||
return;
|
||||
|
||||
first_cpu = cpumask_first(cpu_online_mask);
|
||||
|
||||
@@ -90,7 +90,7 @@ static int x86_of_pci_irq_enable(struct pci_dev *dev)
|
||||
|
||||
ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
return pcibios_err_to_errno(ret);
|
||||
if (!pin)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -383,14 +383,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
|
||||
*/
|
||||
*target_pmd = *pmd;
|
||||
|
||||
addr += PMD_SIZE;
|
||||
addr = round_up(addr + 1, PMD_SIZE);
|
||||
|
||||
} else if (level == PTI_CLONE_PTE) {
|
||||
|
||||
/* Walk the page-table down to the pte level */
|
||||
pte = pte_offset_kernel(pmd, addr);
|
||||
if (pte_none(*pte)) {
|
||||
addr += PAGE_SIZE;
|
||||
addr = round_up(addr + 1, PAGE_SIZE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -410,7 +410,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
|
||||
/* Clone the PTE */
|
||||
*target_pte = *pte;
|
||||
|
||||
addr += PAGE_SIZE;
|
||||
addr = round_up(addr + 1, PAGE_SIZE);
|
||||
|
||||
} else {
|
||||
BUG();
|
||||
|
||||
@@ -223,9 +223,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
||||
return 0;
|
||||
|
||||
ret = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
|
||||
if (ret < 0) {
|
||||
if (ret) {
|
||||
dev_warn(&dev->dev, "Failed to read interrupt line: %d\n", ret);
|
||||
return ret;
|
||||
return pcibios_err_to_errno(ret);
|
||||
}
|
||||
|
||||
switch (intel_mid_identify_cpu()) {
|
||||
|
||||
@@ -36,10 +36,10 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
|
||||
u8 gsi;
|
||||
|
||||
rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
|
||||
if (rc < 0) {
|
||||
if (rc) {
|
||||
dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
return pcibios_err_to_errno(rc);
|
||||
}
|
||||
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
|
||||
pirq = gsi;
|
||||
|
||||
@@ -68,7 +68,7 @@ static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr)
|
||||
|
||||
fail_read:
|
||||
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
|
||||
return result;
|
||||
return pcibios_err_to_errno(result);
|
||||
}
|
||||
|
||||
static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
|
||||
@@ -97,7 +97,7 @@ static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
|
||||
|
||||
fail_write:
|
||||
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
|
||||
return result;
|
||||
return pcibios_err_to_errno(result);
|
||||
}
|
||||
|
||||
int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
|
||||
|
||||
@@ -733,7 +733,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
|
||||
* immediate unmapping.
|
||||
*/
|
||||
map_ops[i].status = GNTST_general_error;
|
||||
unmap[0].host_addr = map_ops[i].host_addr,
|
||||
unmap[0].host_addr = map_ops[i].host_addr;
|
||||
unmap[0].handle = map_ops[i].handle;
|
||||
map_ops[i].handle = ~0;
|
||||
if (map_ops[i].flags & GNTMAP_device_map)
|
||||
@@ -743,7 +743,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
|
||||
|
||||
if (kmap_ops) {
|
||||
kmap_ops[i].status = GNTST_general_error;
|
||||
unmap[1].host_addr = kmap_ops[i].host_addr,
|
||||
unmap[1].host_addr = kmap_ops[i].host_addr;
|
||||
unmap[1].handle = kmap_ops[i].handle;
|
||||
kmap_ops[i].handle = ~0;
|
||||
if (kmap_ops[i].flags & GNTMAP_device_map)
|
||||
|
||||
@@ -1330,10 +1330,13 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
if (ec->busy_polling || bits > 8)
|
||||
acpi_ec_burst_enable(ec);
|
||||
|
||||
for (i = 0; i < bytes; ++i, ++address, ++value)
|
||||
for (i = 0; i < bytes; ++i, ++address, ++value) {
|
||||
result = (function == ACPI_READ) ?
|
||||
acpi_ec_read(ec, address, value) :
|
||||
acpi_ec_write(ec, address, *value);
|
||||
if (result < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ec->busy_polling || bits > 8)
|
||||
acpi_ec_burst_disable(ec);
|
||||
@@ -1345,8 +1348,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
return AE_NOT_FOUND;
|
||||
case -ETIME:
|
||||
return AE_TIME;
|
||||
default:
|
||||
case 0:
|
||||
return AE_OK;
|
||||
default:
|
||||
return AE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/sched.h> /* need_resched() */
|
||||
#include <linux/sort.h>
|
||||
#include <linux/tick.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/cpu.h>
|
||||
@@ -545,28 +544,24 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||
return;
|
||||
}
|
||||
|
||||
static int acpi_cst_latency_cmp(const void *a, const void *b)
|
||||
static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length)
|
||||
{
|
||||
const struct acpi_processor_cx *x = a, *y = b;
|
||||
int i, j, k;
|
||||
|
||||
if (!(x->valid && y->valid))
|
||||
return 0;
|
||||
if (x->latency > y->latency)
|
||||
return 1;
|
||||
if (x->latency < y->latency)
|
||||
return -1;
|
||||
return 0;
|
||||
for (i = 1; i < length; i++) {
|
||||
if (!states[i].valid)
|
||||
continue;
|
||||
|
||||
for (j = i - 1, k = i; j >= 0; j--) {
|
||||
if (!states[j].valid)
|
||||
continue;
|
||||
|
||||
if (states[j].latency > states[k].latency)
|
||||
swap(states[j].latency, states[k].latency);
|
||||
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
static void acpi_cst_latency_swap(void *a, void *b, int n)
|
||||
{
|
||||
struct acpi_processor_cx *x = a, *y = b;
|
||||
u32 tmp;
|
||||
|
||||
if (!(x->valid && y->valid))
|
||||
return;
|
||||
tmp = x->latency;
|
||||
x->latency = y->latency;
|
||||
y->latency = tmp;
|
||||
}
|
||||
|
||||
static int acpi_processor_power_verify(struct acpi_processor *pr)
|
||||
@@ -611,10 +606,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
|
||||
|
||||
if (buggy_latency) {
|
||||
pr_notice("FW issue: working around C-state latencies out of order\n");
|
||||
sort(&pr->power.states[1], max_cstate,
|
||||
sizeof(struct acpi_processor_cx),
|
||||
acpi_cst_latency_cmp,
|
||||
acpi_cst_latency_swap);
|
||||
acpi_cst_latency_sort(&pr->power.states[1], max_cstate);
|
||||
}
|
||||
|
||||
lapic_timer_propagate_broadcast(pr);
|
||||
|
||||
@@ -1002,9 +1002,7 @@ static bool binder_has_work(struct binder_thread *thread, bool do_proc_work)
|
||||
static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread)
|
||||
{
|
||||
return !thread->transaction_stack &&
|
||||
binder_worklist_empty_ilocked(&thread->todo) &&
|
||||
(thread->looper & (BINDER_LOOPER_STATE_ENTERED |
|
||||
BINDER_LOOPER_STATE_REGISTERED));
|
||||
binder_worklist_empty_ilocked(&thread->todo);
|
||||
}
|
||||
|
||||
static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc,
|
||||
|
||||
@@ -6159,6 +6159,9 @@ static void ata_host_release(struct kref *kref)
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap = host->ports[i];
|
||||
|
||||
if (!ap)
|
||||
continue;
|
||||
|
||||
kfree(ap->pmp_link);
|
||||
kfree(ap->slave_link);
|
||||
kfree(ap);
|
||||
|
||||
@@ -1117,8 +1117,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
|
||||
rpp->len += skb->len;
|
||||
|
||||
if (stat & SAR_RSQE_EPDU) {
|
||||
unsigned int len, truesize;
|
||||
unsigned char *l1l2;
|
||||
unsigned int len;
|
||||
|
||||
l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
|
||||
|
||||
@@ -1188,14 +1188,15 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
|
||||
ATM_SKB(skb)->vcc = vcc;
|
||||
__net_timestamp(skb);
|
||||
|
||||
truesize = skb->truesize;
|
||||
vcc->push(vcc, skb);
|
||||
atomic_inc(&vcc->stats->rx);
|
||||
|
||||
if (skb->truesize > SAR_FB_SIZE_3)
|
||||
if (truesize > SAR_FB_SIZE_3)
|
||||
add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
|
||||
else if (skb->truesize > SAR_FB_SIZE_2)
|
||||
else if (truesize > SAR_FB_SIZE_2)
|
||||
add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
|
||||
else if (skb->truesize > SAR_FB_SIZE_1)
|
||||
else if (truesize > SAR_FB_SIZE_1)
|
||||
add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
|
||||
else
|
||||
add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
@@ -1585,6 +1586,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct device_driver *driver;
|
||||
int retval = 0;
|
||||
|
||||
/* add device node properties if present */
|
||||
@@ -1613,8 +1615,12 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
||||
if (dev->type && dev->type->name)
|
||||
add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
|
||||
/* Synchronize with module_remove_driver() */
|
||||
rcu_read_lock();
|
||||
driver = READ_ONCE(dev->driver);
|
||||
if (driver)
|
||||
add_uevent_var(env, "DRIVER=%s", driver->name);
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Add common DT information about the device */
|
||||
of_device_uevent(dev, env);
|
||||
@@ -1684,11 +1690,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
|
||||
if (!env)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Synchronize with really_probe() */
|
||||
device_lock(dev);
|
||||
/* let the kset specific function add its keys */
|
||||
retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
|
||||
device_unlock(dev);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -1057,7 +1057,11 @@ EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
|
||||
*/
|
||||
void devm_free_percpu(struct device *dev, void __percpu *pdata)
|
||||
{
|
||||
WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match,
|
||||
(void *)pdata));
|
||||
/*
|
||||
* Use devres_release() to prevent memory leakage as
|
||||
* devm_free_pages() does.
|
||||
*/
|
||||
WARN_ON(devres_release(dev, devm_percpu_release, devm_percpu_match,
|
||||
(__force void *)pdata));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_free_percpu);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include "base.h"
|
||||
|
||||
static char *make_driver_name(struct device_driver *drv)
|
||||
@@ -77,6 +78,9 @@ void module_remove_driver(struct device_driver *drv)
|
||||
if (!drv)
|
||||
return;
|
||||
|
||||
/* Synchronize with dev_uevent() */
|
||||
synchronize_rcu();
|
||||
|
||||
sysfs_remove_link(&drv->p->kobj, "module");
|
||||
|
||||
if (drv->owner)
|
||||
|
||||
@@ -773,7 +773,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
break;
|
||||
|
||||
case HCIUARTGETPROTO:
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags) &&
|
||||
test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
err = hu->proto->id;
|
||||
else
|
||||
err = -EUNATCH;
|
||||
|
||||
@@ -142,8 +142,10 @@ static int __init mod_init(void)
|
||||
|
||||
found:
|
||||
err = pci_read_config_dword(pdev, 0x58, &pmbase);
|
||||
if (err)
|
||||
if (err) {
|
||||
err = pcibios_err_to_errno(err);
|
||||
goto put_dev;
|
||||
}
|
||||
|
||||
pmbase &= 0x0000FF00;
|
||||
if (pmbase == 0) {
|
||||
|
||||
@@ -52,6 +52,8 @@ static int tpm_bios_measurements_open(struct inode *inode,
|
||||
if (!err) {
|
||||
seq = file->private_data;
|
||||
seq->private = chip;
|
||||
} else {
|
||||
put_device(&chip->dev);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
@@ -518,6 +518,7 @@ static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
|
||||
static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct sh_cmt_channel *ch = dev_id;
|
||||
unsigned long flags;
|
||||
|
||||
/* clear flags */
|
||||
sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
|
||||
@@ -548,6 +549,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
|
||||
|
||||
ch->flags &= ~FLAG_SKIPEVENT;
|
||||
|
||||
raw_spin_lock_irqsave(&ch->lock, flags);
|
||||
|
||||
if (ch->flags & FLAG_REPROGRAM) {
|
||||
ch->flags &= ~FLAG_REPROGRAM;
|
||||
sh_cmt_clock_event_program_verify(ch, 1);
|
||||
@@ -560,6 +563,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
|
||||
|
||||
ch->flags &= ~FLAG_IRQCONTEXT;
|
||||
|
||||
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -758,12 +763,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
|
||||
struct clock_event_device *ced)
|
||||
{
|
||||
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(!clockevent_state_oneshot(ced));
|
||||
|
||||
raw_spin_lock_irqsave(&ch->lock, flags);
|
||||
|
||||
if (likely(ch->flags & FLAG_IRQCONTEXT))
|
||||
ch->next_match_value = delta - 1;
|
||||
else
|
||||
sh_cmt_set_next(ch, delta - 1);
|
||||
__sh_cmt_set_next(ch, delta - 1);
|
||||
|
||||
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -288,16 +288,24 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
switch (args->in.op) {
|
||||
case AMDGPU_CTX_OP_ALLOC_CTX:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
|
||||
args->out.alloc.ctx_id = id;
|
||||
break;
|
||||
case AMDGPU_CTX_OP_FREE_CTX:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_free(fpriv, id);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_QUERY_STATE:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_QUERY_STATE2:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -714,7 +714,8 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
|
||||
uint32_t created = 0;
|
||||
uint32_t allocated = 0;
|
||||
uint32_t tmp, handle = 0;
|
||||
uint32_t *size = &tmp;
|
||||
uint32_t dummy = 0xffffffff;
|
||||
uint32_t *size = &dummy;
|
||||
unsigned idx;
|
||||
int i, r = 0;
|
||||
|
||||
|
||||
@@ -1109,7 +1109,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
|
||||
u32 status_reg;
|
||||
u8 *buffer = msg->buffer;
|
||||
unsigned int i;
|
||||
int num_transferred = 0;
|
||||
int ret;
|
||||
|
||||
/* Buffer size of AUX CH is 16 bytes */
|
||||
@@ -1161,7 +1160,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
|
||||
reg = buffer[i];
|
||||
writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
|
||||
4 * i);
|
||||
num_transferred++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,7 +1207,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
|
||||
reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
|
||||
4 * i);
|
||||
buffer[i] = (unsigned char)reg;
|
||||
num_transferred++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1226,7 +1223,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
|
||||
(msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
|
||||
msg->reply = DP_AUX_NATIVE_REPLY_ACK;
|
||||
|
||||
return num_transferred > 0 ? num_transferred : -EBUSY;
|
||||
return msg->size;
|
||||
|
||||
aux_error:
|
||||
/* if aux err happen, reset aux */
|
||||
|
||||
@@ -1713,6 +1713,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
var->xres_virtual = fb->width;
|
||||
var->yres_virtual = fb->height;
|
||||
|
||||
/*
|
||||
* Workaround for SDL 1.2, which is known to be setting all pixel format
|
||||
* fields values to zero in some cases. We treat this situation as a
|
||||
|
||||
@@ -370,9 +370,11 @@ static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj)
|
||||
|
||||
static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
|
||||
{
|
||||
if (op & ETNA_PREP_READ)
|
||||
op &= ETNA_PREP_READ | ETNA_PREP_WRITE;
|
||||
|
||||
if (op == ETNA_PREP_READ)
|
||||
return DMA_FROM_DEVICE;
|
||||
else if (op & ETNA_PREP_WRITE)
|
||||
else if (op == ETNA_PREP_WRITE)
|
||||
return DMA_TO_DEVICE;
|
||||
else
|
||||
return DMA_BIDIRECTIONAL;
|
||||
|
||||
@@ -404,6 +404,9 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
|
||||
if (mode_dev->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode =
|
||||
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
|
||||
if (!mode)
|
||||
return 0;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -519,6 +519,9 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
|
||||
if (mode_dev->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode =
|
||||
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
|
||||
if (!mode)
|
||||
return 0;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2009,6 +2009,39 @@ compute_partial_view(struct drm_i915_gem_object *obj,
|
||||
return view;
|
||||
}
|
||||
|
||||
static void set_address_limits(struct vm_area_struct *area,
|
||||
struct i915_vma *vma,
|
||||
unsigned long *start_vaddr,
|
||||
unsigned long *end_vaddr)
|
||||
{
|
||||
unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */
|
||||
long start, end; /* memory boundaries */
|
||||
|
||||
/*
|
||||
* Let's move into the ">> PAGE_SHIFT"
|
||||
* domain to be sure not to lose bits
|
||||
*/
|
||||
vm_start = area->vm_start >> PAGE_SHIFT;
|
||||
vm_end = area->vm_end >> PAGE_SHIFT;
|
||||
vma_size = vma->size >> PAGE_SHIFT;
|
||||
|
||||
/*
|
||||
* Calculate the memory boundaries by considering the offset
|
||||
* provided by the user during memory mapping and the offset
|
||||
* provided for the partial mapping.
|
||||
*/
|
||||
start = vm_start;
|
||||
start += vma->ggtt_view.partial.offset;
|
||||
end = start + vma_size;
|
||||
|
||||
start = max_t(long, start, vm_start);
|
||||
end = min_t(long, end, vm_end);
|
||||
|
||||
/* Let's move back into the "<< PAGE_SHIFT" domain */
|
||||
*start_vaddr = (unsigned long)start << PAGE_SHIFT;
|
||||
*end_vaddr = (unsigned long)end << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_fault - fault a page into the GTT
|
||||
* @vmf: fault info
|
||||
@@ -2036,8 +2069,10 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
||||
bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
|
||||
unsigned long start, end; /* memory boundaries */
|
||||
struct i915_vma *vma;
|
||||
pgoff_t page_offset;
|
||||
unsigned long pfn;
|
||||
int ret;
|
||||
|
||||
/* Sanity check that we allow writing into this object */
|
||||
@@ -2119,12 +2154,14 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
|
||||
if (ret)
|
||||
goto err_unpin;
|
||||
|
||||
set_address_limits(area, vma, &start, &end);
|
||||
|
||||
pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT;
|
||||
pfn += (start - area->vm_start) >> PAGE_SHIFT;
|
||||
pfn -= vma->ggtt_view.partial.offset;
|
||||
|
||||
/* Finally, remap it using the new GTT offset */
|
||||
ret = remap_io_mapping(area,
|
||||
area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT),
|
||||
(ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
|
||||
min_t(u64, vma->size, area->vm_end - area->vm_start),
|
||||
&ggtt->iomap);
|
||||
ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap);
|
||||
if (ret)
|
||||
goto err_fence;
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
|
||||
i2c->adapter.algo_data = &i2c->bit;
|
||||
|
||||
i2c->bit.udelay = 10;
|
||||
i2c->bit.timeout = 2;
|
||||
i2c->bit.timeout = usecs_to_jiffies(2200);
|
||||
i2c->bit.data = i2c;
|
||||
i2c->bit.setsda = mga_gpio_setsda;
|
||||
i2c->bit.setscl = mga_gpio_setscl;
|
||||
|
||||
@@ -41,24 +41,14 @@
|
||||
* @fmt: Pointer to format string
|
||||
*/
|
||||
#define DPU_DEBUG(fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_KMS)) \
|
||||
DRM_DEBUG(fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* DPU_DEBUG_DRIVER - macro for hardware driver logging
|
||||
* @fmt: Pointer to format string
|
||||
*/
|
||||
#define DPU_DEBUG_DRIVER(fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
|
||||
DRM_ERROR(fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)
|
||||
#define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
|
||||
|
||||
@@ -100,7 +100,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv,
|
||||
{
|
||||
struct vmw_escape_video_flush *flush;
|
||||
size_t fifo_size;
|
||||
bool have_so = (dev_priv->active_display_unit == vmw_du_screen_object);
|
||||
bool have_so = (dev_priv->active_display_unit != vmw_du_legacy);
|
||||
int i, num_items;
|
||||
SVGAGuestPtr ptr;
|
||||
|
||||
|
||||
@@ -1830,12 +1830,14 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
|
||||
int fmax = field->logical_maximum;
|
||||
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
int resolution_code = code;
|
||||
int resolution = hidinput_calc_abs_res(field, resolution_code);
|
||||
int resolution;
|
||||
|
||||
if (equivalent_usage == HID_DG_TWIST) {
|
||||
resolution_code = ABS_RZ;
|
||||
}
|
||||
|
||||
resolution = hidinput_calc_abs_res(field, resolution_code);
|
||||
|
||||
if (equivalent_usage == HID_GD_X) {
|
||||
fmin += features->offset_left;
|
||||
fmax -= features->offset_right;
|
||||
|
||||
@@ -1785,7 +1785,7 @@ static void adt7475_read_pwm(struct i2c_client *client, int index)
|
||||
data->pwm[CONTROL][index] &= ~0xE0;
|
||||
data->pwm[CONTROL][index] |= (7 << 5);
|
||||
|
||||
i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
|
||||
i2c_smbus_write_byte_data(client, PWM_REG(index),
|
||||
data->pwm[INPUT][index]);
|
||||
|
||||
i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
|
||||
|
||||
@@ -251,7 +251,7 @@ static struct max6697_data *max6697_update_device(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t show_temp_input(struct device *dev,
|
||||
static ssize_t temp_input_show(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
int index = to_sensor_dev_attr(devattr)->index;
|
||||
@@ -267,8 +267,8 @@ static ssize_t show_temp_input(struct device *dev,
|
||||
return sprintf(buf, "%d\n", temp * 125);
|
||||
}
|
||||
|
||||
static ssize_t show_temp(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||
int index = to_sensor_dev_attr_2(devattr)->index;
|
||||
@@ -284,7 +284,7 @@ static ssize_t show_temp(struct device *dev,
|
||||
return sprintf(buf, "%d\n", temp * 1000);
|
||||
}
|
||||
|
||||
static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int index = to_sensor_dev_attr(attr)->index;
|
||||
@@ -299,9 +299,9 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
|
||||
return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1);
|
||||
}
|
||||
|
||||
static ssize_t set_temp(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t temp_store(struct device *dev,
|
||||
struct device_attribute *devattr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||
int index = to_sensor_dev_attr_2(devattr)->index;
|
||||
@@ -314,6 +314,7 @@ static ssize_t set_temp(struct device *dev,
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
temp = clamp_val(temp, -1000000, 1000000); /* prevent underflow */
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
|
||||
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
|
||||
data->temp[nr][index] = temp;
|
||||
@@ -326,79 +327,63 @@ static ssize_t set_temp(struct device *dev,
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
0, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
0, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, 0, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, 0, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
1, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
1, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp, 1, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp2_crit, temp, 1, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
2, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
2, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp3_input, temp_input, 2);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp3_max, temp, 2, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp3_crit, temp, 2, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
3, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
3, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp4_input, temp_input, 3);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp4_max, temp, 3, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp4_crit, temp, 3, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
4, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
4, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp5_input, temp_input, 4);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp5_max, temp, 4, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp5_crit, temp, 4, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
5, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
5, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp6_input, temp_input, 5);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp6_max, temp, 5, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp6_crit, temp, 5, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_input, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
6, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
6, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp7_input, temp_input, 6);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp7_max, temp, 6, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp7_crit, temp, 6, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_input, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
7, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
7, MAX6697_TEMP_CRIT);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp8_input, temp_input, 7);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp8_max, temp, 7, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2_RW(temp8_crit, temp, 7, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 22);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 16);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 17);
|
||||
static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 18);
|
||||
static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 19);
|
||||
static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, show_alarm, NULL, 20);
|
||||
static SENSOR_DEVICE_ATTR(temp7_max_alarm, S_IRUGO, show_alarm, NULL, 21);
|
||||
static SENSOR_DEVICE_ATTR(temp8_max_alarm, S_IRUGO, show_alarm, NULL, 23);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 22);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 16);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 17);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, alarm, 18);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp5_max_alarm, alarm, 19);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp6_max_alarm, alarm, 20);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp7_max_alarm, alarm, 21);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp8_max_alarm, alarm, 23);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
|
||||
static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_alarm, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(temp7_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(temp8_crit_alarm, S_IRUGO, show_alarm, NULL, 15);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 15);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 9);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 10);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, alarm, 11);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, alarm, 12);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp7_crit_alarm, alarm, 13);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp8_crit_alarm, alarm, 14);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 1);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp4_fault, alarm, 3);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp5_fault, alarm, 4);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp6_fault, alarm, 5);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp7_fault, alarm, 6);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp8_fault, alarm, 7);
|
||||
|
||||
static DEVICE_ATTR(dummy, 0, NULL, NULL);
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
|
||||
* frequency with only 62 clock ticks max (31 high, 31 low).
|
||||
* Aim for a duty of 60% LOW, 40% HIGH.
|
||||
*/
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
|
||||
|
||||
for (cks = 0; cks < 7; cks++) {
|
||||
/*
|
||||
|
||||
@@ -42,6 +42,7 @@ static int smbus_do_alert(struct device *dev, void *addrp)
|
||||
struct i2c_client *client = i2c_verify_client(dev);
|
||||
struct alert_data *data = addrp;
|
||||
struct i2c_driver *driver;
|
||||
int ret;
|
||||
|
||||
if (!client || client->addr != data->addr)
|
||||
return 0;
|
||||
@@ -55,16 +56,47 @@ static int smbus_do_alert(struct device *dev, void *addrp)
|
||||
device_lock(dev);
|
||||
if (client->dev.driver) {
|
||||
driver = to_i2c_driver(client->dev.driver);
|
||||
if (driver->alert)
|
||||
if (driver->alert) {
|
||||
/* Stop iterating after we find the device */
|
||||
driver->alert(client, data->type, data->data);
|
||||
else
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
dev_warn(&client->dev, "no driver alert()!\n");
|
||||
} else
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
} else {
|
||||
dev_dbg(&client->dev, "alert with no driver\n");
|
||||
ret = -ENODEV;
|
||||
}
|
||||
device_unlock(dev);
|
||||
|
||||
/* Stop iterating after we find the device */
|
||||
return -EBUSY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Same as above, but call back all drivers with alert handler */
|
||||
|
||||
static int smbus_do_alert_force(struct device *dev, void *addrp)
|
||||
{
|
||||
struct i2c_client *client = i2c_verify_client(dev);
|
||||
struct alert_data *data = addrp;
|
||||
struct i2c_driver *driver;
|
||||
|
||||
if (!client || (client->flags & I2C_CLIENT_TEN))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Drivers should either disable alerts, or provide at least
|
||||
* a minimal handler. Lock so the driver won't change.
|
||||
*/
|
||||
device_lock(dev);
|
||||
if (client->dev.driver) {
|
||||
driver = to_i2c_driver(client->dev.driver);
|
||||
if (driver->alert)
|
||||
driver->alert(client, data->type, data->data);
|
||||
}
|
||||
device_unlock(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -75,7 +107,7 @@ static irqreturn_t smbus_alert(int irq, void *d)
|
||||
{
|
||||
struct i2c_smbus_alert *alert = d;
|
||||
struct i2c_client *ara;
|
||||
unsigned short prev_addr = 0; /* Not a valid address */
|
||||
unsigned short prev_addr = I2C_CLIENT_END; /* Not a valid address */
|
||||
|
||||
ara = alert->ara;
|
||||
|
||||
@@ -99,17 +131,28 @@ static irqreturn_t smbus_alert(int irq, void *d)
|
||||
data.addr = status >> 1;
|
||||
data.type = I2C_PROTOCOL_SMBUS_ALERT;
|
||||
|
||||
if (data.addr == prev_addr) {
|
||||
dev_warn(&ara->dev, "Duplicate SMBALERT# from dev "
|
||||
"0x%02x, skipping\n", data.addr);
|
||||
break;
|
||||
}
|
||||
dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n",
|
||||
data.addr, data.data);
|
||||
|
||||
/* Notify driver for the device which issued the alert */
|
||||
device_for_each_child(&ara->adapter->dev, &data,
|
||||
status = device_for_each_child(&ara->adapter->dev, &data,
|
||||
smbus_do_alert);
|
||||
/*
|
||||
* If we read the same address more than once, and the alert
|
||||
* was not handled by a driver, it won't do any good to repeat
|
||||
* the loop because it will never terminate. Try again, this
|
||||
* time calling the alert handlers of all devices connected to
|
||||
* the bus, and abort the loop afterwards. If this helps, we
|
||||
* are all set. If it doesn't, there is nothing else we can do,
|
||||
* so we might as well abort the loop.
|
||||
* Note: This assumes that a driver with alert handler handles
|
||||
* the alert properly and clears it if necessary.
|
||||
*/
|
||||
if (data.addr == prev_addr && status != -EBUSY) {
|
||||
device_for_each_child(&ara->adapter->dev, &data,
|
||||
smbus_do_alert_force);
|
||||
break;
|
||||
}
|
||||
prev_addr = data.addr;
|
||||
}
|
||||
|
||||
|
||||
@@ -369,8 +369,10 @@ EXPORT_SYMBOL(iw_cm_disconnect);
|
||||
*
|
||||
* Clean up all resources associated with the connection and release
|
||||
* the initial reference taken by iw_create_cm_id.
|
||||
*
|
||||
* Returns true if and only if the last cm_id_priv reference has been dropped.
|
||||
*/
|
||||
static void destroy_cm_id(struct iw_cm_id *cm_id)
|
||||
static bool destroy_cm_id(struct iw_cm_id *cm_id)
|
||||
{
|
||||
struct iwcm_id_private *cm_id_priv;
|
||||
unsigned long flags;
|
||||
@@ -438,7 +440,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
|
||||
iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
|
||||
}
|
||||
|
||||
(void)iwcm_deref_id(cm_id_priv);
|
||||
return iwcm_deref_id(cm_id_priv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -449,7 +451,8 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
|
||||
*/
|
||||
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
|
||||
{
|
||||
destroy_cm_id(cm_id);
|
||||
if (!destroy_cm_id(cm_id))
|
||||
flush_workqueue(iwcm_wq);
|
||||
}
|
||||
EXPORT_SYMBOL(iw_destroy_cm_id);
|
||||
|
||||
@@ -1022,7 +1025,7 @@ static void cm_work_handler(struct work_struct *_work)
|
||||
if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
|
||||
ret = process_event(cm_id_priv, &levent);
|
||||
if (ret)
|
||||
destroy_cm_id(&cm_id_priv->id);
|
||||
WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
|
||||
} else
|
||||
pr_debug("dropping event %d\n", levent.event);
|
||||
if (iwcm_deref_id(cm_id_priv))
|
||||
|
||||
@@ -2112,7 +2112,7 @@ static int bnxt_re_build_send_wqe(struct bnxt_re_qp *qp,
|
||||
break;
|
||||
case IB_WR_SEND_WITH_IMM:
|
||||
wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM;
|
||||
wqe->send.imm_data = wr->ex.imm_data;
|
||||
wqe->send.imm_data = be32_to_cpu(wr->ex.imm_data);
|
||||
break;
|
||||
case IB_WR_SEND_WITH_INV:
|
||||
wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV;
|
||||
@@ -2142,7 +2142,7 @@ static int bnxt_re_build_rdma_wqe(const struct ib_send_wr *wr,
|
||||
break;
|
||||
case IB_WR_RDMA_WRITE_WITH_IMM:
|
||||
wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM;
|
||||
wqe->rdma.imm_data = wr->ex.imm_data;
|
||||
wqe->rdma.imm_data = be32_to_cpu(wr->ex.imm_data);
|
||||
break;
|
||||
case IB_WR_RDMA_READ:
|
||||
wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_READ;
|
||||
@@ -3110,7 +3110,7 @@ static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *qp,
|
||||
wc->byte_len = orig_cqe->length;
|
||||
wc->qp = &qp1_qp->ib_qp;
|
||||
|
||||
wc->ex.imm_data = orig_cqe->immdata;
|
||||
wc->ex.imm_data = cpu_to_be32(le32_to_cpu(orig_cqe->immdata));
|
||||
wc->src_qp = orig_cqe->src_qp;
|
||||
memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
|
||||
if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
|
||||
@@ -3231,7 +3231,7 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
|
||||
continue;
|
||||
}
|
||||
wc->qp = &qp->ib_qp;
|
||||
wc->ex.imm_data = cqe->immdata;
|
||||
wc->ex.imm_data = cpu_to_be32(le32_to_cpu(cqe->immdata));
|
||||
wc->src_qp = cqe->src_qp;
|
||||
memcpy(wc->smac, cqe->smac, ETH_ALEN);
|
||||
wc->port_num = 1;
|
||||
|
||||
@@ -145,7 +145,7 @@ struct bnxt_qplib_swqe {
|
||||
/* Send, with imm, inval key */
|
||||
struct {
|
||||
union {
|
||||
__be32 imm_data;
|
||||
u32 imm_data;
|
||||
u32 inv_key;
|
||||
};
|
||||
u32 q_key;
|
||||
@@ -163,7 +163,7 @@ struct bnxt_qplib_swqe {
|
||||
/* RDMA write, with imm, read */
|
||||
struct {
|
||||
union {
|
||||
__be32 imm_data;
|
||||
u32 imm_data;
|
||||
u32 inv_key;
|
||||
};
|
||||
u64 remote_va;
|
||||
@@ -349,7 +349,7 @@ struct bnxt_qplib_cqe {
|
||||
u32 length;
|
||||
u64 wr_id;
|
||||
union {
|
||||
__be32 immdata;
|
||||
__le32 immdata;
|
||||
u32 invrkey;
|
||||
};
|
||||
u64 qp_handle;
|
||||
|
||||
@@ -832,7 +832,7 @@ void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
|
||||
|
||||
int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
|
||||
{
|
||||
char alias_wq_name[15];
|
||||
char alias_wq_name[22];
|
||||
int ret = 0;
|
||||
int i, j;
|
||||
union ib_gid gid;
|
||||
|
||||
@@ -2158,7 +2158,7 @@ static int mlx4_ib_alloc_demux_ctx(struct mlx4_ib_dev *dev,
|
||||
struct mlx4_ib_demux_ctx *ctx,
|
||||
int port)
|
||||
{
|
||||
char name[12];
|
||||
char name[21];
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp,
|
||||
int solicited;
|
||||
u16 pkey;
|
||||
u32 qp_num;
|
||||
int ack_req;
|
||||
int ack_req = 0;
|
||||
|
||||
/* length from start of bth to end of icrc */
|
||||
paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
|
||||
@@ -426,6 +426,7 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp,
|
||||
qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn :
|
||||
qp->attr.dest_qp_num;
|
||||
|
||||
if (qp_type(qp) != IB_QPT_UD && qp_type(qp) != IB_QPT_UC)
|
||||
ack_req = ((pkt->mask & RXE_END_MASK) ||
|
||||
(qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK));
|
||||
if (ack_req)
|
||||
|
||||
@@ -48,6 +48,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
|
||||
return 0;
|
||||
if (mt)
|
||||
return mt->num_slots != num_slots ? -EINVAL : 0;
|
||||
/* Arbitrary limit for avoiding too large memory allocation. */
|
||||
if (num_slots > 1024)
|
||||
return -EINVAL;
|
||||
|
||||
mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
|
||||
if (!mt)
|
||||
|
||||
@@ -1270,6 +1270,8 @@ static int __maybe_unused elan_suspend(struct device *dev)
|
||||
}
|
||||
|
||||
err:
|
||||
if (ret)
|
||||
enable_irq(client->irq);
|
||||
mutex_unlock(&data->sysfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1527,16 +1527,47 @@ static void elantech_disconnect(struct psmouse *psmouse)
|
||||
psmouse->private = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some hw_version 4 models fail to properly activate absolute mode on
|
||||
* resume without going through disable/enable cycle.
|
||||
*/
|
||||
static const struct dmi_system_id elantech_needs_reenable[] = {
|
||||
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
||||
{
|
||||
/* Lenovo N24 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "81AF"),
|
||||
},
|
||||
},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Put the touchpad back into absolute mode when reconnecting
|
||||
*/
|
||||
static int elantech_reconnect(struct psmouse *psmouse)
|
||||
{
|
||||
int err;
|
||||
|
||||
psmouse_reset(psmouse);
|
||||
|
||||
if (elantech_detect(psmouse, 0))
|
||||
return -1;
|
||||
|
||||
if (dmi_check_system(elantech_needs_reenable)) {
|
||||
err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE);
|
||||
if (err)
|
||||
psmouse_warn(psmouse, "failed to deactivate mouse on %s: %d\n",
|
||||
psmouse->ps2dev.serio->phys, err);
|
||||
|
||||
err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
|
||||
if (err)
|
||||
psmouse_warn(psmouse, "failed to reactivate mouse on %s: %d\n",
|
||||
psmouse->ps2dev.serio->phys, err);
|
||||
}
|
||||
|
||||
if (elantech_set_absolute_mode(psmouse)) {
|
||||
psmouse_err(psmouse,
|
||||
"failed to put touchpad back into absolute mode.\n");
|
||||
|
||||
@@ -78,7 +78,6 @@ struct silead_ts_data {
|
||||
struct regulator_bulk_data regulators[2];
|
||||
char fw_name[64];
|
||||
struct touchscreen_properties prop;
|
||||
u32 max_fingers;
|
||||
u32 chip_id;
|
||||
struct input_mt_pos pos[SILEAD_MAX_FINGERS];
|
||||
int slots[SILEAD_MAX_FINGERS];
|
||||
@@ -106,7 +105,7 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
|
||||
input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
|
||||
touchscreen_parse_properties(data->input, true, &data->prop);
|
||||
|
||||
input_mt_init_slots(data->input, data->max_fingers,
|
||||
input_mt_init_slots(data->input, SILEAD_MAX_FINGERS,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
|
||||
INPUT_MT_TRACK);
|
||||
|
||||
@@ -153,10 +152,10 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf[0] > data->max_fingers) {
|
||||
if (buf[0] > SILEAD_MAX_FINGERS) {
|
||||
dev_warn(dev, "More touches reported then supported %d > %d\n",
|
||||
buf[0], data->max_fingers);
|
||||
buf[0] = data->max_fingers;
|
||||
buf[0], SILEAD_MAX_FINGERS);
|
||||
buf[0] = SILEAD_MAX_FINGERS;
|
||||
}
|
||||
|
||||
touch_nr = 0;
|
||||
@@ -208,7 +207,6 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
|
||||
static int silead_ts_init(struct i2c_client *client)
|
||||
{
|
||||
struct silead_ts_data *data = i2c_get_clientdata(client);
|
||||
int error;
|
||||
|
||||
error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
|
||||
@@ -218,7 +216,7 @@ static int silead_ts_init(struct i2c_client *client)
|
||||
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
|
||||
|
||||
error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR,
|
||||
data->max_fingers);
|
||||
SILEAD_MAX_FINGERS);
|
||||
if (error)
|
||||
goto i2c_write_err;
|
||||
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
|
||||
@@ -445,13 +443,6 @@ static void silead_ts_read_props(struct i2c_client *client)
|
||||
const char *str;
|
||||
int error;
|
||||
|
||||
error = device_property_read_u32(dev, "silead,max-fingers",
|
||||
&data->max_fingers);
|
||||
if (error) {
|
||||
dev_dbg(dev, "Max fingers read error %d\n", error);
|
||||
data->max_fingers = 5; /* Most devices handle up-to 5 fingers */
|
||||
}
|
||||
|
||||
error = device_property_read_string(dev, "firmware-name", &str);
|
||||
if (!error)
|
||||
snprintf(data->fw_name, sizeof(data->fw_name),
|
||||
|
||||
@@ -2958,8 +2958,6 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
|
||||
struct page *vprop_page;
|
||||
int base, nr_ids, i, err = 0;
|
||||
|
||||
BUG_ON(!vm);
|
||||
|
||||
bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids);
|
||||
if (!bitmap)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -75,6 +75,20 @@ struct mbigen_device {
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
static inline unsigned int get_mbigen_node_offset(unsigned int nid)
|
||||
{
|
||||
unsigned int offset = nid * MBIGEN_NODE_OFFSET;
|
||||
|
||||
/*
|
||||
* To avoid touched clear register in unexpected way, we need to directly
|
||||
* skip clear register when access to more than 10 mbigen nodes.
|
||||
*/
|
||||
if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET))
|
||||
offset += MBIGEN_NODE_OFFSET;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
|
||||
{
|
||||
unsigned int nid, pin;
|
||||
@@ -83,8 +97,7 @@ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
|
||||
nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
|
||||
pin = hwirq % IRQS_PER_MBIGEN_NODE;
|
||||
|
||||
return pin * 4 + nid * MBIGEN_NODE_OFFSET
|
||||
+ REG_MBIGEN_VEC_OFFSET;
|
||||
return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
|
||||
}
|
||||
|
||||
static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
|
||||
@@ -99,8 +112,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
|
||||
*mask = 1 << (irq_ofst % 32);
|
||||
ofst = irq_ofst / 32 * 4;
|
||||
|
||||
*addr = ofst + nid * MBIGEN_NODE_OFFSET
|
||||
+ REG_MBIGEN_TYPE_OFFSET;
|
||||
*addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
|
||||
}
|
||||
|
||||
static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
|
||||
|
||||
@@ -1945,7 +1945,7 @@ hfcmulti_dtmf(struct hfc_multi *hc)
|
||||
static void
|
||||
hfcmulti_tx(struct hfc_multi *hc, int ch)
|
||||
{
|
||||
int i, ii, temp, len = 0;
|
||||
int i, ii, temp, tmp_len, len = 0;
|
||||
int Zspace, z1, z2; /* must be int for calculation */
|
||||
int Fspace, f1, f2;
|
||||
u_char *d;
|
||||
@@ -2166,14 +2166,15 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
|
||||
HFC_wait_nodebug(hc);
|
||||
}
|
||||
|
||||
tmp_len = (*sp)->len;
|
||||
dev_kfree_skb(*sp);
|
||||
/* check for next frame */
|
||||
if (bch && get_next_bframe(bch)) {
|
||||
len = (*sp)->len;
|
||||
len = tmp_len;
|
||||
goto next_frame;
|
||||
}
|
||||
if (dch && get_next_dframe(dch)) {
|
||||
len = (*sp)->len;
|
||||
len = tmp_len;
|
||||
goto next_frame;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,9 +126,9 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
|
||||
flags);
|
||||
cancel_work_sync(&led_cdev->set_brightness_work);
|
||||
led_stop_software_blink(led_cdev);
|
||||
device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
|
||||
if (led_cdev->trigger->deactivate)
|
||||
led_cdev->trigger->deactivate(led_cdev);
|
||||
device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
|
||||
led_cdev->trigger = NULL;
|
||||
led_cdev->trigger_data = NULL;
|
||||
led_cdev->activated = false;
|
||||
|
||||
@@ -368,8 +368,10 @@ static int ich7_lpc_probe(struct pci_dev *dev,
|
||||
|
||||
nas_gpio_pci_dev = dev;
|
||||
status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base);
|
||||
if (status)
|
||||
if (status) {
|
||||
status = pcibios_err_to_errno(status);
|
||||
goto out;
|
||||
}
|
||||
g_pm_io_base &= 0x00000ff80;
|
||||
|
||||
status = pci_read_config_dword(dev, GPIO_CTRL, &gc);
|
||||
@@ -381,8 +383,9 @@ static int ich7_lpc_probe(struct pci_dev *dev,
|
||||
}
|
||||
|
||||
status = pci_read_config_dword(dev, GPIO_BASE, &nas_gpio_io_base);
|
||||
if (0 > status) {
|
||||
if (status) {
|
||||
dev_info(&dev->dev, "Unable to read GPIOBASE.\n");
|
||||
status = pcibios_err_to_errno(status);
|
||||
goto out;
|
||||
}
|
||||
dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base);
|
||||
|
||||
@@ -549,7 +549,7 @@ g4fan_exit( void )
|
||||
platform_driver_unregister( &therm_of_driver );
|
||||
|
||||
if( x.of_dev )
|
||||
of_device_unregister( x.of_dev );
|
||||
of_platform_device_destroy(&x.of_dev->dev, NULL);
|
||||
}
|
||||
|
||||
module_init(g4fan_init);
|
||||
|
||||
@@ -1039,8 +1039,26 @@ static int do_resume(struct dm_ioctl *param)
|
||||
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
|
||||
if (param->flags & DM_NOFLUSH_FLAG)
|
||||
suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
|
||||
if (!dm_suspended_md(md))
|
||||
dm_suspend(md, suspend_flags);
|
||||
if (!dm_suspended_md(md)) {
|
||||
r = dm_suspend(md, suspend_flags);
|
||||
if (r) {
|
||||
down_write(&_hash_lock);
|
||||
hc = dm_get_mdptr(md);
|
||||
if (hc && !hc->new_map) {
|
||||
hc->new_map = new_map;
|
||||
new_map = NULL;
|
||||
} else {
|
||||
r = -ENXIO;
|
||||
}
|
||||
up_write(&_hash_lock);
|
||||
if (new_map) {
|
||||
dm_sync_table(md);
|
||||
dm_table_destroy(new_map);
|
||||
}
|
||||
dm_put(md);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
old_map = dm_swap_table(md, new_map);
|
||||
if (IS_ERR(old_map)) {
|
||||
|
||||
@@ -2585,7 +2585,7 @@ static int dm_wait_for_completion(struct mapped_device *md, long task_state)
|
||||
break;
|
||||
|
||||
if (signal_pending_state(task_state, current)) {
|
||||
r = -EINTR;
|
||||
r = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -7245,11 +7245,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
|
||||
mddev = bdev->bd_disk->private_data;
|
||||
|
||||
if (!mddev) {
|
||||
BUG();
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Some actions do not requires the mutex */
|
||||
switch (cmd) {
|
||||
case GET_ARRAY_INFO:
|
||||
|
||||
@@ -275,7 +275,7 @@ static void sm_metadata_destroy(struct dm_space_map *sm)
|
||||
{
|
||||
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
|
||||
|
||||
kfree(smm);
|
||||
kvfree(smm);
|
||||
}
|
||||
|
||||
static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
|
||||
@@ -759,7 +759,7 @@ struct dm_space_map *dm_sm_metadata_init(void)
|
||||
{
|
||||
struct sm_metadata *smm;
|
||||
|
||||
smm = kmalloc(sizeof(*smm), GFP_KERNEL);
|
||||
smm = kvmalloc(sizeof(*smm), GFP_KERNEL);
|
||||
if (!smm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
||||
@@ -5818,7 +5818,9 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
|
||||
safepos = conf->reshape_safe;
|
||||
sector_div(safepos, data_disks);
|
||||
if (mddev->reshape_backwards) {
|
||||
BUG_ON(writepos < reshape_sectors);
|
||||
if (WARN_ON(writepos < reshape_sectors))
|
||||
return MaxSector;
|
||||
|
||||
writepos -= reshape_sectors;
|
||||
readpos += reshape_sectors;
|
||||
safepos += reshape_sectors;
|
||||
@@ -5836,14 +5838,18 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
|
||||
* to set 'stripe_addr' which is where we will write to.
|
||||
*/
|
||||
if (mddev->reshape_backwards) {
|
||||
BUG_ON(conf->reshape_progress == 0);
|
||||
if (WARN_ON(conf->reshape_progress == 0))
|
||||
return MaxSector;
|
||||
|
||||
stripe_addr = writepos;
|
||||
BUG_ON((mddev->dev_sectors &
|
||||
~((sector_t)reshape_sectors - 1))
|
||||
- reshape_sectors - stripe_addr
|
||||
!= sector_nr);
|
||||
if (WARN_ON((mddev->dev_sectors &
|
||||
~((sector_t)reshape_sectors - 1)) -
|
||||
reshape_sectors - stripe_addr != sector_nr))
|
||||
return MaxSector;
|
||||
} else {
|
||||
BUG_ON(writepos != sector_nr + reshape_sectors);
|
||||
if (WARN_ON(writepos != sector_nr + reshape_sectors))
|
||||
return MaxSector;
|
||||
|
||||
stripe_addr = sector_nr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1297,6 +1297,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
/* register Video device */
|
||||
dev->video_dev = cx23885_vdev_init(dev, dev->pci,
|
||||
&cx23885_video_template, "video");
|
||||
if (!dev->video_dev) {
|
||||
err = -ENOMEM;
|
||||
goto fail_unreg;
|
||||
}
|
||||
dev->video_dev->queue = &dev->vb2_vidq;
|
||||
err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
|
||||
video_nr[dev->nr]);
|
||||
@@ -1311,6 +1315,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
/* register VBI device */
|
||||
dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
|
||||
&cx23885_vbi_template, "vbi");
|
||||
if (!dev->vbi_dev) {
|
||||
err = -ENOMEM;
|
||||
goto fail_unreg;
|
||||
}
|
||||
dev->vbi_dev->queue = &dev->vb2_vbiq;
|
||||
err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
|
||||
vbi_nr[dev->nr]);
|
||||
|
||||
@@ -475,7 +475,9 @@ static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
|
||||
/* switch the board to analog mode */
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
|
||||
if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1027,7 +1029,9 @@ static int md8800_set_voltage2(struct dvb_frontend *fe,
|
||||
else
|
||||
wbuf[1] = rbuf & 0xef;
|
||||
msg[0].len = 2;
|
||||
i2c_transfer(&dev->i2c_adap, msg, 1);
|
||||
if (i2c_transfer(&dev->i2c_adap, msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1096,6 +1096,7 @@ static int vdec_close(struct file *file)
|
||||
{
|
||||
struct venus_inst *inst = to_inst(file);
|
||||
|
||||
cancel_work_sync(&inst->delayed_process_work);
|
||||
v4l2_m2m_ctx_release(inst->m2m_ctx);
|
||||
v4l2_m2m_release(inst->m2m_dev);
|
||||
vdec_ctrl_deinit(inst);
|
||||
|
||||
@@ -36,9 +36,8 @@ struct vsp1_histogram_buffer *
|
||||
vsp1_histogram_buffer_get(struct vsp1_histogram *histo)
|
||||
{
|
||||
struct vsp1_histogram_buffer *buf = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&histo->irqlock, flags);
|
||||
spin_lock(&histo->irqlock);
|
||||
|
||||
if (list_empty(&histo->irqqueue))
|
||||
goto done;
|
||||
@@ -49,7 +48,7 @@ vsp1_histogram_buffer_get(struct vsp1_histogram *histo)
|
||||
histo->readout = true;
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&histo->irqlock, flags);
|
||||
spin_unlock(&histo->irqlock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -58,7 +57,6 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
|
||||
size_t size)
|
||||
{
|
||||
struct vsp1_pipeline *pipe = histo->entity.pipe;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* The pipeline pointer is guaranteed to be valid as this function is
|
||||
@@ -70,10 +68,10 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
|
||||
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, size);
|
||||
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
|
||||
|
||||
spin_lock_irqsave(&histo->irqlock, flags);
|
||||
spin_lock(&histo->irqlock);
|
||||
histo->readout = false;
|
||||
wake_up(&histo->wait_queue);
|
||||
spin_unlock_irqrestore(&histo->irqlock, flags);
|
||||
spin_unlock(&histo->irqlock);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@@ -124,11 +122,10 @@ static void histo_buffer_queue(struct vb2_buffer *vb)
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue);
|
||||
struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&histo->irqlock, flags);
|
||||
spin_lock_irq(&histo->irqlock);
|
||||
list_add_tail(&buf->queue, &histo->irqqueue);
|
||||
spin_unlock_irqrestore(&histo->irqlock, flags);
|
||||
spin_unlock_irq(&histo->irqlock);
|
||||
}
|
||||
|
||||
static int histo_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
@@ -140,9 +137,8 @@ static void histo_stop_streaming(struct vb2_queue *vq)
|
||||
{
|
||||
struct vsp1_histogram *histo = vb2_get_drv_priv(vq);
|
||||
struct vsp1_histogram_buffer *buffer;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&histo->irqlock, flags);
|
||||
spin_lock_irq(&histo->irqlock);
|
||||
|
||||
/* Remove all buffers from the IRQ queue. */
|
||||
list_for_each_entry(buffer, &histo->irqqueue, queue)
|
||||
@@ -152,7 +148,7 @@ static void histo_stop_streaming(struct vb2_queue *vq)
|
||||
/* Wait for the buffer being read out (if any) to complete. */
|
||||
wait_event_lock_irq(histo->wait_queue, !histo->readout, histo->irqlock);
|
||||
|
||||
spin_unlock_irqrestore(&histo->irqlock, flags);
|
||||
spin_unlock_irq(&histo->irqlock);
|
||||
}
|
||||
|
||||
static const struct vb2_ops histo_video_queue_qops = {
|
||||
|
||||
@@ -73,7 +73,7 @@ struct vsp1_partition_window {
|
||||
* @wpf: The WPF partition window configuration
|
||||
*/
|
||||
struct vsp1_partition {
|
||||
struct vsp1_partition_window rpf;
|
||||
struct vsp1_partition_window rpf[VSP1_MAX_RPF];
|
||||
struct vsp1_partition_window uds_sink;
|
||||
struct vsp1_partition_window uds_source;
|
||||
struct vsp1_partition_window sru;
|
||||
|
||||
@@ -270,8 +270,8 @@ static void rpf_configure_partition(struct vsp1_entity *entity,
|
||||
* 'width' need to be adjusted.
|
||||
*/
|
||||
if (pipe->partitions > 1) {
|
||||
crop.width = pipe->partition->rpf.width;
|
||||
crop.left += pipe->partition->rpf.left;
|
||||
crop.width = pipe->partition->rpf[rpf->entity.index].width;
|
||||
crop.left += pipe->partition->rpf[rpf->entity.index].left;
|
||||
}
|
||||
|
||||
if (pipe->interlaced) {
|
||||
@@ -326,7 +326,9 @@ static void rpf_partition(struct vsp1_entity *entity,
|
||||
unsigned int partition_idx,
|
||||
struct vsp1_partition_window *window)
|
||||
{
|
||||
partition->rpf = *window;
|
||||
struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
|
||||
|
||||
partition->rpf[rpf->entity.index] = *window;
|
||||
}
|
||||
|
||||
static const struct vsp1_entity_operations rpf_entity_ops = {
|
||||
|
||||
@@ -1126,10 +1126,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto)
|
||||
|
||||
memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
|
||||
|
||||
if (!mutex_is_locked(&ictx->lock)) {
|
||||
unlock = true;
|
||||
mutex_lock(&ictx->lock);
|
||||
}
|
||||
unlock = mutex_trylock(&ictx->lock);
|
||||
|
||||
retval = send_packet(ictx);
|
||||
if (retval)
|
||||
|
||||
@@ -997,8 +997,45 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
|
||||
return value;
|
||||
}
|
||||
|
||||
static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
|
||||
struct uvc_control *ctrl)
|
||||
{
|
||||
u8 *data;
|
||||
int ret;
|
||||
|
||||
if (ctrl->loaded)
|
||||
return 0;
|
||||
|
||||
data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);
|
||||
|
||||
if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
|
||||
memset(data, 0, ctrl->info.size);
|
||||
ctrl->loaded = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctrl->entity->get_cur)
|
||||
ret = ctrl->entity->get_cur(chain->dev, ctrl->entity,
|
||||
ctrl->info.selector, data,
|
||||
ctrl->info.size);
|
||||
else
|
||||
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
|
||||
ctrl->entity->id, chain->dev->intfnum,
|
||||
ctrl->info.selector, data,
|
||||
ctrl->info.size);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ctrl->loaded = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __uvc_ctrl_get(struct uvc_video_chain *chain,
|
||||
struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
|
||||
struct uvc_control *ctrl,
|
||||
struct uvc_control_mapping *mapping,
|
||||
s32 *value)
|
||||
{
|
||||
int ret;
|
||||
@@ -1006,17 +1043,10 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain,
|
||||
if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
|
||||
return -EACCES;
|
||||
|
||||
if (!ctrl->loaded) {
|
||||
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
|
||||
chain->dev->intfnum, ctrl->info.selector,
|
||||
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
|
||||
ctrl->info.size);
|
||||
ret = __uvc_ctrl_load_cur(chain, ctrl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ctrl->loaded = 1;
|
||||
}
|
||||
|
||||
*value = __uvc_ctrl_get_value(mapping,
|
||||
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
|
||||
|
||||
@@ -1670,23 +1700,12 @@ int uvc_ctrl_set(struct uvc_fh *handle,
|
||||
* needs to be loaded from the device to perform the read-modify-write
|
||||
* operation.
|
||||
*/
|
||||
if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
|
||||
if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
|
||||
memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
|
||||
0, ctrl->info.size);
|
||||
} else {
|
||||
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
|
||||
ctrl->entity->id, chain->dev->intfnum,
|
||||
ctrl->info.selector,
|
||||
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
|
||||
ctrl->info.size);
|
||||
if ((ctrl->info.size * 8) != mapping->size) {
|
||||
ret = __uvc_ctrl_load_cur(chain, ctrl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctrl->loaded = 1;
|
||||
}
|
||||
|
||||
/* Backup the current value in case we need to rollback later. */
|
||||
if (!ctrl->dirty) {
|
||||
memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
|
||||
@@ -1723,9 +1742,19 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev,
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
|
||||
info->selector, data, 1);
|
||||
if (!ret)
|
||||
if (ctrl->entity->get_info)
|
||||
ret = ctrl->entity->get_info(dev, ctrl->entity,
|
||||
ctrl->info.selector, data);
|
||||
else
|
||||
ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id,
|
||||
dev->intfnum, info->selector, data, 1);
|
||||
|
||||
if (!ret) {
|
||||
info->flags &= ~(UVC_CTRL_FLAG_GET_CUR |
|
||||
UVC_CTRL_FLAG_SET_CUR |
|
||||
UVC_CTRL_FLAG_AUTO_UPDATE |
|
||||
UVC_CTRL_FLAG_ASYNCHRONOUS);
|
||||
|
||||
info->flags |= (data[0] & UVC_CONTROL_CAP_GET ?
|
||||
UVC_CTRL_FLAG_GET_CUR : 0)
|
||||
| (data[0] & UVC_CONTROL_CAP_SET ?
|
||||
@@ -1734,6 +1763,7 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev,
|
||||
UVC_CTRL_FLAG_AUTO_UPDATE : 0)
|
||||
| (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ?
|
||||
UVC_CTRL_FLAG_ASYNCHRONOUS : 0);
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return ret;
|
||||
|
||||
@@ -214,13 +214,13 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
|
||||
/* Compute a bandwidth estimation by multiplying the frame
|
||||
* size by the number of video frames per second, divide the
|
||||
* result by the number of USB frames (or micro-frames for
|
||||
* high-speed devices) per second and add the UVC header size
|
||||
* (assumed to be 12 bytes long).
|
||||
* high- and super-speed devices) per second and add the UVC
|
||||
* header size (assumed to be 12 bytes long).
|
||||
*/
|
||||
bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
|
||||
bandwidth *= 10000000 / interval + 1;
|
||||
bandwidth /= 1000;
|
||||
if (stream->dev->udev->speed == USB_SPEED_HIGH)
|
||||
if (stream->dev->udev->speed >= USB_SPEED_HIGH)
|
||||
bandwidth /= 8;
|
||||
bandwidth += 12;
|
||||
|
||||
@@ -475,6 +475,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
|
||||
ktime_t time;
|
||||
u16 host_sof;
|
||||
u16 dev_sof;
|
||||
u32 dev_stc;
|
||||
|
||||
switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
|
||||
case UVC_STREAM_PTS | UVC_STREAM_SCR:
|
||||
@@ -519,6 +520,34 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
|
||||
if (dev_sof == stream->clock.last_sof)
|
||||
return;
|
||||
|
||||
dev_stc = get_unaligned_le32(&data[header_size - 6]);
|
||||
|
||||
/*
|
||||
* STC (Source Time Clock) is the clock used by the camera. The UVC 1.5
|
||||
* standard states that it "must be captured when the first video data
|
||||
* of a video frame is put on the USB bus". This is generally understood
|
||||
* as requiring devices to clear the payload header's SCR bit before
|
||||
* the first packet containing video data.
|
||||
*
|
||||
* Most vendors follow that interpretation, but some (namely SunplusIT
|
||||
* on some devices) always set the `UVC_STREAM_SCR` bit, fill the SCR
|
||||
* field with 0's,and expect that the driver only processes the SCR if
|
||||
* there is data in the packet.
|
||||
*
|
||||
* Ignore all the hardware timestamp information if we haven't received
|
||||
* any data for this frame yet, the packet contains no data, and both
|
||||
* STC and SOF are zero. This heuristics should be safe on compliant
|
||||
* devices. This should be safe with compliant devices, as in the very
|
||||
* unlikely case where a UVC 1.1 device would send timing information
|
||||
* only before the first packet containing data, and both STC and SOF
|
||||
* happen to be zero for a particular frame, we would only miss one
|
||||
* clock sample from many and the clock recovery algorithm wouldn't
|
||||
* suffer from this condition.
|
||||
*/
|
||||
if (buf && buf->bytesused == 0 && len == header_size &&
|
||||
dev_stc == 0 && dev_sof == 0)
|
||||
return;
|
||||
|
||||
stream->clock.last_sof = dev_sof;
|
||||
|
||||
host_sof = usb_get_current_frame_number(stream->dev->udev);
|
||||
@@ -556,7 +585,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
|
||||
spin_lock_irqsave(&stream->clock.lock, flags);
|
||||
|
||||
sample = &stream->clock.samples[stream->clock.head];
|
||||
sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
|
||||
sample->dev_stc = dev_stc;
|
||||
sample->dev_sof = dev_sof;
|
||||
sample->host_sof = host_sof;
|
||||
sample->host_time = time;
|
||||
@@ -701,11 +730,11 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
unsigned long flags;
|
||||
u64 timestamp;
|
||||
u32 delta_stc;
|
||||
u32 y1, y2;
|
||||
u32 y1;
|
||||
u32 x1, x2;
|
||||
u32 mean;
|
||||
u32 sof;
|
||||
u64 y;
|
||||
u64 y, y2;
|
||||
|
||||
if (!uvc_hw_timestamps_param)
|
||||
return;
|
||||
@@ -745,7 +774,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
sof = y;
|
||||
|
||||
uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
|
||||
"(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
|
||||
"(x1 %u x2 %u y1 %u y2 %llu SOF offset %u)\n",
|
||||
stream->dev->name, buf->pts,
|
||||
y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
|
||||
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
|
||||
@@ -760,7 +789,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
goto done;
|
||||
|
||||
y1 = NSEC_PER_SEC;
|
||||
y2 = (u32)ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1;
|
||||
y2 = ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1;
|
||||
|
||||
/* Interpolated and host SOF timestamps can wrap around at slightly
|
||||
* different times. Handle this by adding or removing 2048 to or from
|
||||
@@ -780,7 +809,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
timestamp = ktime_to_ns(first->host_time) + y - y1;
|
||||
|
||||
uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu "
|
||||
"buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
|
||||
"buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %llu)\n",
|
||||
stream->dev->name,
|
||||
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
|
||||
y, timestamp, vbuf->vb2_buf.timestamp,
|
||||
|
||||
@@ -345,6 +345,11 @@ struct uvc_entity {
|
||||
u8 bNrInPins;
|
||||
u8 *baSourceID;
|
||||
|
||||
int (*get_info)(struct uvc_device *dev, struct uvc_entity *entity,
|
||||
u8 cs, u8 *caps);
|
||||
int (*get_cur)(struct uvc_device *dev, struct uvc_entity *entity,
|
||||
u8 cs, void *data, u16 size);
|
||||
|
||||
unsigned int ncontrols;
|
||||
struct uvc_control *controls;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user