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:
Michael Bestas
2024-10-01 11:50:22 +03:00
308 changed files with 3037 additions and 1520 deletions

View File

@@ -61,8 +61,26 @@ stable kernels.
| ARM | Cortex-A73 | #858921 | ARM64_ERRATUM_858921 | | ARM | Cortex-A73 | #858921 | ARM64_ERRATUM_858921 |
| ARM | Cortex-A55 | #1024718 | ARM64_ERRATUM_1024718 | | ARM | Cortex-A55 | #1024718 | ARM64_ERRATUM_1024718 |
| ARM | Cortex-A76 | #1463225 | ARM64_ERRATUM_1463225 | | 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 | Cortex-A77 | #1542418 | ARM64_ERRATUM_1542418 |
| ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 | | 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 | | ARM | MMU-500 | #841119,#826419 | N/A |
| | | | | | | | | |
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 | | Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |

View File

@@ -299,17 +299,25 @@ functions is used.
The header file linux/hwmon-sysfs.h provides a number of useful macros to The header file linux/hwmon-sysfs.h provides a number of useful macros to
declare and use hardware monitoring sysfs attributes. declare and use hardware monitoring sysfs attributes.
In many cases, you can use the exsting define DEVICE_ATTR to declare such In many cases, you can use the exsting define DEVICE_ATTR or its variants
attributes. This is feasible if an attribute has no additional context. However, DEVICE_ATTR_{RW,RO,WO} to declare such attributes. This is feasible if an
in many cases there will be additional information such as a sensor index which attribute has no additional context. However, in many cases there will be
will need to be passed to the sysfs attribute handling function. 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 SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 can be used to define attributes
which need such additional context information. SENSOR_DEVICE_ATTR requires which need such additional context information. SENSOR_DEVICE_ATTR requires
one additional argument, SENSOR_DEVICE_ATTR_2 requires two. one additional argument, SENSOR_DEVICE_ATTR_2 requires two.
SENSOR_DEVICE_ATTR defines a struct sensor_device_attribute variable. Simplified variants of SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 are available
This structure has the following fields. 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 sensor_device_attribute {
struct device_attribute dev_attr; 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 read or write function. Its parameter is the device to which the
attribute is attached. attribute is attached.
SENSOR_DEVICE_ATTR_2 defines a struct sensor_device_attribute_2 variable, SENSOR_DEVICE_ATTR_2 and its variants define a struct sensor_device_attribute_2
which is defined as follows. variable, which is defined as follows.
struct sensor_device_attribute_2 { struct sensor_device_attribute_2 {
struct device_attribute dev_attr; struct device_attribute dev_attr;

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 4 VERSION = 4
PATCHLEVEL = 19 PATCHLEVEL = 19
SUBLEVEL = 318 SUBLEVEL = 321
EXTRAVERSION = EXTRAVERSION =
NAME = "People's Front" NAME = "People's Front"

View File

@@ -145,16 +145,6 @@ extern int __get_user_64t_1(void *);
extern int __get_user_64t_2(void *); extern int __get_user_64t_2(void *);
extern int __get_user_64t_4(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) \ #define __get_user_x(__r2, __p, __e, __l, __s) \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__asmeq("%0", "r0") __asmeq("%1", "r2") \ __asmeq("%0", "r0") __asmeq("%1", "r2") \
@@ -162,7 +152,7 @@ extern int __get_user_64t_4(void *);
"bl __get_user_" #__s \ "bl __get_user_" #__s \
: "=&r" (__e), "=r" (__r2) \ : "=&r" (__e), "=r" (__r2) \
: "0" (__p), "r" (__l) \ : "0" (__p), "r" (__l) \
: __GUP_CLOBBER_##__s) : "ip", "lr", "cc")
/* narrowing a double-word get into a single 32bit word register: */ /* narrowing a double-word get into a single 32bit word register: */
#ifdef __ARMEB__ #ifdef __ARMEB__
@@ -184,7 +174,7 @@ extern int __get_user_64t_4(void *);
"bl __get_user_64t_" #__s \ "bl __get_user_64t_" #__s \
: "=&r" (__e), "=r" (__r2) \ : "=&r" (__e), "=r" (__r2) \
: "0" (__p), "r" (__l) \ : "0" (__p), "r" (__l) \
: __GUP_CLOBBER_##__s) : "ip", "lr", "cc")
#else #else
#define __get_user_x_64t __get_user_x #define __get_user_x_64t __get_user_x
#endif #endif

View File

@@ -579,6 +579,44 @@ config ARM64_ERRATUM_1742098
If unsure, say Y. 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 config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313" bool "Cavium erratum 22375, 24313"
default y default y

View File

@@ -649,8 +649,8 @@
<0>, <24000000>, <0>, <24000000>,
<24000000>, <24000000>, <24000000>, <24000000>,
<15000000>, <15000000>, <15000000>, <15000000>,
<100000000>, <100000000>, <300000000>, <100000000>,
<100000000>, <100000000>, <400000000>, <100000000>,
<50000000>, <100000000>, <50000000>, <100000000>,
<100000000>, <100000000>, <100000000>, <100000000>,
<50000000>, <50000000>, <50000000>, <50000000>,

View File

@@ -147,6 +147,19 @@
hint #22 hint #22
.endm .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 * Sanitise a 64-bit bounded index wrt speculation, returning zero if out
* of bounds. * of bounds.

View File

@@ -34,6 +34,10 @@
#define psb_csync() asm volatile("hint #17" : : : "memory") #define psb_csync() asm volatile("hint #17" : : : "memory")
#define csdb() asm volatile("hint #20" : : : "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 mb() dsb(sy)
#define rmb() dsb(ld) #define rmb() dsb(ld)
#define wmb() dsb(st) #define wmb() dsb(st)

View File

@@ -58,6 +58,8 @@
#define ARM64_WORKAROUND_1542419 37 #define ARM64_WORKAROUND_1542419 37
#define ARM64_SPECTRE_BHB 38 #define ARM64_SPECTRE_BHB 38
#define ARM64_WORKAROUND_1742098 39 #define ARM64_WORKAROUND_1742098 39
#define ARM64_HAS_SB 40
#define ARM64_WORKAROUND_SPECULATIVE_SSBS 41
/* kabi: reserve 40 - 62 for future cpu capabilities */ /* kabi: reserve 40 - 62 for future cpu capabilities */
#define ARM64_NCAPS 62 #define ARM64_NCAPS 62

View File

@@ -101,6 +101,14 @@
#define ARM_CPU_PART_CORTEX_X2 0xD48 #define ARM_CPU_PART_CORTEX_X2 0xD48
#define ARM_CPU_PART_NEOVERSE_N2 0xD49 #define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B #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 #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_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_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_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 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_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) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)

View File

@@ -107,6 +107,11 @@
#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift)) #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 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_ISW sys_insn(1, 0, 7, 6, 2)
#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4) #define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6) #define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
@@ -538,6 +543,7 @@
#define ID_AA64ISAR0_AES_SHIFT 4 #define ID_AA64ISAR0_AES_SHIFT 4
/* id_aa64isar1 */ /* id_aa64isar1 */
#define ID_AA64ISAR1_SB_SHIFT 36
#define ID_AA64ISAR1_LRCPC_SHIFT 20 #define ID_AA64ISAR1_LRCPC_SHIFT 20
#define ID_AA64ISAR1_FCMA_SHIFT 16 #define ID_AA64ISAR1_FCMA_SHIFT 16
#define ID_AA64ISAR1_JSCVT_SHIFT 12 #define ID_AA64ISAR1_JSCVT_SHIFT 12

View File

@@ -46,8 +46,7 @@ static inline void set_fs(mm_segment_t fs)
* Prevent a mispredicted conditional call to set_fs from forwarding * Prevent a mispredicted conditional call to set_fs from forwarding
* the wrong address limit to access_ok under speculation. * the wrong address limit to access_ok under speculation.
*/ */
dsb(nsh); spec_bar();
isb();
/* On user-mode return, check fs is correct */ /* On user-mode return, check fs is correct */
set_thread_flag(TIF_FSCHECK); set_thread_flag(TIF_FSCHECK);

View File

@@ -49,5 +49,6 @@
#define HWCAP_ILRCPC (1 << 26) #define HWCAP_ILRCPC (1 << 26)
#define HWCAP_FLAGM (1 << 27) #define HWCAP_FLAGM (1 << 27)
#define HWCAP_SSBS (1 << 28) #define HWCAP_SSBS (1 << 28)
#define HWCAP_SB (1 << 29)
#endif /* _UAPI__ASM_HWCAP_H */ #endif /* _UAPI__ASM_HWCAP_H */

View File

@@ -28,7 +28,7 @@
#include <asm/numa.h> #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) int __init acpi_numa_get_nid(unsigned int cpu)
{ {

View File

@@ -345,6 +345,19 @@ void arm64_set_ssbd_mitigation(bool state)
asm volatile(SET_PSTATE_SSBS(0)); asm volatile(SET_PSTATE_SSBS(0));
else else
asm volatile(SET_PSTATE_SSBS(1)); 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; return;
} }
@@ -743,6 +756,30 @@ static struct midr_range broken_aarch32_aes[] = {
}; };
#endif #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[] = { const struct arm64_cpu_capabilities arm64_errata[] = {
#if defined(CONFIG_ARM64_ERRATUM_826319) || \ #if defined(CONFIG_ARM64_ERRATUM_826319) || \
defined(CONFIG_ARM64_ERRATUM_827319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -964,6 +1001,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
CAP_MIDR_RANGE_LIST(broken_aarch32_aes), CAP_MIDR_RANGE_LIST(broken_aarch32_aes),
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, .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 #endif
{ {
} }

View File

@@ -144,6 +144,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
}; };
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { 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_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_FCMA_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_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, 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[] = { 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, 4, 4, 0), /* FPMisc */
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* SIMDMisc */ 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[] = { 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_RDM_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE, 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_VISIBLE, 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_VISIBLE, 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_AES_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
ARM64_FTR_END, 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 * Common ftr bits for a 32bit register with all hidden, strict
* attributes, with 4bit feature fields and a default safe value of * attributes, with 4bit feature fields and a default safe value of
* 0. Covers the following 32bit registers: * 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[] = { static const struct arm64_ftr_bits ftr_generic_32bits[] = {
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0), 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), ARM64_FTR_REG(SYS_ID_MMFR4_EL1, ftr_id_mmfr4),
/* Op1 = 0, CRn = 0, CRm = 3 */ /* Op1 = 0, CRn = 0, CRm = 3 */
ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits), ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_mvfr0),
ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits), ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_mvfr1),
ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2), ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2),
/* Op1 = 0, CRn = 0, CRm = 4 */ /* 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; 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 static bool
has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope) has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
{ {
u64 val; u64 val = read_scoped_sysreg(entry, scope);
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);
return feature_matches(val, entry); return feature_matches(val, entry);
} }
@@ -1157,6 +1204,17 @@ static void cpu_enable_ssbs(const struct arm64_cpu_capabilities *__unused)
} }
#endif /* CONFIG_ARM64_SSBD */ #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) static void elf_hwcap_fixup(void)
{ {
#ifdef CONFIG_ARM64_ERRATUM_1742098 #ifdef CONFIG_ARM64_ERRATUM_1742098
@@ -1363,12 +1421,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.cpu_enable = cpu_enable_ssbs, .cpu_enable = cpu_enable_ssbs,
}, },
#endif #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) \ #define HWCAP_CPUID_MATCH(reg, field, s, min_value) \
.matches = has_cpuid_feature, \ .matches = has_user_cpuid_feature, \
.sys_reg = reg, \ .sys_reg = reg, \
.field_pos = field, \ .field_pos = field, \
.sign = s, \ .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_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, 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_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), HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_USCAT),
#ifdef CONFIG_ARM64_SVE #ifdef CONFIG_ARM64_SVE
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_SVE_SHIFT, FTR_UNSIGNED, ID_AA64PFR0_SVE, CAP_HWCAP, HWCAP_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(); setup_system_capabilities();
mark_const_caps_ready(); mark_const_caps_ready();
user_feature_fixup();
setup_elf_hwcaps(arm64_elf_hwcaps); setup_elf_hwcaps(arm64_elf_hwcaps);
if (system_supports_32bit_el0()) { 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. * 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, * See Table C5-6 System instruction encodings for System register accesses,
* ARMv8 ARM(ARM DDI 0487A.f) for more details. * 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_CRn(id) == 0x0 &&
sys_reg_Op1(id) == 0x0 && sys_reg_Op1(id) == 0x0 &&
(sys_reg_CRm(id) == 0 || (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))));
} }
/* /*

View File

@@ -89,6 +89,7 @@ static const char *const hwcap_str[] = {
"ilrcpc", "ilrcpc",
"flagm", "flagm",
"ssbs", "ssbs",
"sb",
NULL NULL
}; };

View File

@@ -181,6 +181,15 @@ int __init amiga_parse_bootinfo(const struct bi_record *record)
dev->slotsize = be16_to_cpu(cd->cd_SlotSize); dev->slotsize = be16_to_cpu(cd->cd_SlotSize);
dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr); dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
dev->boardsize = be32_to_cpu(cd->cd_BoardSize); 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 } else
pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n"); pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n");
#endif /* CONFIG_ZORRO */ #endif /* CONFIG_ZORRO */

View File

@@ -302,11 +302,7 @@ void __init atari_init_IRQ(void)
if (ATARIHW_PRESENT(SCU)) { if (ATARIHW_PRESENT(SCU)) {
/* init the SCU if present */ /* init the SCU if present */
tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and tt_scu.sys_mask = 0x0; /* disable all interrupts */
* disable HSYNC interrupts (who
* needs them?) MFP and SCC are
* enabled in VME mask
*/
tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */
} else { } else {
/* If no SCU and no Hades, the HSYNC interrupt needs to be /* If no SCU and no Hades, the HSYNC interrupt needs to be

View File

@@ -33,7 +33,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
x = tmp; x = tmp;
break; break;
default: default:
tmp = __invalid_xchg_size(x, ptr, size); x = __invalid_xchg_size(x, ptr, size);
break; break;
} }

View File

@@ -232,6 +232,10 @@ GCR_ACCESSOR_RO(32, 0x0d0, gic_status)
GCR_ACCESSOR_RO(32, 0x0f0, cpc_status) GCR_ACCESSOR_RO(32, 0x0f0, cpc_status)
#define CM_GCR_CPC_STATUS_EX BIT(0) #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_L2_CONFIG - Indicates L2 cache configuration when Config5.L2C=1 */
GCR_ACCESSOR_RW(32, 0x130, l2_config) GCR_ACCESSOR_RW(32, 0x130, l2_config)
#define CM_GCR_L2_CONFIG_BYPASS BIT(20) #define CM_GCR_L2_CONFIG_BYPASS BIT(20)

View File

@@ -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); write_gcr_co_reset_ext_base(CM_GCR_Cx_RESET_EXT_BASE_UEB);
/* Ensure the core can access the GCRs */ /* Ensure the core can access the GCRs */
set_gcr_access(1 << core); if (mips_cm_revision() < CM_REV_CM3)
set_gcr_access(1 << core);
else
set_gcr_access_cm3(1 << core);
if (mips_cpc_present()) { if (mips_cpc_present()) {
/* Reset the core */ /* Reset the core */

0
arch/mips/pci/pcie-octeon.c Executable file → Normal file
View File

View File

@@ -287,6 +287,9 @@ void calibrate_delay(void)
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
/* setup memblock allocator */
setup_memory();
unflatten_and_copy_device_tree(); unflatten_and_copy_device_tree();
setup_cpuinfo(); setup_cpuinfo();
@@ -311,9 +314,6 @@ void __init setup_arch(char **cmdline_p)
initrd_below_start_ok = 1; initrd_below_start_ok = 1;
#endif #endif
/* setup memblock allocator */
setup_memory();
/* paging_init() sets up the MMU and marks all pages as reserved */ /* paging_init() sets up the MMU and marks all pages as reserved */
paging_init(); paging_init();

View File

@@ -524,7 +524,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
old_regs = set_irq_regs(regs); old_regs = set_irq_regs(regs);
local_irq_disable(); local_irq_disable();
irq_enter(); irq_enter_rcu();
eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu); eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
if (!eirr_val) if (!eirr_val)
@@ -559,7 +559,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
#endif /* CONFIG_IRQSTACKS */ #endif /* CONFIG_IRQSTACKS */
out: out:
irq_exit(); irq_exit_rcu();
set_irq_regs(old_regs); set_irq_regs(old_regs);
return; return;

View File

@@ -114,8 +114,11 @@ static void *simple_realloc(void *ptr, unsigned long size)
return ptr; return ptr;
new = simple_malloc(size); new = simple_malloc(size);
memcpy(new, ptr, p->size); if (new) {
simple_free(ptr); memcpy(new, ptr, p->size);
simple_free(ptr);
}
return new; return new;
} }

View File

@@ -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", rname = kasprintf(GFP_KERNEL, "CPU %d [0x%x] Interrupt Presentation",
cpu, hw_id); cpu, hw_id);
if (!rname)
return -ENOMEM;
if (!request_mem_region(addr, size, rname)) { if (!request_mem_region(addr, size, rname)) {
pr_warn("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n", pr_warn("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n",
cpu, hw_id); cpu, hw_id);

View File

@@ -133,32 +133,21 @@ int print_insn_powerpc (unsigned long insn, unsigned long memaddr)
bool insn_is_short; bool insn_is_short;
ppc_cpu_t dialect; ppc_cpu_t dialect;
dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON;
| PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
if (cpu_has_feature(CPU_FTRS_POWER5)) if (IS_ENABLED(CONFIG_PPC64))
dialect |= PPC_OPCODE_POWER5; 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)) if (cpu_has_feature(CPU_FTR_TM))
dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC); dialect |= PPC_OPCODE_HTM;
if (cpu_has_feature(CPU_FTRS_POWER6)) if (cpu_has_feature(CPU_FTR_ALTIVEC))
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC); dialect |= PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2;
if (cpu_has_feature(CPU_FTRS_POWER7)) if (cpu_has_feature(CPU_FTR_VSX))
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 dialect |= PPC_OPCODE_VSX | PPC_OPCODE_VSX3;
| 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);
/* Get the major opcode of the insn. */ /* Get the major opcode of the insn. */
opcode = NULL; opcode = NULL;

View File

@@ -247,6 +247,7 @@ void prom_sun4v_guest_soft_state(void);
int prom_ihandle2path(int handle, char *buffer, int bufsize); int prom_ihandle2path(int handle, char *buffer, int bufsize);
/* Client interface level routines. */ /* Client interface level routines. */
void prom_cif_init(void *cif_handler);
void p1275_cmd_direct(unsigned long *); void p1275_cmd_direct(unsigned long *);
#endif /* !(__SPARC64_OPLIB_H) */ #endif /* !(__SPARC64_OPLIB_H) */

View File

@@ -26,9 +26,6 @@ phandle prom_chosen_node;
* routines in the prom library. * routines in the prom library.
* It gets passed the pointer to the PROM vector. * It gets passed the pointer to the PROM vector.
*/ */
extern void prom_cif_init(void *);
void __init prom_init(void *cif_handler) void __init prom_init(void *cif_handler)
{ {
phandle node; phandle node;

View File

@@ -49,7 +49,7 @@ void p1275_cmd_direct(unsigned long *args)
local_irq_restore(flags); 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; p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
} }

View File

@@ -75,7 +75,7 @@ static struct pt_cap_desc {
PT_CAP(psb_periods, 1, CPUID_EBX, 0xffff0000), 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]; struct pt_cap_desc *cd = &pt_caps[cap];
u32 c = pt_pmu.caps[cd->leaf * PT_CPUID_REGS_NUM + cd->reg]; 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; return (c & cd->mask) >> shift;
} }
EXPORT_SYMBOL_GPL(intel_pt_validate_hw_cap);
static ssize_t pt_cap_show(struct device *cdev, static ssize_t pt_cap_show(struct device *cdev,
struct device_attribute *attr, 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); container_of(attr, struct dev_ext_attribute, attr);
enum pt_capabilities cap = (long)ea->var; 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 = { static struct attribute_group pt_cap_group = {
@@ -310,16 +311,16 @@ static bool pt_event_valid(struct perf_event *event)
return false; return false;
if (config & RTIT_CTL_CYC_PSB) { 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; 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) >> requested = (config & RTIT_CTL_PSB_FREQ) >>
RTIT_CTL_PSB_FREQ_OFFSET; RTIT_CTL_PSB_FREQ_OFFSET;
if (requested && (!(allowed & BIT(requested)))) if (requested && (!(allowed & BIT(requested))))
return false; 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) >> requested = (config & RTIT_CTL_CYC_THRESH) >>
RTIT_CTL_CYC_THRESH_OFFSET; RTIT_CTL_CYC_THRESH_OFFSET;
if (requested && (!(allowed & BIT(requested)))) 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 * Spec says that setting mtc period bits while mtc bit in
* CPUID is 0 will #GP, so better safe than sorry. * 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; return false;
allowed = pt_cap_get(PT_CAP_mtc_periods); allowed = intel_pt_validate_hw_cap(PT_CAP_mtc_periods);
if (!allowed) if (!allowed)
return false; return false;
@@ -349,11 +350,11 @@ static bool pt_event_valid(struct perf_event *event)
} }
if (config & RTIT_CTL_PWR_EVT_EN && 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; return false;
if (config & RTIT_CTL_PTW) { if (config & RTIT_CTL_PTW) {
if (!pt_cap_get(PT_CAP_ptwrite)) if (!intel_pt_validate_hw_cap(PT_CAP_ptwrite))
return false; return false;
/* FUPonPTW without PTW doesn't make sense */ /* 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); 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 * struct topa - ToPA metadata
* @table: actual ToPA table entries, as understood by PT hardware
* @list: linkage to struct pt_buffer's list of tables * @list: linkage to struct pt_buffer's list of tables
* @phys: physical address of this page * @phys: physical address of this page
* @offset: offset of the first entry in this table in the buffer * @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 * @last: index of the last initialized entry in this table
*/ */
struct topa { struct topa {
struct topa_entry table[TENTS_PER_PAGE];
struct list_head list; struct list_head list;
u64 phys; u64 phys;
u64 offset; u64 offset;
@@ -570,8 +562,40 @@ struct topa {
int last; 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 */ /* 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 * topa_alloc() - allocate page-sized ToPA table
@@ -583,27 +607,27 @@ struct topa {
static struct topa *topa_alloc(int cpu, gfp_t gfp) static struct topa *topa_alloc(int cpu, gfp_t gfp)
{ {
int node = cpu_to_node(cpu); int node = cpu_to_node(cpu);
struct topa *topa; struct topa_page *tp;
struct page *p; struct page *p;
p = alloc_pages_node(node, gfp | __GFP_ZERO, 0); p = alloc_pages_node(node, gfp | __GFP_ZERO, 0);
if (!p) if (!p)
return NULL; return NULL;
topa = page_address(p); tp = page_address(p);
topa->last = 0; tp->topa.last = 0;
topa->phys = page_to_phys(p); tp->topa.phys = page_to_phys(p);
/* /*
* In case of singe-entry ToPA, always put the self-referencing END * In case of singe-entry ToPA, always put the self-referencing END
* link as the 2nd entry in the table * link as the 2nd entry in the table
*/ */
if (!pt_cap_get(PT_CAP_topa_multiple_entries)) { if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT; TOPA_ENTRY(&tp->topa, 1)->base = tp->topa.phys;
TOPA_ENTRY(topa, 1)->end = 1; 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; topa->offset = last->offset + last->size;
buf->last = topa; buf->last = topa;
if (!pt_cap_get(PT_CAP_topa_multiple_entries)) if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
return; return;
BUG_ON(last->last != TENTS_PER_PAGE - 1); 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) static bool topa_table_full(struct topa *topa)
{ {
/* single-entry ToPA is a special case */ /* 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;
return topa->last == TENTS_PER_PAGE - 1; 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)->base = page_to_phys(p) >> TOPA_SHIFT;
TOPA_ENTRY(topa, -1)->size = order; 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)->intr = 1;
TOPA_ENTRY(topa, -1)->stop = 1; TOPA_ENTRY(topa, -1)->stop = 1;
} }
@@ -712,22 +737,23 @@ static void pt_topa_dump(struct pt_buffer *buf)
struct topa *topa; struct topa *topa;
list_for_each_entry(topa, &buf->tables, list) { list_for_each_entry(topa, &buf->tables, list) {
struct topa_page *tp = topa_to_page(topa);
int i; 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); topa->phys, topa->offset, topa->size);
for (i = 0; i < TENTS_PER_PAGE; i++) { for (i = 0; i < TENTS_PER_PAGE; i++) {
pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n", pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n",
&topa->table[i], &tp->table[i],
(unsigned long)topa->table[i].base << TOPA_SHIFT, (unsigned long)tp->table[i].base << TOPA_SHIFT,
sizes(topa->table[i].size), sizes(tp->table[i].size),
topa->table[i].end ? 'E' : ' ', tp->table[i].end ? 'E' : ' ',
topa->table[i].intr ? 'I' : ' ', tp->table[i].intr ? 'I' : ' ',
topa->table[i].stop ? 'S' : ' ', tp->table[i].stop ? 'S' : ' ',
*(u64 *)&topa->table[i]); *(u64 *)&tp->table[i]);
if ((pt_cap_get(PT_CAP_topa_multiple_entries) && if ((intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) &&
topa->table[i].stop) || tp->table[i].stop) ||
topa->table[i].end) tp->table[i].end)
break; break;
} }
} }
@@ -770,7 +796,7 @@ static void pt_update_head(struct pt *pt)
/* offset of the current output region within this table */ /* offset of the current output region within this table */
for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++) 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) { if (buf->snapshot) {
local_set(&buf->data_size, base); 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) 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) 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 * means we are already losing data; need to let the decoder
* know. * know.
*/ */
if (!pt_cap_get(PT_CAP_topa_multiple_entries) || if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) ||
buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) { buf->output_off == pt_buffer_region_size(buf)) {
perf_aux_output_flag(&pt->handle, perf_aux_output_flag(&pt->handle,
PERF_AUX_FLAG_TRUNCATED); PERF_AUX_FLAG_TRUNCATED);
advance++; advance++;
@@ -840,7 +866,8 @@ static void pt_handle_status(struct pt *pt)
* Also on single-entry ToPA implementations, interrupt will come * Also on single-entry ToPA implementations, interrupt will come
* before the output reaches its output region's boundary. * 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) { pt_buffer_region_size(buf) - buf->output_off <= TOPA_PMI_MARGIN) {
void *head = pt_buffer_region(buf); 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) static void pt_read_offset(struct pt_buffer *buf)
{ {
u64 offset, base_topa; u64 offset, base_topa;
struct topa_page *tp;
rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa); 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); rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
/* offset within current output region */ /* offset within current output region */
@@ -923,15 +952,14 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
unsigned long idx, npages, wakeup; unsigned long idx, npages, wakeup;
/* can't stop in the middle of an output region */ /* can't stop in the middle of an output region */
if (buf->output_off + handle->size + 1 < if (buf->output_off + handle->size + 1 < pt_buffer_region_size(buf)) {
sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
return -EINVAL; return -EINVAL;
} }
/* single entry ToPA is handled by marking all regions STOP=1 INT=1 */ /* 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; return 0;
/* clear STOP and INT from current entry */ /* 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) static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
{ {
struct topa_page *cur_tp;
int pg; int pg;
if (buf->snapshot) 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 = (head >> PAGE_SHIFT) & (buf->nr_pages - 1);
pg = pt_topa_next_entry(buf, pg); pg = pt_topa_next_entry(buf, pg);
buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK); cur_tp = topa_entry_to_page(buf->topa_index[pg]);
buf->cur_idx = ((unsigned long)buf->topa_index[pg] - buf->cur = &cur_tp->topa;
(unsigned long)buf->cur) / sizeof(struct topa_entry); buf->cur_idx = buf->topa_index[pg] - TOPA_ENTRY(buf->cur, 0);
buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1); buf->output_off = head & (pt_buffer_region_size(buf) - 1);
local64_set(&buf->head, head); local64_set(&buf->head, head);
local_set(&buf->data_size, 0); 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); pt_buffer_setup_topa_index(buf);
/* link last table to the first one, unless we're double buffering */ /* 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)->base = buf->first->phys >> TOPA_SHIFT;
TOPA_ENTRY(buf->last, -1)->end = 1; 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; struct pt_filters *filters;
int node = event->cpu == -1 ? -1 : cpu_to_node(event->cpu); 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; return 0;
filters = kzalloc_node(sizeof(struct pt_filters), GFP_KERNEL, node); 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; 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; return -EOPNOTSUPP;
} }
@@ -1294,7 +1323,7 @@ void intel_pt_interrupt(void)
return; 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); buf->output_off);
pt_config(event); pt_config(event);
} }
@@ -1359,7 +1388,7 @@ static void pt_event_start(struct perf_event *event, int mode)
WRITE_ONCE(pt->handle_nmi, 1); WRITE_ONCE(pt->handle_nmi, 1);
hwc->state = 0; 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); buf->output_off);
pt_config(event); pt_config(event);
@@ -1509,12 +1538,12 @@ static __init int pt_init(void)
if (ret) if (ret)
return 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"); pr_warn("ToPA output is not supported on this CPU\n");
return -ENODEV; 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 = pt_pmu.pmu.capabilities =
PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF; 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_sync = pt_event_addr_filters_sync;
pt_pmu.pmu.addr_filters_validate = pt_event_addr_filters_validate; pt_pmu.pmu.addr_filters_validate = pt_event_addr_filters_validate;
pt_pmu.pmu.nr_addr_filters = 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); ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);

View File

@@ -78,34 +78,13 @@ struct topa_entry {
u64 rsvd2 : 1; u64 rsvd2 : 1;
u64 size : 4; u64 size : 4;
u64 rsvd3 : 2; u64 rsvd3 : 2;
u64 base : 36; u64 base : 40;
u64 rsvd4 : 16; 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 */ /* TSC to Core Crystal Clock Ratio */
#define CPUID_TSC_LEAF 0x15 #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 pt_pmu {
struct pmu pmu; struct pmu pmu;
u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES]; u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];

View File

@@ -2,10 +2,33 @@
#ifndef _ASM_X86_INTEL_PT_H #ifndef _ASM_X86_INTEL_PT_H
#define _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) #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
void cpu_emergency_stop_pt(void); void cpu_emergency_stop_pt(void);
extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap);
#else #else
static inline void cpu_emergency_stop_pt(void) {} static inline void cpu_emergency_stop_pt(void) {}
static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; }
#endif #endif
#endif /* _ASM_X86_INTEL_PT_H */ #endif /* _ASM_X86_INTEL_PT_H */

View File

@@ -819,7 +819,7 @@ void mtrr_save_state(void)
{ {
int first_cpu; int first_cpu;
if (!mtrr_enabled()) if (!mtrr_enabled() || !mtrr_state.have_fixed)
return; return;
first_cpu = cpumask_first(cpu_online_mask); first_cpu = cpumask_first(cpu_online_mask);

View File

@@ -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); ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (ret) if (ret)
return ret; return pcibios_err_to_errno(ret);
if (!pin) if (!pin)
return 0; return 0;

View File

@@ -383,14 +383,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
*/ */
*target_pmd = *pmd; *target_pmd = *pmd;
addr += PMD_SIZE; addr = round_up(addr + 1, PMD_SIZE);
} else if (level == PTI_CLONE_PTE) { } else if (level == PTI_CLONE_PTE) {
/* Walk the page-table down to the pte level */ /* Walk the page-table down to the pte level */
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if (pte_none(*pte)) { if (pte_none(*pte)) {
addr += PAGE_SIZE; addr = round_up(addr + 1, PAGE_SIZE);
continue; continue;
} }
@@ -410,7 +410,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
/* Clone the PTE */ /* Clone the PTE */
*target_pte = *pte; *target_pte = *pte;
addr += PAGE_SIZE; addr = round_up(addr + 1, PAGE_SIZE);
} else { } else {
BUG(); BUG();

View File

@@ -223,9 +223,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
return 0; return 0;
ret = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); 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); 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()) { switch (intel_mid_identify_cpu()) {

View File

@@ -36,10 +36,10 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
u8 gsi; u8 gsi;
rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &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", dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
rc); rc);
return rc; return pcibios_err_to_errno(rc);
} }
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/ /* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
pirq = gsi; pirq = gsi;

View File

@@ -68,7 +68,7 @@ static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr)
fail_read: fail_read:
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result); 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) 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: fail_write:
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result); 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) int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)

View File

@@ -733,7 +733,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
* immediate unmapping. * immediate unmapping.
*/ */
map_ops[i].status = GNTST_general_error; 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; unmap[0].handle = map_ops[i].handle;
map_ops[i].handle = ~0; map_ops[i].handle = ~0;
if (map_ops[i].flags & GNTMAP_device_map) 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) { if (kmap_ops) {
kmap_ops[i].status = GNTST_general_error; 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; unmap[1].handle = kmap_ops[i].handle;
kmap_ops[i].handle = ~0; kmap_ops[i].handle = ~0;
if (kmap_ops[i].flags & GNTMAP_device_map) if (kmap_ops[i].flags & GNTMAP_device_map)

View File

@@ -1330,10 +1330,13 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
if (ec->busy_polling || bits > 8) if (ec->busy_polling || bits > 8)
acpi_ec_burst_enable(ec); 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) ? result = (function == ACPI_READ) ?
acpi_ec_read(ec, address, value) : acpi_ec_read(ec, address, value) :
acpi_ec_write(ec, address, *value); acpi_ec_write(ec, address, *value);
if (result < 0)
break;
}
if (ec->busy_polling || bits > 8) if (ec->busy_polling || bits > 8)
acpi_ec_burst_disable(ec); acpi_ec_burst_disable(ec);
@@ -1345,8 +1348,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
return AE_NOT_FOUND; return AE_NOT_FOUND;
case -ETIME: case -ETIME:
return AE_TIME; return AE_TIME;
default: case 0:
return AE_OK; return AE_OK;
default:
return AE_ERROR;
} }
} }

View File

@@ -29,7 +29,6 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/sched.h> /* need_resched() */ #include <linux/sched.h> /* need_resched() */
#include <linux/sort.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/cpu.h> #include <linux/cpu.h>
@@ -545,28 +544,24 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
return; 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)) for (i = 1; i < length; i++) {
return 0; if (!states[i].valid)
if (x->latency > y->latency) continue;
return 1;
if (x->latency < y->latency)
return -1;
return 0;
}
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)) for (j = i - 1, k = i; j >= 0; j--) {
return; if (!states[j].valid)
tmp = x->latency; continue;
x->latency = y->latency;
y->latency = tmp; if (states[j].latency > states[k].latency)
swap(states[j].latency, states[k].latency);
k = j;
}
}
} }
static int acpi_processor_power_verify(struct acpi_processor *pr) 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) { if (buggy_latency) {
pr_notice("FW issue: working around C-state latencies out of order\n"); pr_notice("FW issue: working around C-state latencies out of order\n");
sort(&pr->power.states[1], max_cstate, acpi_cst_latency_sort(&pr->power.states[1], max_cstate);
sizeof(struct acpi_processor_cx),
acpi_cst_latency_cmp,
acpi_cst_latency_swap);
} }
lapic_timer_propagate_broadcast(pr); lapic_timer_propagate_broadcast(pr);

View File

@@ -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) static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread)
{ {
return !thread->transaction_stack && return !thread->transaction_stack &&
binder_worklist_empty_ilocked(&thread->todo) && binder_worklist_empty_ilocked(&thread->todo);
(thread->looper & (BINDER_LOOPER_STATE_ENTERED |
BINDER_LOOPER_STATE_REGISTERED));
} }
static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc, static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc,

View File

@@ -6159,6 +6159,9 @@ static void ata_host_release(struct kref *kref)
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i]; struct ata_port *ap = host->ports[i];
if (!ap)
continue;
kfree(ap->pmp_link); kfree(ap->pmp_link);
kfree(ap->slave_link); kfree(ap->slave_link);
kfree(ap); kfree(ap);

View File

@@ -1117,8 +1117,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
rpp->len += skb->len; rpp->len += skb->len;
if (stat & SAR_RSQE_EPDU) { if (stat & SAR_RSQE_EPDU) {
unsigned int len, truesize;
unsigned char *l1l2; unsigned char *l1l2;
unsigned int len;
l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6); 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; ATM_SKB(skb)->vcc = vcc;
__net_timestamp(skb); __net_timestamp(skb);
truesize = skb->truesize;
vcc->push(vcc, skb); vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx); 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); 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); 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); add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
else else
add_rx_skb(card, 0, SAR_FB_SIZE_0, 1); add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);

View File

@@ -24,6 +24,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/sysfs.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 kobj_uevent_env *env)
{ {
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
struct device_driver *driver;
int retval = 0; int retval = 0;
/* add device node properties if present */ /* 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) if (dev->type && dev->type->name)
add_uevent_var(env, "DEVTYPE=%s", dev->type->name); add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
if (dev->driver) /* Synchronize with module_remove_driver() */
add_uevent_var(env, "DRIVER=%s", dev->driver->name); 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 */ /* Add common DT information about the device */
of_device_uevent(dev, env); of_device_uevent(dev, env);
@@ -1684,11 +1690,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
if (!env) if (!env)
return -ENOMEM; return -ENOMEM;
/* Synchronize with really_probe() */
device_lock(dev);
/* let the kset specific function add its keys */ /* let the kset specific function add its keys */
retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
device_unlock(dev);
if (retval) if (retval)
goto out; goto out;

View File

@@ -1057,7 +1057,11 @@ EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
*/ */
void devm_free_percpu(struct device *dev, void __percpu *pdata) 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); EXPORT_SYMBOL_GPL(devm_free_percpu);

View File

@@ -7,6 +7,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/rcupdate.h>
#include "base.h" #include "base.h"
static char *make_driver_name(struct device_driver *drv) static char *make_driver_name(struct device_driver *drv)
@@ -77,6 +78,9 @@ void module_remove_driver(struct device_driver *drv)
if (!drv) if (!drv)
return; return;
/* Synchronize with dev_uevent() */
synchronize_rcu();
sysfs_remove_link(&drv->p->kobj, "module"); sysfs_remove_link(&drv->p->kobj, "module");
if (drv->owner) if (drv->owner)

View File

@@ -773,7 +773,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
break; break;
case HCIUARTGETPROTO: 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; err = hu->proto->id;
else else
err = -EUNATCH; err = -EUNATCH;

View File

@@ -142,8 +142,10 @@ static int __init mod_init(void)
found: found:
err = pci_read_config_dword(pdev, 0x58, &pmbase); err = pci_read_config_dword(pdev, 0x58, &pmbase);
if (err) if (err) {
err = pcibios_err_to_errno(err);
goto put_dev; goto put_dev;
}
pmbase &= 0x0000FF00; pmbase &= 0x0000FF00;
if (pmbase == 0) { if (pmbase == 0) {

View File

@@ -52,6 +52,8 @@ static int tpm_bios_measurements_open(struct inode *inode,
if (!err) { if (!err) {
seq = file->private_data; seq = file->private_data;
seq->private = chip; seq->private = chip;
} else {
put_device(&chip->dev);
} }
return err; return err;

View File

@@ -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) static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
{ {
struct sh_cmt_channel *ch = dev_id; struct sh_cmt_channel *ch = dev_id;
unsigned long flags;
/* clear flags */ /* clear flags */
sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & 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; ch->flags &= ~FLAG_SKIPEVENT;
raw_spin_lock_irqsave(&ch->lock, flags);
if (ch->flags & FLAG_REPROGRAM) { if (ch->flags & FLAG_REPROGRAM) {
ch->flags &= ~FLAG_REPROGRAM; ch->flags &= ~FLAG_REPROGRAM;
sh_cmt_clock_event_program_verify(ch, 1); 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; ch->flags &= ~FLAG_IRQCONTEXT;
raw_spin_unlock_irqrestore(&ch->lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -758,12 +763,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
struct clock_event_device *ced) struct clock_event_device *ced)
{ {
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
unsigned long flags;
BUG_ON(!clockevent_state_oneshot(ced)); BUG_ON(!clockevent_state_oneshot(ced));
raw_spin_lock_irqsave(&ch->lock, flags);
if (likely(ch->flags & FLAG_IRQCONTEXT)) if (likely(ch->flags & FLAG_IRQCONTEXT))
ch->next_match_value = delta - 1; ch->next_match_value = delta - 1;
else else
sh_cmt_set_next(ch, delta - 1); __sh_cmt_set_next(ch, delta - 1);
raw_spin_unlock_irqrestore(&ch->lock, flags);
return 0; return 0;
} }

View File

@@ -288,16 +288,24 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
switch (args->in.op) { switch (args->in.op) {
case AMDGPU_CTX_OP_ALLOC_CTX: case AMDGPU_CTX_OP_ALLOC_CTX:
if (args->in.flags)
return -EINVAL;
r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id); r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
args->out.alloc.ctx_id = id; args->out.alloc.ctx_id = id;
break; break;
case AMDGPU_CTX_OP_FREE_CTX: case AMDGPU_CTX_OP_FREE_CTX:
if (args->in.flags)
return -EINVAL;
r = amdgpu_ctx_free(fpriv, id); r = amdgpu_ctx_free(fpriv, id);
break; break;
case AMDGPU_CTX_OP_QUERY_STATE: case AMDGPU_CTX_OP_QUERY_STATE:
if (args->in.flags)
return -EINVAL;
r = amdgpu_ctx_query(adev, fpriv, id, &args->out); r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
break; break;
case AMDGPU_CTX_OP_QUERY_STATE2: case AMDGPU_CTX_OP_QUERY_STATE2:
if (args->in.flags)
return -EINVAL;
r = amdgpu_ctx_query2(adev, fpriv, id, &args->out); r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
break; break;
default: default:

View File

@@ -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 created = 0;
uint32_t allocated = 0; uint32_t allocated = 0;
uint32_t tmp, handle = 0; uint32_t tmp, handle = 0;
uint32_t *size = &tmp; uint32_t dummy = 0xffffffff;
uint32_t *size = &dummy;
unsigned idx; unsigned idx;
int i, r = 0; int i, r = 0;

View File

@@ -1109,7 +1109,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
u32 status_reg; u32 status_reg;
u8 *buffer = msg->buffer; u8 *buffer = msg->buffer;
unsigned int i; unsigned int i;
int num_transferred = 0;
int ret; int ret;
/* Buffer size of AUX CH is 16 bytes */ /* 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]; reg = buffer[i];
writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
4 * i); 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 + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
4 * i); 4 * i);
buffer[i] = (unsigned char)reg; 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->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
msg->reply = DP_AUX_NATIVE_REPLY_ACK; msg->reply = DP_AUX_NATIVE_REPLY_ACK;
return num_transferred > 0 ? num_transferred : -EBUSY; return msg->size;
aux_error: aux_error:
/* if aux err happen, reset aux */ /* if aux err happen, reset aux */

View File

@@ -1713,6 +1713,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
return -EINVAL; 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 * 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 * fields values to zero in some cases. We treat this situation as a

View File

@@ -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) 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; return DMA_FROM_DEVICE;
else if (op & ETNA_PREP_WRITE) else if (op == ETNA_PREP_WRITE)
return DMA_TO_DEVICE; return DMA_TO_DEVICE;
else else
return DMA_BIDIRECTIONAL; return DMA_BIDIRECTIONAL;

View File

@@ -404,6 +404,9 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
if (mode_dev->panel_fixed_mode != NULL) { if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode = struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
if (!mode)
return 0;
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
return 1; return 1;
} }

View File

@@ -519,6 +519,9 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
if (mode_dev->panel_fixed_mode != NULL) { if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode = struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
if (!mode)
return 0;
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
return 1; return 1;
} }

View File

@@ -2009,6 +2009,39 @@ compute_partial_view(struct drm_i915_gem_object *obj,
return view; 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 * i915_gem_fault - fault a page into the GTT
* @vmf: fault info * @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 drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_ggtt *ggtt = &dev_priv->ggtt;
bool write = !!(vmf->flags & FAULT_FLAG_WRITE); bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
unsigned long start, end; /* memory boundaries */
struct i915_vma *vma; struct i915_vma *vma;
pgoff_t page_offset; pgoff_t page_offset;
unsigned long pfn;
int ret; int ret;
/* Sanity check that we allow writing into this object */ /* 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) if (ret)
goto err_unpin; 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 */ /* Finally, remap it using the new GTT offset */
ret = remap_io_mapping(area, ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap);
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);
if (ret) if (ret)
goto err_fence; goto err_fence;

View File

@@ -133,7 +133,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
i2c->adapter.algo_data = &i2c->bit; i2c->adapter.algo_data = &i2c->bit;
i2c->bit.udelay = 10; i2c->bit.udelay = 10;
i2c->bit.timeout = 2; i2c->bit.timeout = usecs_to_jiffies(2200);
i2c->bit.data = i2c; i2c->bit.data = i2c;
i2c->bit.setsda = mga_gpio_setsda; i2c->bit.setsda = mga_gpio_setsda;
i2c->bit.setscl = mga_gpio_setscl; i2c->bit.setscl = mga_gpio_setscl;

View File

@@ -41,24 +41,14 @@
* @fmt: Pointer to format string * @fmt: Pointer to format string
*/ */
#define DPU_DEBUG(fmt, ...) \ #define DPU_DEBUG(fmt, ...) \
do { \ DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
if (unlikely(drm_debug & DRM_UT_KMS)) \
DRM_DEBUG(fmt, ##__VA_ARGS__); \
else \
pr_debug(fmt, ##__VA_ARGS__); \
} while (0)
/** /**
* DPU_DEBUG_DRIVER - macro for hardware driver logging * DPU_DEBUG_DRIVER - macro for hardware driver logging
* @fmt: Pointer to format string * @fmt: Pointer to format string
*/ */
#define DPU_DEBUG_DRIVER(fmt, ...) \ #define DPU_DEBUG_DRIVER(fmt, ...) \
do { \ DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
DRM_ERROR(fmt, ##__VA_ARGS__); \
else \
pr_debug(fmt, ##__VA_ARGS__); \
} while (0)
#define DPU_ERROR(fmt, ...) pr_err("[dpu error]" 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__) #define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)

View File

@@ -100,7 +100,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv,
{ {
struct vmw_escape_video_flush *flush; struct vmw_escape_video_flush *flush;
size_t fifo_size; 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; int i, num_items;
SVGAGuestPtr ptr; SVGAGuestPtr ptr;

View File

@@ -1830,12 +1830,14 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
int fmax = field->logical_maximum; int fmax = field->logical_maximum;
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
int resolution_code = code; int resolution_code = code;
int resolution = hidinput_calc_abs_res(field, resolution_code); int resolution;
if (equivalent_usage == HID_DG_TWIST) { if (equivalent_usage == HID_DG_TWIST) {
resolution_code = ABS_RZ; resolution_code = ABS_RZ;
} }
resolution = hidinput_calc_abs_res(field, resolution_code);
if (equivalent_usage == HID_GD_X) { if (equivalent_usage == HID_GD_X) {
fmin += features->offset_left; fmin += features->offset_left;
fmax -= features->offset_right; fmax -= features->offset_right;

View File

@@ -1785,7 +1785,7 @@ static void adt7475_read_pwm(struct i2c_client *client, int index)
data->pwm[CONTROL][index] &= ~0xE0; data->pwm[CONTROL][index] &= ~0xE0;
data->pwm[CONTROL][index] |= (7 << 5); 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]); data->pwm[INPUT][index]);
i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),

View File

@@ -251,7 +251,7 @@ static struct max6697_data *max6697_update_device(struct device *dev)
return ret; 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) struct device_attribute *devattr, char *buf)
{ {
int index = to_sensor_dev_attr(devattr)->index; 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); return sprintf(buf, "%d\n", temp * 125);
} }
static ssize_t show_temp(struct device *dev, static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
struct device_attribute *devattr, char *buf) char *buf)
{ {
int nr = to_sensor_dev_attr_2(devattr)->nr; int nr = to_sensor_dev_attr_2(devattr)->nr;
int index = to_sensor_dev_attr_2(devattr)->index; 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); 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) char *buf)
{ {
int index = to_sensor_dev_attr(attr)->index; 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); return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1);
} }
static ssize_t set_temp(struct device *dev, static ssize_t temp_store(struct device *dev,
struct device_attribute *devattr, struct device_attribute *devattr, const char *buf,
const char *buf, size_t count) size_t count)
{ {
int nr = to_sensor_dev_attr_2(devattr)->nr; int nr = to_sensor_dev_attr_2(devattr)->nr;
int index = to_sensor_dev_attr_2(devattr)->index; int index = to_sensor_dev_attr_2(devattr)->index;
@@ -314,6 +314,7 @@ static ssize_t set_temp(struct device *dev,
return ret; return ret;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
temp = clamp_val(temp, -1000000, 1000000); /* prevent underflow */
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset; temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127); temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
data->temp[nr][index] = temp; data->temp[nr][index] = temp;
@@ -326,79 +327,63 @@ static ssize_t set_temp(struct device *dev,
return ret < 0 ? ret : count; return ret < 0 ? ret : count;
} }
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, 0, MAX6697_TEMP_MAX);
0, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, 0, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
0, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp, 1, MAX6697_TEMP_MAX);
1, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp2_crit, temp, 1, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
1, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); static SENSOR_DEVICE_ATTR_RO(temp3_input, temp_input, 2);
static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp3_max, temp, 2, MAX6697_TEMP_MAX);
2, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp3_crit, temp, 2, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
2, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); static SENSOR_DEVICE_ATTR_RO(temp4_input, temp_input, 3);
static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp4_max, temp, 3, MAX6697_TEMP_MAX);
3, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp4_crit, temp, 3, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
3, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); static SENSOR_DEVICE_ATTR_RO(temp5_input, temp_input, 4);
static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp5_max, temp, 4, MAX6697_TEMP_MAX);
4, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp5_crit, temp, 4, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
4, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); static SENSOR_DEVICE_ATTR_RO(temp6_input, temp_input, 5);
static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp6_max, temp, 5, MAX6697_TEMP_MAX);
5, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp6_crit, temp, 5, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
5, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_input, NULL, 6); static SENSOR_DEVICE_ATTR_RO(temp7_input, temp_input, 6);
static SENSOR_DEVICE_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp7_max, temp, 6, MAX6697_TEMP_MAX);
6, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp7_crit, temp, 6, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
6, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_input, NULL, 7); static SENSOR_DEVICE_ATTR_RO(temp8_input, temp_input, 7);
static SENSOR_DEVICE_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2_RW(temp8_max, temp, 7, MAX6697_TEMP_MAX);
7, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp8_crit, temp, 7, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
7, MAX6697_TEMP_CRIT);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 22); static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 22);
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 16); static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 16);
static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 17); static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 17);
static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 18); static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, alarm, 18);
static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 19); static SENSOR_DEVICE_ATTR_RO(temp5_max_alarm, alarm, 19);
static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, show_alarm, NULL, 20); static SENSOR_DEVICE_ATTR_RO(temp6_max_alarm, alarm, 20);
static SENSOR_DEVICE_ATTR(temp7_max_alarm, S_IRUGO, show_alarm, NULL, 21); static SENSOR_DEVICE_ATTR_RO(temp7_max_alarm, alarm, 21);
static SENSOR_DEVICE_ATTR(temp8_max_alarm, S_IRUGO, show_alarm, NULL, 23); 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_RO(temp1_crit_alarm, alarm, 15);
static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8);
static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 9);
static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 10); static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 10);
static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_alarm, NULL, 11); static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, alarm, 11);
static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, show_alarm, NULL, 12); static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, alarm, 12);
static SENSOR_DEVICE_ATTR(temp7_crit_alarm, S_IRUGO, show_alarm, NULL, 13); static SENSOR_DEVICE_ATTR_RO(temp7_crit_alarm, alarm, 13);
static SENSOR_DEVICE_ATTR(temp8_crit_alarm, S_IRUGO, show_alarm, NULL, 15); 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_RO(temp2_fault, alarm, 1);
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2);
static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 3); static SENSOR_DEVICE_ATTR_RO(temp4_fault, alarm, 3);
static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL, 4); static SENSOR_DEVICE_ATTR_RO(temp5_fault, alarm, 4);
static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5); static SENSOR_DEVICE_ATTR_RO(temp6_fault, alarm, 5);
static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6); static SENSOR_DEVICE_ATTR_RO(temp7_fault, alarm, 6);
static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7); static SENSOR_DEVICE_ATTR_RO(temp8_fault, alarm, 7);
static DEVICE_ATTR(dummy, 0, NULL, NULL); static DEVICE_ATTR(dummy, 0, NULL, NULL);

View File

@@ -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). * frequency with only 62 clock ticks max (31 high, 31 low).
* Aim for a duty of 60% LOW, 40% HIGH. * 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++) { for (cks = 0; cks < 7; cks++) {
/* /*

View File

@@ -42,6 +42,7 @@ static int smbus_do_alert(struct device *dev, void *addrp)
struct i2c_client *client = i2c_verify_client(dev); struct i2c_client *client = i2c_verify_client(dev);
struct alert_data *data = addrp; struct alert_data *data = addrp;
struct i2c_driver *driver; struct i2c_driver *driver;
int ret;
if (!client || client->addr != data->addr) if (!client || client->addr != data->addr)
return 0; return 0;
@@ -55,16 +56,47 @@ static int smbus_do_alert(struct device *dev, void *addrp)
device_lock(dev); device_lock(dev);
if (client->dev.driver) { if (client->dev.driver) {
driver = to_i2c_driver(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); driver->alert(client, data->type, data->data);
else ret = -EBUSY;
} else {
dev_warn(&client->dev, "no driver alert()!\n"); dev_warn(&client->dev, "no driver alert()!\n");
} else ret = -EOPNOTSUPP;
}
} else {
dev_dbg(&client->dev, "alert with no driver\n"); dev_dbg(&client->dev, "alert with no driver\n");
ret = -ENODEV;
}
device_unlock(dev); device_unlock(dev);
/* Stop iterating after we find the device */ return ret;
return -EBUSY; }
/* 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_smbus_alert *alert = d;
struct i2c_client *ara; 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; ara = alert->ara;
@@ -99,17 +131,28 @@ static irqreturn_t smbus_alert(int irq, void *d)
data.addr = status >> 1; data.addr = status >> 1;
data.type = I2C_PROTOCOL_SMBUS_ALERT; 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", dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n",
data.addr, data.data); data.addr, data.data);
/* Notify driver for the device which issued the alert */ /* 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); 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; prev_addr = data.addr;
} }

View File

@@ -369,8 +369,10 @@ EXPORT_SYMBOL(iw_cm_disconnect);
* *
* Clean up all resources associated with the connection and release * Clean up all resources associated with the connection and release
* the initial reference taken by iw_create_cm_id. * 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; struct iwcm_id_private *cm_id_priv;
unsigned long flags; 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); 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) 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); 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)) { if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
ret = process_event(cm_id_priv, &levent); ret = process_event(cm_id_priv, &levent);
if (ret) if (ret)
destroy_cm_id(&cm_id_priv->id); WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
} else } else
pr_debug("dropping event %d\n", levent.event); pr_debug("dropping event %d\n", levent.event);
if (iwcm_deref_id(cm_id_priv)) if (iwcm_deref_id(cm_id_priv))

View File

@@ -2112,7 +2112,7 @@ static int bnxt_re_build_send_wqe(struct bnxt_re_qp *qp,
break; break;
case IB_WR_SEND_WITH_IMM: case IB_WR_SEND_WITH_IMM:
wqe->type = BNXT_QPLIB_SWQE_TYPE_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; break;
case IB_WR_SEND_WITH_INV: case IB_WR_SEND_WITH_INV:
wqe->type = BNXT_QPLIB_SWQE_TYPE_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; break;
case IB_WR_RDMA_WRITE_WITH_IMM: case IB_WR_RDMA_WRITE_WITH_IMM:
wqe->type = BNXT_QPLIB_SWQE_TYPE_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; break;
case IB_WR_RDMA_READ: case IB_WR_RDMA_READ:
wqe->type = BNXT_QPLIB_SWQE_TYPE_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->byte_len = orig_cqe->length;
wc->qp = &qp1_qp->ib_qp; 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; wc->src_qp = orig_cqe->src_qp;
memcpy(wc->smac, orig_cqe->smac, ETH_ALEN); memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) { 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; continue;
} }
wc->qp = &qp->ib_qp; 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; wc->src_qp = cqe->src_qp;
memcpy(wc->smac, cqe->smac, ETH_ALEN); memcpy(wc->smac, cqe->smac, ETH_ALEN);
wc->port_num = 1; wc->port_num = 1;

View File

@@ -145,7 +145,7 @@ struct bnxt_qplib_swqe {
/* Send, with imm, inval key */ /* Send, with imm, inval key */
struct { struct {
union { union {
__be32 imm_data; u32 imm_data;
u32 inv_key; u32 inv_key;
}; };
u32 q_key; u32 q_key;
@@ -163,7 +163,7 @@ struct bnxt_qplib_swqe {
/* RDMA write, with imm, read */ /* RDMA write, with imm, read */
struct { struct {
union { union {
__be32 imm_data; u32 imm_data;
u32 inv_key; u32 inv_key;
}; };
u64 remote_va; u64 remote_va;
@@ -349,7 +349,7 @@ struct bnxt_qplib_cqe {
u32 length; u32 length;
u64 wr_id; u64 wr_id;
union { union {
__be32 immdata; __le32 immdata;
u32 invrkey; u32 invrkey;
}; };
u64 qp_handle; u64 qp_handle;

View File

@@ -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) 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 ret = 0;
int i, j; int i, j;
union ib_gid gid; union ib_gid gid;

View File

@@ -2158,7 +2158,7 @@ static int mlx4_ib_alloc_demux_ctx(struct mlx4_ib_dev *dev,
struct mlx4_ib_demux_ctx *ctx, struct mlx4_ib_demux_ctx *ctx,
int port) int port)
{ {
char name[12]; char name[21];
int ret = 0; int ret = 0;
int i; int i;

View File

@@ -390,7 +390,7 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp,
int solicited; int solicited;
u16 pkey; u16 pkey;
u32 qp_num; u32 qp_num;
int ack_req; int ack_req = 0;
/* length from start of bth to end of icrc */ /* length from start of bth to end of icrc */
paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE; paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
@@ -426,8 +426,9 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp,
qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn : qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn :
qp->attr.dest_qp_num; qp->attr.dest_qp_num;
ack_req = ((pkt->mask & RXE_END_MASK) || if (qp_type(qp) != IB_QPT_UD && qp_type(qp) != IB_QPT_UC)
(qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK)); ack_req = ((pkt->mask & RXE_END_MASK) ||
(qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK));
if (ack_req) if (ack_req)
qp->req.noack_pkts = 0; qp->req.noack_pkts = 0;

View File

@@ -48,6 +48,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
return 0; return 0;
if (mt) if (mt)
return mt->num_slots != num_slots ? -EINVAL : 0; 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); mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
if (!mt) if (!mt)

View File

@@ -1270,6 +1270,8 @@ static int __maybe_unused elan_suspend(struct device *dev)
} }
err: err:
if (ret)
enable_irq(client->irq);
mutex_unlock(&data->sysfs_mutex); mutex_unlock(&data->sysfs_mutex);
return ret; return ret;
} }

View File

@@ -1527,16 +1527,47 @@ static void elantech_disconnect(struct psmouse *psmouse)
psmouse->private = NULL; 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 * Put the touchpad back into absolute mode when reconnecting
*/ */
static int elantech_reconnect(struct psmouse *psmouse) static int elantech_reconnect(struct psmouse *psmouse)
{ {
int err;
psmouse_reset(psmouse); psmouse_reset(psmouse);
if (elantech_detect(psmouse, 0)) if (elantech_detect(psmouse, 0))
return -1; 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)) { if (elantech_set_absolute_mode(psmouse)) {
psmouse_err(psmouse, psmouse_err(psmouse,
"failed to put touchpad back into absolute mode.\n"); "failed to put touchpad back into absolute mode.\n");

View File

@@ -78,7 +78,6 @@ struct silead_ts_data {
struct regulator_bulk_data regulators[2]; struct regulator_bulk_data regulators[2];
char fw_name[64]; char fw_name[64];
struct touchscreen_properties prop; struct touchscreen_properties prop;
u32 max_fingers;
u32 chip_id; u32 chip_id;
struct input_mt_pos pos[SILEAD_MAX_FINGERS]; struct input_mt_pos pos[SILEAD_MAX_FINGERS];
int slots[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); input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
touchscreen_parse_properties(data->input, true, &data->prop); 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_DIRECT | INPUT_MT_DROP_UNUSED |
INPUT_MT_TRACK); INPUT_MT_TRACK);
@@ -153,10 +152,10 @@ static void silead_ts_read_data(struct i2c_client *client)
return; return;
} }
if (buf[0] > data->max_fingers) { if (buf[0] > SILEAD_MAX_FINGERS) {
dev_warn(dev, "More touches reported then supported %d > %d\n", dev_warn(dev, "More touches reported then supported %d > %d\n",
buf[0], data->max_fingers); buf[0], SILEAD_MAX_FINGERS);
buf[0] = data->max_fingers; buf[0] = SILEAD_MAX_FINGERS;
} }
touch_nr = 0; 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) static int silead_ts_init(struct i2c_client *client)
{ {
struct silead_ts_data *data = i2c_get_clientdata(client);
int error; int error;
error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET, 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); usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR, error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR,
data->max_fingers); SILEAD_MAX_FINGERS);
if (error) if (error)
goto i2c_write_err; goto i2c_write_err;
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); 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; const char *str;
int error; 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); error = device_property_read_string(dev, "firmware-name", &str);
if (!error) if (!error)
snprintf(data->fw_name, sizeof(data->fw_name), snprintf(data->fw_name, sizeof(data->fw_name),

View File

@@ -2958,8 +2958,6 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
struct page *vprop_page; struct page *vprop_page;
int base, nr_ids, i, err = 0; int base, nr_ids, i, err = 0;
BUG_ON(!vm);
bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids); bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids);
if (!bitmap) if (!bitmap)
return -ENOMEM; return -ENOMEM;

View File

@@ -75,6 +75,20 @@ struct mbigen_device {
void __iomem *base; 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) static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
{ {
unsigned int nid, pin; 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; nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
pin = hwirq % IRQS_PER_MBIGEN_NODE; pin = hwirq % IRQS_PER_MBIGEN_NODE;
return pin * 4 + nid * MBIGEN_NODE_OFFSET return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
+ REG_MBIGEN_VEC_OFFSET;
} }
static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, 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); *mask = 1 << (irq_ofst % 32);
ofst = irq_ofst / 32 * 4; ofst = irq_ofst / 32 * 4;
*addr = ofst + nid * MBIGEN_NODE_OFFSET *addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
+ REG_MBIGEN_TYPE_OFFSET;
} }
static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq, static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,

View File

@@ -1945,7 +1945,7 @@ hfcmulti_dtmf(struct hfc_multi *hc)
static void static void
hfcmulti_tx(struct hfc_multi *hc, int ch) 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 Zspace, z1, z2; /* must be int for calculation */
int Fspace, f1, f2; int Fspace, f1, f2;
u_char *d; u_char *d;
@@ -2166,14 +2166,15 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
HFC_wait_nodebug(hc); HFC_wait_nodebug(hc);
} }
tmp_len = (*sp)->len;
dev_kfree_skb(*sp); dev_kfree_skb(*sp);
/* check for next frame */ /* check for next frame */
if (bch && get_next_bframe(bch)) { if (bch && get_next_bframe(bch)) {
len = (*sp)->len; len = tmp_len;
goto next_frame; goto next_frame;
} }
if (dch && get_next_dframe(dch)) { if (dch && get_next_dframe(dch)) {
len = (*sp)->len; len = tmp_len;
goto next_frame; goto next_frame;
} }

View File

@@ -126,9 +126,9 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
flags); flags);
cancel_work_sync(&led_cdev->set_brightness_work); cancel_work_sync(&led_cdev->set_brightness_work);
led_stop_software_blink(led_cdev); led_stop_software_blink(led_cdev);
device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
if (led_cdev->trigger->deactivate) if (led_cdev->trigger->deactivate)
led_cdev->trigger->deactivate(led_cdev); led_cdev->trigger->deactivate(led_cdev);
device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
led_cdev->trigger = NULL; led_cdev->trigger = NULL;
led_cdev->trigger_data = NULL; led_cdev->trigger_data = NULL;
led_cdev->activated = false; led_cdev->activated = false;

View File

@@ -368,8 +368,10 @@ static int ich7_lpc_probe(struct pci_dev *dev,
nas_gpio_pci_dev = dev; nas_gpio_pci_dev = dev;
status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base); status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base);
if (status) if (status) {
status = pcibios_err_to_errno(status);
goto out; goto out;
}
g_pm_io_base &= 0x00000ff80; g_pm_io_base &= 0x00000ff80;
status = pci_read_config_dword(dev, GPIO_CTRL, &gc); 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); 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"); dev_info(&dev->dev, "Unable to read GPIOBASE.\n");
status = pcibios_err_to_errno(status);
goto out; goto out;
} }
dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base); dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base);

View File

@@ -549,7 +549,7 @@ g4fan_exit( void )
platform_driver_unregister( &therm_of_driver ); platform_driver_unregister( &therm_of_driver );
if( x.of_dev ) if( x.of_dev )
of_device_unregister( x.of_dev ); of_platform_device_destroy(&x.of_dev->dev, NULL);
} }
module_init(g4fan_init); module_init(g4fan_init);

View File

@@ -1039,8 +1039,26 @@ static int do_resume(struct dm_ioctl *param)
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
if (param->flags & DM_NOFLUSH_FLAG) if (param->flags & DM_NOFLUSH_FLAG)
suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
if (!dm_suspended_md(md)) if (!dm_suspended_md(md)) {
dm_suspend(md, suspend_flags); 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); old_map = dm_swap_table(md, new_map);
if (IS_ERR(old_map)) { if (IS_ERR(old_map)) {

View File

@@ -2585,7 +2585,7 @@ static int dm_wait_for_completion(struct mapped_device *md, long task_state)
break; break;
if (signal_pending_state(task_state, current)) { if (signal_pending_state(task_state, current)) {
r = -EINTR; r = -ERESTARTSYS;
break; break;
} }

View File

@@ -7245,11 +7245,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
mddev = bdev->bd_disk->private_data; mddev = bdev->bd_disk->private_data;
if (!mddev) {
BUG();
goto out;
}
/* Some actions do not requires the mutex */ /* Some actions do not requires the mutex */
switch (cmd) { switch (cmd) {
case GET_ARRAY_INFO: case GET_ARRAY_INFO:

View File

@@ -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); 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) 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; struct sm_metadata *smm;
smm = kmalloc(sizeof(*smm), GFP_KERNEL); smm = kvmalloc(sizeof(*smm), GFP_KERNEL);
if (!smm) if (!smm)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);

View File

@@ -5818,7 +5818,9 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
safepos = conf->reshape_safe; safepos = conf->reshape_safe;
sector_div(safepos, data_disks); sector_div(safepos, data_disks);
if (mddev->reshape_backwards) { if (mddev->reshape_backwards) {
BUG_ON(writepos < reshape_sectors); if (WARN_ON(writepos < reshape_sectors))
return MaxSector;
writepos -= reshape_sectors; writepos -= reshape_sectors;
readpos += reshape_sectors; readpos += reshape_sectors;
safepos += 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. * to set 'stripe_addr' which is where we will write to.
*/ */
if (mddev->reshape_backwards) { if (mddev->reshape_backwards) {
BUG_ON(conf->reshape_progress == 0); if (WARN_ON(conf->reshape_progress == 0))
return MaxSector;
stripe_addr = writepos; stripe_addr = writepos;
BUG_ON((mddev->dev_sectors & if (WARN_ON((mddev->dev_sectors &
~((sector_t)reshape_sectors - 1)) ~((sector_t)reshape_sectors - 1)) -
- reshape_sectors - stripe_addr reshape_sectors - stripe_addr != sector_nr))
!= sector_nr); return MaxSector;
} else { } else {
BUG_ON(writepos != sector_nr + reshape_sectors); if (WARN_ON(writepos != sector_nr + reshape_sectors))
return MaxSector;
stripe_addr = sector_nr; stripe_addr = sector_nr;
} }

View File

@@ -1297,6 +1297,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
/* register Video device */ /* register Video device */
dev->video_dev = cx23885_vdev_init(dev, dev->pci, dev->video_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_video_template, "video"); &cx23885_video_template, "video");
if (!dev->video_dev) {
err = -ENOMEM;
goto fail_unreg;
}
dev->video_dev->queue = &dev->vb2_vidq; dev->video_dev->queue = &dev->vb2_vidq;
err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
video_nr[dev->nr]); video_nr[dev->nr]);
@@ -1311,6 +1315,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
/* register VBI device */ /* register VBI device */
dev->vbi_dev = cx23885_vdev_init(dev, dev->pci, dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_vbi_template, "vbi"); &cx23885_vbi_template, "vbi");
if (!dev->vbi_dev) {
err = -ENOMEM;
goto fail_unreg;
}
dev->vbi_dev->queue = &dev->vb2_vbiq; dev->vbi_dev->queue = &dev->vb2_vbiq;
err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
vbi_nr[dev->nr]); vbi_nr[dev->nr]);

View File

@@ -475,7 +475,9 @@ static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
/* switch the board to analog mode */ /* switch the board to analog mode */
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); 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; return 0;
} }
@@ -1027,7 +1029,9 @@ static int md8800_set_voltage2(struct dvb_frontend *fe,
else else
wbuf[1] = rbuf & 0xef; wbuf[1] = rbuf & 0xef;
msg[0].len = 2; msg[0].len = 2;
i2c_transfer(&dev->i2c_adap, msg, 1); if (i2c_transfer(&dev->i2c_adap, msg, 1) != 1)
return -EIO;
return 0; return 0;
} }

View File

@@ -1096,6 +1096,7 @@ static int vdec_close(struct file *file)
{ {
struct venus_inst *inst = to_inst(file); struct venus_inst *inst = to_inst(file);
cancel_work_sync(&inst->delayed_process_work);
v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev); v4l2_m2m_release(inst->m2m_dev);
vdec_ctrl_deinit(inst); vdec_ctrl_deinit(inst);

View File

@@ -36,9 +36,8 @@ struct vsp1_histogram_buffer *
vsp1_histogram_buffer_get(struct vsp1_histogram *histo) vsp1_histogram_buffer_get(struct vsp1_histogram *histo)
{ {
struct vsp1_histogram_buffer *buf = NULL; struct vsp1_histogram_buffer *buf = NULL;
unsigned long flags;
spin_lock_irqsave(&histo->irqlock, flags); spin_lock(&histo->irqlock);
if (list_empty(&histo->irqqueue)) if (list_empty(&histo->irqqueue))
goto done; goto done;
@@ -49,7 +48,7 @@ vsp1_histogram_buffer_get(struct vsp1_histogram *histo)
histo->readout = true; histo->readout = true;
done: done:
spin_unlock_irqrestore(&histo->irqlock, flags); spin_unlock(&histo->irqlock);
return buf; return buf;
} }
@@ -58,7 +57,6 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
size_t size) size_t size)
{ {
struct vsp1_pipeline *pipe = histo->entity.pipe; struct vsp1_pipeline *pipe = histo->entity.pipe;
unsigned long flags;
/* /*
* The pipeline pointer is guaranteed to be valid as this function is * 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_set_plane_payload(&buf->buf.vb2_buf, 0, size);
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE); vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
spin_lock_irqsave(&histo->irqlock, flags); spin_lock(&histo->irqlock);
histo->readout = false; histo->readout = false;
wake_up(&histo->wait_queue); 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 vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue); struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue);
struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf); 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); 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) 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 *histo = vb2_get_drv_priv(vq);
struct vsp1_histogram_buffer *buffer; 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. */ /* Remove all buffers from the IRQ queue. */
list_for_each_entry(buffer, &histo->irqqueue, 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 for the buffer being read out (if any) to complete. */
wait_event_lock_irq(histo->wait_queue, !histo->readout, histo->irqlock); 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 = { static const struct vb2_ops histo_video_queue_qops = {

View File

@@ -73,7 +73,7 @@ struct vsp1_partition_window {
* @wpf: The WPF partition window configuration * @wpf: The WPF partition window configuration
*/ */
struct vsp1_partition { 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_sink;
struct vsp1_partition_window uds_source; struct vsp1_partition_window uds_source;
struct vsp1_partition_window sru; struct vsp1_partition_window sru;

View File

@@ -270,8 +270,8 @@ static void rpf_configure_partition(struct vsp1_entity *entity,
* 'width' need to be adjusted. * 'width' need to be adjusted.
*/ */
if (pipe->partitions > 1) { if (pipe->partitions > 1) {
crop.width = pipe->partition->rpf.width; crop.width = pipe->partition->rpf[rpf->entity.index].width;
crop.left += pipe->partition->rpf.left; crop.left += pipe->partition->rpf[rpf->entity.index].left;
} }
if (pipe->interlaced) { if (pipe->interlaced) {
@@ -326,7 +326,9 @@ static void rpf_partition(struct vsp1_entity *entity,
unsigned int partition_idx, unsigned int partition_idx,
struct vsp1_partition_window *window) 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 = { static const struct vsp1_entity_operations rpf_entity_ops = {

View File

@@ -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)); memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
if (!mutex_is_locked(&ictx->lock)) { unlock = mutex_trylock(&ictx->lock);
unlock = true;
mutex_lock(&ictx->lock);
}
retval = send_packet(ictx); retval = send_packet(ictx);
if (retval) if (retval)

View File

@@ -997,25 +997,55 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
return value; 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, static int __uvc_ctrl_get(struct uvc_video_chain *chain,
struct uvc_control *ctrl, struct uvc_control_mapping *mapping, struct uvc_control *ctrl,
s32 *value) struct uvc_control_mapping *mapping,
s32 *value)
{ {
int ret; int ret;
if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
return -EACCES; return -EACCES;
if (!ctrl->loaded) { ret = __uvc_ctrl_load_cur(chain, ctrl);
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, if (ret < 0)
chain->dev->intfnum, ctrl->info.selector, return ret;
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
ctrl->info.size);
if (ret < 0)
return ret;
ctrl->loaded = 1;
}
*value = __uvc_ctrl_get_value(mapping, *value = __uvc_ctrl_get_value(mapping,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
@@ -1670,21 +1700,10 @@ int uvc_ctrl_set(struct uvc_fh *handle,
* needs to be loaded from the device to perform the read-modify-write * needs to be loaded from the device to perform the read-modify-write
* operation. * operation.
*/ */
if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) { if ((ctrl->info.size * 8) != mapping->size) {
if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { ret = __uvc_ctrl_load_cur(chain, ctrl);
memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), if (ret < 0)
0, ctrl->info.size); return ret;
} 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 (ret < 0)
return ret;
}
ctrl->loaded = 1;
} }
/* Backup the current value in case we need to rollback later. */ /* Backup the current value in case we need to rollback later. */
@@ -1723,9 +1742,19 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev,
if (data == NULL) if (data == NULL)
return -ENOMEM; return -ENOMEM;
ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum, if (ctrl->entity->get_info)
info->selector, data, 1); ret = ctrl->entity->get_info(dev, ctrl->entity,
if (!ret) 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 ? info->flags |= (data[0] & UVC_CONTROL_CAP_GET ?
UVC_CTRL_FLAG_GET_CUR : 0) UVC_CTRL_FLAG_GET_CUR : 0)
| (data[0] & UVC_CONTROL_CAP_SET ? | (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) UVC_CTRL_FLAG_AUTO_UPDATE : 0)
| (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ? | (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ?
UVC_CTRL_FLAG_ASYNCHRONOUS : 0); UVC_CTRL_FLAG_ASYNCHRONOUS : 0);
}
kfree(data); kfree(data);
return ret; return ret;

View File

@@ -214,13 +214,13 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
/* Compute a bandwidth estimation by multiplying the frame /* Compute a bandwidth estimation by multiplying the frame
* size by the number of video frames per second, divide the * size by the number of video frames per second, divide the
* result by the number of USB frames (or micro-frames for * result by the number of USB frames (or micro-frames for
* high-speed devices) per second and add the UVC header size * high- and super-speed devices) per second and add the UVC
* (assumed to be 12 bytes long). * header size (assumed to be 12 bytes long).
*/ */
bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
bandwidth *= 10000000 / interval + 1; bandwidth *= 10000000 / interval + 1;
bandwidth /= 1000; bandwidth /= 1000;
if (stream->dev->udev->speed == USB_SPEED_HIGH) if (stream->dev->udev->speed >= USB_SPEED_HIGH)
bandwidth /= 8; bandwidth /= 8;
bandwidth += 12; bandwidth += 12;
@@ -475,6 +475,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
ktime_t time; ktime_t time;
u16 host_sof; u16 host_sof;
u16 dev_sof; u16 dev_sof;
u32 dev_stc;
switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
case 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) if (dev_sof == stream->clock.last_sof)
return; 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; stream->clock.last_sof = dev_sof;
host_sof = usb_get_current_frame_number(stream->dev->udev); 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); spin_lock_irqsave(&stream->clock.lock, flags);
sample = &stream->clock.samples[stream->clock.head]; 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->dev_sof = dev_sof;
sample->host_sof = host_sof; sample->host_sof = host_sof;
sample->host_time = time; sample->host_time = time;
@@ -701,11 +730,11 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
unsigned long flags; unsigned long flags;
u64 timestamp; u64 timestamp;
u32 delta_stc; u32 delta_stc;
u32 y1, y2; u32 y1;
u32 x1, x2; u32 x1, x2;
u32 mean; u32 mean;
u32 sof; u32 sof;
u64 y; u64 y, y2;
if (!uvc_hw_timestamps_param) if (!uvc_hw_timestamps_param)
return; return;
@@ -745,7 +774,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
sof = y; sof = y;
uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu " 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, stream->dev->name, buf->pts,
y >> 16, div_u64((y & 0xffff) * 1000000, 65536), y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 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; goto done;
y1 = NSEC_PER_SEC; 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 /* Interpolated and host SOF timestamps can wrap around at slightly
* different times. Handle this by adding or removing 2048 to or from * 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; timestamp = ktime_to_ns(first->host_time) + y - y1;
uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu " 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, stream->dev->name,
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
y, timestamp, vbuf->vb2_buf.timestamp, y, timestamp, vbuf->vb2_buf.timestamp,

View File

@@ -345,6 +345,11 @@ struct uvc_entity {
u8 bNrInPins; u8 bNrInPins;
u8 *baSourceID; 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; unsigned int ncontrols;
struct uvc_control *controls; struct uvc_control *controls;
}; };

Some files were not shown because too many files have changed in this diff Show More