Merge fba396b799 ("sparc/mm: avoid calling arch_enter/leave_lazy_mmu() in set_ptes") into android16-6.12-lts
Steps on the way to 6.12.24 Change-Id: I10efdb86ef7942f71b14841ff3628b4eaa3ae1e9 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -71,7 +71,7 @@ properties:
|
||||
description:
|
||||
Any lane can be inverted or not.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
|
||||
@@ -1451,6 +1451,7 @@
|
||||
/* TODO: update once support for this CMU exists */
|
||||
clocks = <0>;
|
||||
clock-names = "pclk";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
cmu_top: clock-controller@1e080000 {
|
||||
|
||||
@@ -1255,8 +1255,7 @@
|
||||
};
|
||||
|
||||
pwm0: pwm@1401e000 {
|
||||
compatible = "mediatek,mt8173-disp-pwm",
|
||||
"mediatek,mt6595-disp-pwm";
|
||||
compatible = "mediatek,mt8173-disp-pwm";
|
||||
reg = <0 0x1401e000 0 0x1000>;
|
||||
#pwm-cells = <2>;
|
||||
clocks = <&mmsys CLK_MM_DISP_PWM026M>,
|
||||
@@ -1266,8 +1265,7 @@
|
||||
};
|
||||
|
||||
pwm1: pwm@1401f000 {
|
||||
compatible = "mediatek,mt8173-disp-pwm",
|
||||
"mediatek,mt6595-disp-pwm";
|
||||
compatible = "mediatek,mt8173-disp-pwm";
|
||||
reg = <0 0x1401f000 0 0x1000>;
|
||||
#pwm-cells = <2>;
|
||||
clocks = <&mmsys CLK_MM_DISP_PWM126M>,
|
||||
|
||||
@@ -227,13 +227,6 @@
|
||||
wakeup-event-action = <EV_ACT_ASSERTED>;
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
key-suspend {
|
||||
label = "Suspend";
|
||||
gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <EV_KEY>;
|
||||
linux,code = <KEY_SLEEP>;
|
||||
};
|
||||
};
|
||||
|
||||
fan: pwm-fan {
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#define ARM_CPU_PART_CORTEX_A76 0xD0B
|
||||
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
|
||||
#define ARM_CPU_PART_CORTEX_A77 0xD0D
|
||||
#define ARM_CPU_PART_CORTEX_A76AE 0xD0E
|
||||
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
|
||||
#define ARM_CPU_PART_CORTEX_A78 0xD41
|
||||
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
|
||||
@@ -159,6 +160,7 @@
|
||||
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
|
||||
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
|
||||
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
|
||||
#define MIDR_CORTEX_A76AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76AE)
|
||||
#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
|
||||
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
|
||||
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
|
||||
|
||||
@@ -97,7 +97,6 @@ enum mitigation_state arm64_get_meltdown_state(void);
|
||||
|
||||
enum mitigation_state arm64_get_spectre_bhb_state(void);
|
||||
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
|
||||
u8 spectre_bhb_loop_affected(int scope);
|
||||
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
|
||||
bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr);
|
||||
|
||||
|
||||
@@ -845,52 +845,73 @@ static unsigned long system_bhb_mitigations;
|
||||
* This must be called with SCOPE_LOCAL_CPU for each type of CPU, before any
|
||||
* SCOPE_SYSTEM call will give the right answer.
|
||||
*/
|
||||
u8 spectre_bhb_loop_affected(int scope)
|
||||
static bool is_spectre_bhb_safe(int scope)
|
||||
{
|
||||
static const struct midr_range spectre_bhb_safe_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A510),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A520),
|
||||
MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER),
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER),
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
|
||||
{},
|
||||
};
|
||||
static bool all_safe = true;
|
||||
|
||||
if (scope != SCOPE_LOCAL_CPU)
|
||||
return all_safe;
|
||||
|
||||
if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_safe_list))
|
||||
return true;
|
||||
|
||||
all_safe = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 spectre_bhb_loop_affected(void)
|
||||
{
|
||||
u8 k = 0;
|
||||
static u8 max_bhb_k;
|
||||
|
||||
if (scope == SCOPE_LOCAL_CPU) {
|
||||
static const struct midr_range spectre_bhb_k32_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k24_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k11_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k8_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k32_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k24_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k11_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k8_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
||||
{},
|
||||
};
|
||||
|
||||
if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list))
|
||||
k = 32;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list))
|
||||
k = 24;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list))
|
||||
k = 11;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list))
|
||||
k = 8;
|
||||
|
||||
max_bhb_k = max(max_bhb_k, k);
|
||||
} else {
|
||||
k = max_bhb_k;
|
||||
}
|
||||
if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list))
|
||||
k = 32;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list))
|
||||
k = 24;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list))
|
||||
k = 11;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list))
|
||||
k = 8;
|
||||
|
||||
return k;
|
||||
}
|
||||
@@ -916,29 +937,13 @@ static enum mitigation_state spectre_bhb_get_cpu_fw_mitigation_state(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_spectre_bhb_fw_affected(int scope)
|
||||
static bool has_spectre_bhb_fw_mitigation(void)
|
||||
{
|
||||
static bool system_affected;
|
||||
enum mitigation_state fw_state;
|
||||
bool has_smccc = arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_NONE;
|
||||
static const struct midr_range spectre_bhb_firmware_mitigated_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
|
||||
{},
|
||||
};
|
||||
bool cpu_in_list = is_midr_in_range_list(read_cpuid_id(),
|
||||
spectre_bhb_firmware_mitigated_list);
|
||||
|
||||
if (scope != SCOPE_LOCAL_CPU)
|
||||
return system_affected;
|
||||
|
||||
fw_state = spectre_bhb_get_cpu_fw_mitigation_state();
|
||||
if (cpu_in_list || (has_smccc && fw_state == SPECTRE_MITIGATED)) {
|
||||
system_affected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return has_smccc && fw_state == SPECTRE_MITIGATED;
|
||||
}
|
||||
|
||||
static bool supports_ecbhb(int scope)
|
||||
@@ -954,6 +959,8 @@ static bool supports_ecbhb(int scope)
|
||||
ID_AA64MMFR1_EL1_ECBHB_SHIFT);
|
||||
}
|
||||
|
||||
static u8 max_bhb_k;
|
||||
|
||||
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
|
||||
int scope)
|
||||
{
|
||||
@@ -962,16 +969,18 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
|
||||
if (supports_csv2p3(scope))
|
||||
return false;
|
||||
|
||||
if (supports_clearbhb(scope))
|
||||
return true;
|
||||
if (is_spectre_bhb_safe(scope))
|
||||
return false;
|
||||
|
||||
if (spectre_bhb_loop_affected(scope))
|
||||
return true;
|
||||
/*
|
||||
* At this point the core isn't known to be "safe" so we're going to
|
||||
* assume it's vulnerable. We still need to update `max_bhb_k` though,
|
||||
* but only if we aren't mitigating with clearbhb though.
|
||||
*/
|
||||
if (scope == SCOPE_LOCAL_CPU && !supports_clearbhb(SCOPE_LOCAL_CPU))
|
||||
max_bhb_k = max(max_bhb_k, spectre_bhb_loop_affected());
|
||||
|
||||
if (is_spectre_bhb_fw_affected(scope))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
|
||||
@@ -1002,7 +1011,7 @@ early_param("nospectre_bhb", parse_spectre_bhb_param);
|
||||
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
|
||||
{
|
||||
bp_hardening_cb_t cpu_cb;
|
||||
enum mitigation_state fw_state, state = SPECTRE_VULNERABLE;
|
||||
enum mitigation_state state = SPECTRE_VULNERABLE;
|
||||
struct bp_hardening_data *data = this_cpu_ptr(&bp_hardening_data);
|
||||
|
||||
if (!is_spectre_bhb_affected(entry, SCOPE_LOCAL_CPU))
|
||||
@@ -1028,7 +1037,7 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
|
||||
this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN);
|
||||
state = SPECTRE_MITIGATED;
|
||||
set_bit(BHB_INSN, &system_bhb_mitigations);
|
||||
} else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) {
|
||||
} else if (spectre_bhb_loop_affected()) {
|
||||
/*
|
||||
* Ensure KVM uses the indirect vector which will have the
|
||||
* branchy-loop added. A57/A72-r0 will already have selected
|
||||
@@ -1041,32 +1050,29 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
|
||||
this_cpu_set_vectors(EL1_VECTOR_BHB_LOOP);
|
||||
state = SPECTRE_MITIGATED;
|
||||
set_bit(BHB_LOOP, &system_bhb_mitigations);
|
||||
} else if (is_spectre_bhb_fw_affected(SCOPE_LOCAL_CPU)) {
|
||||
fw_state = spectre_bhb_get_cpu_fw_mitigation_state();
|
||||
if (fw_state == SPECTRE_MITIGATED) {
|
||||
/*
|
||||
* Ensure KVM uses one of the spectre bp_hardening
|
||||
* vectors. The indirect vector doesn't include the EL3
|
||||
* call, so needs upgrading to
|
||||
* HYP_VECTOR_SPECTRE_INDIRECT.
|
||||
*/
|
||||
if (!data->slot || data->slot == HYP_VECTOR_INDIRECT)
|
||||
data->slot += 1;
|
||||
} else if (has_spectre_bhb_fw_mitigation()) {
|
||||
/*
|
||||
* Ensure KVM uses one of the spectre bp_hardening
|
||||
* vectors. The indirect vector doesn't include the EL3
|
||||
* call, so needs upgrading to
|
||||
* HYP_VECTOR_SPECTRE_INDIRECT.
|
||||
*/
|
||||
if (!data->slot || data->slot == HYP_VECTOR_INDIRECT)
|
||||
data->slot += 1;
|
||||
|
||||
this_cpu_set_vectors(EL1_VECTOR_BHB_FW);
|
||||
this_cpu_set_vectors(EL1_VECTOR_BHB_FW);
|
||||
|
||||
/*
|
||||
* The WA3 call in the vectors supersedes the WA1 call
|
||||
* made during context-switch. Uninstall any firmware
|
||||
* bp_hardening callback.
|
||||
*/
|
||||
cpu_cb = spectre_v2_get_sw_mitigation_cb();
|
||||
if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb)
|
||||
__this_cpu_write(bp_hardening_data.fn, NULL);
|
||||
/*
|
||||
* The WA3 call in the vectors supersedes the WA1 call
|
||||
* made during context-switch. Uninstall any firmware
|
||||
* bp_hardening callback.
|
||||
*/
|
||||
cpu_cb = spectre_v2_get_sw_mitigation_cb();
|
||||
if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb)
|
||||
__this_cpu_write(bp_hardening_data.fn, NULL);
|
||||
|
||||
state = SPECTRE_MITIGATED;
|
||||
set_bit(BHB_FW, &system_bhb_mitigations);
|
||||
}
|
||||
state = SPECTRE_MITIGATED;
|
||||
set_bit(BHB_FW, &system_bhb_mitigations);
|
||||
}
|
||||
|
||||
update_mitigation_state(&spectre_bhb_state, state);
|
||||
@@ -1100,7 +1106,6 @@ void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt,
|
||||
{
|
||||
u8 rd;
|
||||
u32 insn;
|
||||
u16 loop_count = spectre_bhb_loop_affected(SCOPE_SYSTEM);
|
||||
|
||||
BUG_ON(nr_inst != 1); /* MOV -> MOV */
|
||||
|
||||
@@ -1109,7 +1114,7 @@ void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt,
|
||||
|
||||
insn = le32_to_cpu(*origptr);
|
||||
rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn);
|
||||
insn = aarch64_insn_gen_movewide(rd, loop_count, 0,
|
||||
insn = aarch64_insn_gen_movewide(rd, max_bhb_k, 0,
|
||||
AARCH64_INSN_VARIANT_64BIT,
|
||||
AARCH64_INSN_MOVEWIDE_ZERO);
|
||||
*updptr++ = cpu_to_le32(insn);
|
||||
|
||||
@@ -1361,7 +1361,8 @@ int arch_add_memory(int nid, u64 start, u64 size,
|
||||
__remove_pgd_mapping(swapper_pg_dir,
|
||||
__phys_to_virt(start), size);
|
||||
else {
|
||||
max_pfn = PFN_UP(start + size);
|
||||
/* Address of hotplugged memory can be smaller */
|
||||
max_pfn = max(max_pfn, PFN_UP(start + size));
|
||||
max_low_pfn = max_pfn;
|
||||
}
|
||||
|
||||
|
||||
@@ -936,7 +936,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte, unsigned int nr)
|
||||
{
|
||||
arch_enter_lazy_mmu_mode();
|
||||
for (;;) {
|
||||
__set_pte_at(mm, addr, ptep, pte, 0);
|
||||
if (--nr == 0)
|
||||
@@ -945,7 +944,6 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
|
||||
pte_val(pte) += PAGE_SIZE;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
arch_leave_lazy_mmu_mode();
|
||||
}
|
||||
#define set_ptes set_ptes
|
||||
|
||||
|
||||
@@ -52,8 +52,10 @@ out:
|
||||
|
||||
void arch_enter_lazy_mmu_mode(void)
|
||||
{
|
||||
struct tlb_batch *tb = this_cpu_ptr(&tlb_batch);
|
||||
struct tlb_batch *tb;
|
||||
|
||||
preempt_disable();
|
||||
tb = this_cpu_ptr(&tlb_batch);
|
||||
tb->active = 1;
|
||||
}
|
||||
|
||||
@@ -64,6 +66,7 @@ void arch_leave_lazy_mmu_mode(void)
|
||||
if (tb->tlb_nr)
|
||||
flush_tlb_pending();
|
||||
tb->active = 0;
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
|
||||
|
||||
@@ -331,7 +331,7 @@ ivpu_force_recovery_fn(struct file *file, const char __user *user_buf, size_t si
|
||||
return -EINVAL;
|
||||
|
||||
ret = ivpu_rpm_get(vdev);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ivpu_pm_trigger_recovery(vdev, "debugfs");
|
||||
@@ -408,7 +408,7 @@ static int dct_active_set(void *data, u64 active_percent)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ivpu_rpm_get(vdev);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (active_percent)
|
||||
|
||||
@@ -299,7 +299,8 @@ ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req
|
||||
struct ivpu_ipc_consumer cons;
|
||||
int ret;
|
||||
|
||||
drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev));
|
||||
drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev) &&
|
||||
pm_runtime_enabled(vdev->drm.dev));
|
||||
|
||||
ivpu_ipc_consumer_add(vdev, &cons, channel, NULL);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_file.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "ivpu_drv.h"
|
||||
#include "ivpu_gem.h"
|
||||
@@ -44,6 +45,10 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
|
||||
args->sampling_period_ns < MS_MIN_SAMPLE_PERIOD_NS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ivpu_rpm_get(vdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&file_priv->ms_lock);
|
||||
|
||||
if (get_instance_by_mask(file_priv, args->metric_group_mask)) {
|
||||
@@ -96,6 +101,8 @@ err_free_ms:
|
||||
kfree(ms);
|
||||
unlock:
|
||||
mutex_unlock(&file_priv->ms_lock);
|
||||
|
||||
ivpu_rpm_put(vdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -160,6 +167,10 @@ int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *
|
||||
if (!args->metric_group_mask)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ivpu_rpm_get(vdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&file_priv->ms_lock);
|
||||
|
||||
ms = get_instance_by_mask(file_priv, args->metric_group_mask);
|
||||
@@ -187,6 +198,7 @@ int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *
|
||||
unlock:
|
||||
mutex_unlock(&file_priv->ms_lock);
|
||||
|
||||
ivpu_rpm_put(vdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -204,11 +216,17 @@ int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file
|
||||
{
|
||||
struct ivpu_file_priv *file_priv = file->driver_priv;
|
||||
struct drm_ivpu_metric_streamer_stop *args = data;
|
||||
struct ivpu_device *vdev = file_priv->vdev;
|
||||
struct ivpu_ms_instance *ms;
|
||||
int ret;
|
||||
|
||||
if (!args->metric_group_mask)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ivpu_rpm_get(vdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&file_priv->ms_lock);
|
||||
|
||||
ms = get_instance_by_mask(file_priv, args->metric_group_mask);
|
||||
@@ -217,6 +235,7 @@ int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file
|
||||
|
||||
mutex_unlock(&file_priv->ms_lock);
|
||||
|
||||
ivpu_rpm_put(vdev);
|
||||
return ms ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
@@ -281,6 +300,9 @@ unlock:
|
||||
void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv)
|
||||
{
|
||||
struct ivpu_ms_instance *ms, *tmp;
|
||||
struct ivpu_device *vdev = file_priv->vdev;
|
||||
|
||||
pm_runtime_get_sync(vdev->drm.dev);
|
||||
|
||||
mutex_lock(&file_priv->ms_lock);
|
||||
|
||||
@@ -293,6 +315,8 @@ void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv)
|
||||
free_instance(file_priv, ms);
|
||||
|
||||
mutex_unlock(&file_priv->ms_lock);
|
||||
|
||||
pm_runtime_put_autosuspend(vdev->drm.dev);
|
||||
}
|
||||
|
||||
void ivpu_ms_cleanup_all(struct ivpu_device *vdev)
|
||||
|
||||
@@ -313,7 +313,7 @@ static int hd44780_probe(struct platform_device *pdev)
|
||||
fail3:
|
||||
kfree(hd);
|
||||
fail2:
|
||||
kfree(lcd);
|
||||
charlcd_free(lcd);
|
||||
fail1:
|
||||
kfree(hdc);
|
||||
return ret;
|
||||
@@ -328,7 +328,7 @@ static void hd44780_remove(struct platform_device *pdev)
|
||||
kfree(hdc->hd44780);
|
||||
kfree(lcd->drvdata);
|
||||
|
||||
kfree(lcd);
|
||||
charlcd_free(lcd);
|
||||
}
|
||||
|
||||
static const struct of_device_id hd44780_of_match[] = {
|
||||
|
||||
@@ -1207,11 +1207,16 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
struct mhi_ring_element *mhi_tre;
|
||||
struct mhi_buf_info *buf_info;
|
||||
int eot, eob, chain, bei;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* Protect accesses for reading and incrementing WP */
|
||||
write_lock_bh(&mhi_chan->lock);
|
||||
|
||||
if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf_ring = &mhi_chan->buf_ring;
|
||||
tre_ring = &mhi_chan->tre_ring;
|
||||
|
||||
@@ -1229,10 +1234,8 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
|
||||
if (!info->pre_mapped) {
|
||||
ret = mhi_cntrl->map_single(mhi_cntrl, buf_info);
|
||||
if (ret) {
|
||||
write_unlock_bh(&mhi_chan->lock);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
eob = !!(flags & MHI_EOB);
|
||||
@@ -1250,9 +1253,10 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
mhi_add_ring_element(mhi_cntrl, tre_ring);
|
||||
mhi_add_ring_element(mhi_cntrl, buf_ring);
|
||||
|
||||
out:
|
||||
write_unlock_bh(&mhi_chan->lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
|
||||
@@ -168,6 +168,11 @@ int tpm_try_get_ops(struct tpm_chip *chip)
|
||||
goto out_ops;
|
||||
|
||||
mutex_lock(&chip->tpm_mutex);
|
||||
|
||||
/* tmp_chip_start may issue IO that is denied while suspended */
|
||||
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
|
||||
goto out_lock;
|
||||
|
||||
rc = tpm_chip_start(chip);
|
||||
if (rc)
|
||||
goto out_lock;
|
||||
|
||||
@@ -445,18 +445,11 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
|
||||
/* Give back zero bytes, as TPM chip has not yet fully resumed: */
|
||||
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
rc = tpm2_get_random(chip, out, max);
|
||||
else
|
||||
rc = tpm1_get_random(chip, out, max);
|
||||
|
||||
out:
|
||||
tpm_put_ops(chip);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -114,11 +114,10 @@ again:
|
||||
return 0;
|
||||
/* process status changes without irq support */
|
||||
do {
|
||||
usleep_range(priv->timeout_min, priv->timeout_max);
|
||||
status = chip->ops->status(chip);
|
||||
if ((status & mask) == mask)
|
||||
return 0;
|
||||
usleep_range(priv->timeout_min,
|
||||
priv->timeout_max);
|
||||
} while (time_before(jiffies, stop));
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
@@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) {
|
||||
ret = device_init_wakeup(&pdev->dev, true);
|
||||
if (ret)
|
||||
goto out_clk_disable;
|
||||
device_set_wakeup_capable(&pdev->dev, true);
|
||||
|
||||
ret = dev_pm_set_wake_irq(&pdev->dev, irq);
|
||||
if (ret)
|
||||
|
||||
@@ -190,6 +190,12 @@
|
||||
#define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102
|
||||
#define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302
|
||||
|
||||
#define USB_VENDOR_ID_ASETEK 0x2433
|
||||
#define USB_DEVICE_ID_ASETEK_INVICTA 0xf300
|
||||
#define USB_DEVICE_ID_ASETEK_FORTE 0xf301
|
||||
#define USB_DEVICE_ID_ASETEK_LA_PRIMA 0xf303
|
||||
#define USB_DEVICE_ID_ASETEK_TONY_KANAAN 0xf306
|
||||
|
||||
#define USB_VENDOR_ID_ASUS 0x0486
|
||||
#define USB_DEVICE_ID_ASUS_T91MT 0x0185
|
||||
#define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* hid-pidff wrapper for PID-enabled devices
|
||||
* Handles device reports, quirks and extends usable button range
|
||||
*
|
||||
* Copyright (c) 2024, 2025 Makarenko Oleg
|
||||
* Copyright (c) 2024, 2025 Oleg Makarenko
|
||||
* Copyright (c) 2024, 2025 Tomasz Pakuła
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include "hid-ids.h"
|
||||
#include "usbhid/hid-pidff.h"
|
||||
|
||||
#define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1)
|
||||
|
||||
@@ -89,7 +90,7 @@ static int universal_pidff_probe(struct hid_device *hdev,
|
||||
}
|
||||
|
||||
/* Check if HID_PID support is enabled */
|
||||
int (*init_function)(struct hid_device *, __u32);
|
||||
int (*init_function)(struct hid_device *, u32);
|
||||
init_function = hid_pidff_init_with_quirks;
|
||||
|
||||
if (!init_function) {
|
||||
@@ -103,7 +104,7 @@ static int universal_pidff_probe(struct hid_device *hdev,
|
||||
goto err;
|
||||
}
|
||||
|
||||
hid_info(hdev, "Universal pidff driver loaded sucesfully!");
|
||||
hid_info(hdev, "Universal pidff driver loaded sucessfully!");
|
||||
|
||||
return 0;
|
||||
err:
|
||||
@@ -178,6 +179,10 @@ static const struct hid_device_id universal_pidff_devices[] = {
|
||||
.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF),
|
||||
.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_INVICTA) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_LA_PRIMA) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_TONY_KANAAN) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
|
||||
@@ -193,5 +198,5 @@ module_hid_driver(universal_pidff);
|
||||
|
||||
MODULE_DESCRIPTION("Universal driver for USB PID Force Feedback devices");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Makarenko Oleg <oleg@makarenk.ooo>");
|
||||
MODULE_AUTHOR("Oleg Makarenko <oleg@makarenk.ooo>");
|
||||
MODULE_AUTHOR("Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>");
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <linux/hid-debug.h>
|
||||
#include <linux/hidraw.h>
|
||||
#include "usbhid.h"
|
||||
#include "hid-pidff.h"
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
|
||||
@@ -3,28 +3,27 @@
|
||||
* Force feedback driver for USB HID PID compliant devices
|
||||
*
|
||||
* Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
|
||||
* Upgraded 2025 by Oleg Makarenko and Tomasz Pakuła
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "hid-pidff.h"
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/minmax.h>
|
||||
|
||||
#include "usbhid.h"
|
||||
|
||||
#define PID_EFFECTS_MAX 64
|
||||
#define PID_INFINITE 0xffff
|
||||
#define PID_INFINITE U16_MAX
|
||||
|
||||
/* Linux Force Feedback API uses miliseconds as time unit */
|
||||
#define FF_TIME_EXPONENT -3
|
||||
#define FF_INFINITE 0
|
||||
|
||||
/* Report usage table used to put reports into an array */
|
||||
|
||||
#define PID_SET_EFFECT 0
|
||||
#define PID_EFFECT_OPERATION 1
|
||||
#define PID_DEVICE_GAIN 2
|
||||
@@ -45,12 +44,19 @@ static const u8 pidff_reports[] = {
|
||||
0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab,
|
||||
0x5a, 0x5f, 0x6e, 0x73, 0x74
|
||||
};
|
||||
/*
|
||||
* device_control is really 0x95, but 0x96 specified
|
||||
* as it is the usage of the only field in that report.
|
||||
*/
|
||||
|
||||
/* device_control is really 0x95, but 0x96 specified as it is the usage of
|
||||
the only field in that report */
|
||||
/* PID special fields */
|
||||
#define PID_EFFECT_TYPE 0x25
|
||||
#define PID_DIRECTION 0x57
|
||||
#define PID_EFFECT_OPERATION_ARRAY 0x78
|
||||
#define PID_BLOCK_LOAD_STATUS 0x8b
|
||||
#define PID_DEVICE_CONTROL_ARRAY 0x96
|
||||
|
||||
/* Value usage tables used to put fields and values into arrays */
|
||||
|
||||
#define PID_EFFECT_BLOCK_INDEX 0
|
||||
|
||||
#define PID_DURATION 1
|
||||
@@ -108,10 +114,13 @@ static const u8 pidff_device_gain[] = { 0x7e };
|
||||
static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
|
||||
|
||||
/* Special field key tables used to put special field keys into arrays */
|
||||
|
||||
#define PID_ENABLE_ACTUATORS 0
|
||||
#define PID_RESET 1
|
||||
static const u8 pidff_device_control[] = { 0x97, 0x9a };
|
||||
#define PID_DISABLE_ACTUATORS 1
|
||||
#define PID_STOP_ALL_EFFECTS 2
|
||||
#define PID_RESET 3
|
||||
#define PID_PAUSE 4
|
||||
#define PID_CONTINUE 5
|
||||
static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c };
|
||||
|
||||
#define PID_CONSTANT 0
|
||||
#define PID_RAMP 1
|
||||
@@ -131,13 +140,14 @@ static const u8 pidff_effect_types[] = {
|
||||
|
||||
#define PID_BLOCK_LOAD_SUCCESS 0
|
||||
#define PID_BLOCK_LOAD_FULL 1
|
||||
static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
|
||||
#define PID_BLOCK_LOAD_ERROR 2
|
||||
static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e};
|
||||
|
||||
#define PID_EFFECT_START 0
|
||||
#define PID_EFFECT_STOP 1
|
||||
static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
|
||||
|
||||
/* Polar direction 90 degrees (North) */
|
||||
/* Polar direction 90 degrees (East) */
|
||||
#define PIDFF_FIXED_WHEEL_DIRECTION 0x4000
|
||||
|
||||
struct pidff_usage {
|
||||
@@ -163,8 +173,10 @@ struct pidff_device {
|
||||
struct pidff_usage effect_operation[sizeof(pidff_effect_operation)];
|
||||
struct pidff_usage block_free[sizeof(pidff_block_free)];
|
||||
|
||||
/* Special field is a field that is not composed of
|
||||
usage<->value pairs that pidff_usage values are */
|
||||
/*
|
||||
* Special field is a field that is not composed of
|
||||
* usage<->value pairs that pidff_usage values are
|
||||
*/
|
||||
|
||||
/* Special field in create_new_effect */
|
||||
struct hid_field *create_new_effect_type;
|
||||
@@ -190,30 +202,59 @@ struct pidff_device {
|
||||
int pid_id[PID_EFFECTS_MAX];
|
||||
|
||||
u32 quirks;
|
||||
u8 effect_count;
|
||||
};
|
||||
|
||||
/*
|
||||
* Clamp value for a given field
|
||||
*/
|
||||
static s32 pidff_clamp(s32 i, struct hid_field *field)
|
||||
{
|
||||
s32 clamped = clamp(i, field->logical_minimum, field->logical_maximum);
|
||||
pr_debug("clamped from %d to %d", i, clamped);
|
||||
return clamped;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scale an unsigned value with range 0..max for the given field
|
||||
*/
|
||||
static int pidff_rescale(int i, int max, struct hid_field *field)
|
||||
{
|
||||
return i * (field->logical_maximum - field->logical_minimum) / max +
|
||||
field->logical_minimum;
|
||||
field->logical_minimum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scale a signed value in range -0x8000..0x7fff for the given field
|
||||
* Scale a signed value in range S16_MIN..S16_MAX for the given field
|
||||
*/
|
||||
static int pidff_rescale_signed(int i, struct hid_field *field)
|
||||
{
|
||||
return i == 0 ? 0 : i >
|
||||
0 ? i * field->logical_maximum / 0x7fff : i *
|
||||
field->logical_minimum / -0x8000;
|
||||
if (i > 0) return i * field->logical_maximum / S16_MAX;
|
||||
if (i < 0) return i * field->logical_minimum / S16_MIN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scale time value from Linux default (ms) to field units
|
||||
*/
|
||||
static u32 pidff_rescale_time(u16 time, struct hid_field *field)
|
||||
{
|
||||
u32 scaled_time = time;
|
||||
int exponent = field->unit_exponent;
|
||||
pr_debug("time field exponent: %d\n", exponent);
|
||||
|
||||
for (;exponent < FF_TIME_EXPONENT; exponent++)
|
||||
scaled_time *= 10;
|
||||
for (;exponent > FF_TIME_EXPONENT; exponent--)
|
||||
scaled_time /= 10;
|
||||
|
||||
pr_debug("time calculated from %d to %d\n", time, scaled_time);
|
||||
return scaled_time;
|
||||
}
|
||||
|
||||
static void pidff_set(struct pidff_usage *usage, u16 value)
|
||||
{
|
||||
usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
|
||||
usage->value[0] = pidff_rescale(value, U16_MAX, usage->field);
|
||||
pr_debug("calculated from %d to %d\n", value, usage->value[0]);
|
||||
}
|
||||
|
||||
@@ -224,14 +265,35 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value)
|
||||
else {
|
||||
if (value < 0)
|
||||
usage->value[0] =
|
||||
pidff_rescale(-value, 0x8000, usage->field);
|
||||
pidff_rescale(-value, -S16_MIN, usage->field);
|
||||
else
|
||||
usage->value[0] =
|
||||
pidff_rescale(value, 0x7fff, usage->field);
|
||||
pidff_rescale(value, S16_MAX, usage->field);
|
||||
}
|
||||
pr_debug("calculated from %d to %d\n", value, usage->value[0]);
|
||||
}
|
||||
|
||||
static void pidff_set_time(struct pidff_usage *usage, u16 time)
|
||||
{
|
||||
u32 modified_time = pidff_rescale_time(time, usage->field);
|
||||
usage->value[0] = pidff_clamp(modified_time, usage->field);
|
||||
}
|
||||
|
||||
static void pidff_set_duration(struct pidff_usage *usage, u16 duration)
|
||||
{
|
||||
/* Infinite value conversion from Linux API -> PID */
|
||||
if (duration == FF_INFINITE)
|
||||
duration = PID_INFINITE;
|
||||
|
||||
/* PID defines INFINITE as the max possible value for duration field */
|
||||
if (duration == PID_INFINITE) {
|
||||
usage->value[0] = (1U << usage->field->report_size) - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
pidff_set_time(usage, duration);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send envelope report to the device
|
||||
*/
|
||||
@@ -239,19 +301,21 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
|
||||
struct ff_envelope *envelope)
|
||||
{
|
||||
pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] =
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
|
||||
|
||||
pidff->set_envelope[PID_ATTACK_LEVEL].value[0] =
|
||||
pidff_rescale(envelope->attack_level >
|
||||
0x7fff ? 0x7fff : envelope->attack_level, 0x7fff,
|
||||
pidff->set_envelope[PID_ATTACK_LEVEL].field);
|
||||
pidff_rescale(envelope->attack_level >
|
||||
S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX,
|
||||
pidff->set_envelope[PID_ATTACK_LEVEL].field);
|
||||
pidff->set_envelope[PID_FADE_LEVEL].value[0] =
|
||||
pidff_rescale(envelope->fade_level >
|
||||
0x7fff ? 0x7fff : envelope->fade_level, 0x7fff,
|
||||
pidff->set_envelope[PID_FADE_LEVEL].field);
|
||||
pidff_rescale(envelope->fade_level >
|
||||
S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX,
|
||||
pidff->set_envelope[PID_FADE_LEVEL].field);
|
||||
|
||||
pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
|
||||
pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
|
||||
pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME],
|
||||
envelope->attack_length);
|
||||
pidff_set_time(&pidff->set_envelope[PID_FADE_TIME],
|
||||
envelope->fade_length);
|
||||
|
||||
hid_dbg(pidff->hid, "attack %u => %d\n",
|
||||
envelope->attack_level,
|
||||
@@ -320,14 +384,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
|
||||
pidff->set_effect_type->value[0] =
|
||||
pidff->create_new_effect_type->value[0];
|
||||
|
||||
/* Convert infinite length from Linux API (0)
|
||||
to PID standard (NULL) if needed */
|
||||
pidff->set_effect[PID_DURATION].value[0] =
|
||||
effect->replay.length == 0 ? PID_INFINITE : effect->replay.length;
|
||||
pidff_set_duration(&pidff->set_effect[PID_DURATION],
|
||||
effect->replay.length);
|
||||
|
||||
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
|
||||
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
|
||||
effect->trigger.interval;
|
||||
pidff_set_time(&pidff->set_effect[PID_TRIGGER_REPEAT_INT],
|
||||
effect->trigger.interval);
|
||||
pidff->set_effect[PID_GAIN].value[0] =
|
||||
pidff->set_effect[PID_GAIN].field->logical_maximum;
|
||||
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
|
||||
@@ -336,11 +398,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
|
||||
pidff->effect_direction->value[0] = pidff_rescale(
|
||||
pidff->quirks & HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION ?
|
||||
PIDFF_FIXED_WHEEL_DIRECTION : effect->direction,
|
||||
0xffff, pidff->effect_direction);
|
||||
U16_MAX, pidff->effect_direction);
|
||||
|
||||
/* Omit setting delay field if it's missing */
|
||||
if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
|
||||
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
|
||||
pidff_set_time(&pidff->set_effect[PID_START_DELAY],
|
||||
effect->replay.delay);
|
||||
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
||||
HID_REQ_SET_REPORT);
|
||||
@@ -372,11 +435,11 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
|
||||
pidff_set_signed(&pidff->set_periodic[PID_OFFSET],
|
||||
effect->u.periodic.offset);
|
||||
pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
|
||||
pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
|
||||
pidff_set_time(&pidff->set_periodic[PID_PERIOD],
|
||||
effect->u.periodic.period);
|
||||
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
|
||||
HID_REQ_SET_REPORT);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -476,9 +539,104 @@ static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old)
|
||||
effect->u.ramp.end_level != old->u.ramp.end_level;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set device gain
|
||||
*/
|
||||
static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain)
|
||||
{
|
||||
if (!pidff->device_gain[PID_DEVICE_GAIN_FIELD].field)
|
||||
return;
|
||||
|
||||
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
|
||||
HID_REQ_SET_REPORT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send device control report to the device
|
||||
*/
|
||||
static void pidff_set_device_control(struct pidff_device *pidff, int field)
|
||||
{
|
||||
int i, index;
|
||||
int field_index = pidff->control_id[field];
|
||||
|
||||
if (field_index < 1)
|
||||
return;
|
||||
|
||||
/* Detect if the field is a bitmask variable or an array */
|
||||
if (pidff->device_control->flags & HID_MAIN_ITEM_VARIABLE) {
|
||||
hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n");
|
||||
|
||||
/* Clear current bitmask */
|
||||
for(i = 0; i < sizeof(pidff_device_control); i++) {
|
||||
index = pidff->control_id[i];
|
||||
if (index < 1)
|
||||
continue;
|
||||
|
||||
pidff->device_control->value[index - 1] = 0;
|
||||
}
|
||||
|
||||
pidff->device_control->value[field_index - 1] = 1;
|
||||
} else {
|
||||
hid_dbg(pidff->hid, "DEVICE_CONTROL is an array\n");
|
||||
pidff->device_control->value[0] = field_index;
|
||||
}
|
||||
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
|
||||
hid_hw_wait(pidff->hid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify actuators state
|
||||
*/
|
||||
static void pidff_set_actuators(struct pidff_device *pidff, bool enable)
|
||||
{
|
||||
hid_dbg(pidff->hid, "%s actuators\n", enable ? "Enable" : "Disable");
|
||||
pidff_set_device_control(pidff,
|
||||
enable ? PID_ENABLE_ACTUATORS : PID_DISABLE_ACTUATORS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the device, stop all effects, enable actuators
|
||||
*/
|
||||
static void pidff_reset(struct pidff_device *pidff)
|
||||
{
|
||||
/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
|
||||
pidff_set_device_control(pidff, PID_RESET);
|
||||
pidff_set_device_control(pidff, PID_RESET);
|
||||
pidff->effect_count = 0;
|
||||
|
||||
pidff_set_device_control(pidff, PID_STOP_ALL_EFFECTS);
|
||||
pidff_set_actuators(pidff, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch pool report
|
||||
*/
|
||||
static void pidff_fetch_pool(struct pidff_device *pidff)
|
||||
{
|
||||
int i;
|
||||
struct hid_device *hid = pidff->hid;
|
||||
|
||||
/* Repeat if PID_SIMULTANEOUS_MAX < 2 to make sure it's correct */
|
||||
for(i = 0; i < 20; i++) {
|
||||
hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
|
||||
hid_hw_wait(hid);
|
||||
|
||||
if (!pidff->pool[PID_SIMULTANEOUS_MAX].value)
|
||||
return;
|
||||
if (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] >= 2)
|
||||
return;
|
||||
}
|
||||
hid_warn(hid, "device reports %d simultaneous effects\n",
|
||||
pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a request for effect upload to the device
|
||||
*
|
||||
* Reset and enable actuators if no effects were present on the device
|
||||
*
|
||||
* Returns 0 if device reported success, -ENOSPC if the device reported memory
|
||||
* is full. Upon unknown response the function will retry for 60 times, if
|
||||
* still unsuccessful -EIO is returned.
|
||||
@@ -487,6 +645,9 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (!pidff->effect_count)
|
||||
pidff_reset(pidff);
|
||||
|
||||
pidff->create_new_effect_type->value[0] = efnum;
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
|
||||
HID_REQ_SET_REPORT);
|
||||
@@ -506,6 +667,8 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
|
||||
hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
|
||||
|
||||
pidff->effect_count++;
|
||||
return 0;
|
||||
}
|
||||
if (pidff->block_load_status->value[0] ==
|
||||
@@ -515,6 +678,11 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
|
||||
return -ENOSPC;
|
||||
}
|
||||
if (pidff->block_load_status->value[0] ==
|
||||
pidff->status_id[PID_BLOCK_LOAD_ERROR]) {
|
||||
hid_dbg(pidff->hid, "device error during effect creation\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
}
|
||||
hid_err(pidff->hid, "pid_block_load failed 60 times\n");
|
||||
return -EIO;
|
||||
@@ -533,7 +701,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
|
||||
} else {
|
||||
pidff->effect_operation_status->value[0] =
|
||||
pidff->operation_id[PID_EFFECT_START];
|
||||
pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
|
||||
pidff->effect_operation[PID_LOOP_COUNT].value[0] =
|
||||
pidff_clamp(n, pidff->effect_operation[PID_LOOP_COUNT].field);
|
||||
}
|
||||
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
|
||||
@@ -546,20 +715,22 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
|
||||
static int pidff_playback(struct input_dev *dev, int effect_id, int value)
|
||||
{
|
||||
struct pidff_device *pidff = dev->ff->private;
|
||||
|
||||
pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Erase effect with PID id
|
||||
* Decrease the device effect counter
|
||||
*/
|
||||
static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
|
||||
{
|
||||
pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
|
||||
HID_REQ_SET_REPORT);
|
||||
|
||||
if (pidff->effect_count > 0)
|
||||
pidff->effect_count--;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -572,8 +743,11 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
|
||||
|
||||
hid_dbg(pidff->hid, "starting to erase %d/%d\n",
|
||||
effect_id, pidff->pid_id[effect_id]);
|
||||
/* Wait for the queue to clear. We do not want a full fifo to
|
||||
prevent the effect removal. */
|
||||
|
||||
/*
|
||||
* Wait for the queue to clear. We do not want
|
||||
* a full fifo to prevent the effect removal.
|
||||
*/
|
||||
hid_hw_wait(pidff->hid);
|
||||
pidff_playback_pid(pidff, pid_id, 0);
|
||||
pidff_erase_pid(pidff, pid_id);
|
||||
@@ -671,48 +845,26 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
|
||||
break;
|
||||
|
||||
case FF_SPRING:
|
||||
if (!old) {
|
||||
error = pidff_request_effect_upload(pidff,
|
||||
pidff->type_id[PID_SPRING]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
if (!old || pidff_needs_set_effect(effect, old))
|
||||
pidff_set_effect_report(pidff, effect);
|
||||
if (!old || pidff_needs_set_condition(effect, old))
|
||||
pidff_set_condition_report(pidff, effect);
|
||||
break;
|
||||
|
||||
case FF_DAMPER:
|
||||
case FF_INERTIA:
|
||||
case FF_FRICTION:
|
||||
if (!old) {
|
||||
switch(effect->type) {
|
||||
case FF_SPRING:
|
||||
type_id = PID_SPRING;
|
||||
break;
|
||||
case FF_DAMPER:
|
||||
type_id = PID_DAMPER;
|
||||
break;
|
||||
case FF_INERTIA:
|
||||
type_id = PID_INERTIA;
|
||||
break;
|
||||
case FF_FRICTION:
|
||||
type_id = PID_FRICTION;
|
||||
break;
|
||||
}
|
||||
error = pidff_request_effect_upload(pidff,
|
||||
pidff->type_id[PID_FRICTION]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
if (!old || pidff_needs_set_effect(effect, old))
|
||||
pidff_set_effect_report(pidff, effect);
|
||||
if (!old || pidff_needs_set_condition(effect, old))
|
||||
pidff_set_condition_report(pidff, effect);
|
||||
break;
|
||||
|
||||
case FF_DAMPER:
|
||||
if (!old) {
|
||||
error = pidff_request_effect_upload(pidff,
|
||||
pidff->type_id[PID_DAMPER]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
if (!old || pidff_needs_set_effect(effect, old))
|
||||
pidff_set_effect_report(pidff, effect);
|
||||
if (!old || pidff_needs_set_condition(effect, old))
|
||||
pidff_set_condition_report(pidff, effect);
|
||||
break;
|
||||
|
||||
case FF_INERTIA:
|
||||
if (!old) {
|
||||
error = pidff_request_effect_upload(pidff,
|
||||
pidff->type_id[PID_INERTIA]);
|
||||
pidff->type_id[type_id]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@@ -741,11 +893,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
|
||||
*/
|
||||
static void pidff_set_gain(struct input_dev *dev, u16 gain)
|
||||
{
|
||||
struct pidff_device *pidff = dev->ff->private;
|
||||
|
||||
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
|
||||
HID_REQ_SET_REPORT);
|
||||
pidff_set_gain_report(dev->ff->private, gain);
|
||||
}
|
||||
|
||||
static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
|
||||
@@ -782,9 +930,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
|
||||
*/
|
||||
static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
|
||||
{
|
||||
struct pidff_device *pidff = dev->ff->private;
|
||||
|
||||
pidff_autocenter(pidff, magnitude);
|
||||
pidff_autocenter(dev->ff->private, magnitude);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -979,23 +1125,24 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
|
||||
|
||||
pidff->create_new_effect_type =
|
||||
pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
|
||||
0x25, 1);
|
||||
PID_EFFECT_TYPE, 1);
|
||||
pidff->set_effect_type =
|
||||
pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
|
||||
0x25, 1);
|
||||
PID_EFFECT_TYPE, 1);
|
||||
pidff->effect_direction =
|
||||
pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
|
||||
0x57, 0);
|
||||
PID_DIRECTION, 0);
|
||||
pidff->device_control =
|
||||
pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
|
||||
0x96, !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL));
|
||||
PID_DEVICE_CONTROL_ARRAY,
|
||||
!(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL));
|
||||
|
||||
pidff->block_load_status =
|
||||
pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
|
||||
0x8b, 1);
|
||||
PID_BLOCK_LOAD_STATUS, 1);
|
||||
pidff->effect_operation_status =
|
||||
pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
|
||||
0x78, 1);
|
||||
PID_EFFECT_OPERATION_ARRAY, 1);
|
||||
|
||||
hid_dbg(pidff->hid, "search done\n");
|
||||
|
||||
@@ -1024,10 +1171,6 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pidff_find_special_keys(pidff->control_id, pidff->device_control,
|
||||
pidff_device_control,
|
||||
sizeof(pidff_device_control));
|
||||
|
||||
PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control);
|
||||
|
||||
if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
|
||||
@@ -1106,7 +1249,6 @@ static int pidff_find_effects(struct pidff_device *pidff,
|
||||
set_bit(FF_FRICTION, dev->ffbit);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#define PIDFF_FIND_FIELDS(name, report, strict) \
|
||||
@@ -1207,46 +1349,6 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the device
|
||||
*/
|
||||
static void pidff_reset(struct pidff_device *pidff)
|
||||
{
|
||||
struct hid_device *hid = pidff->hid;
|
||||
int i = 0;
|
||||
|
||||
pidff->device_control->value[0] = pidff->control_id[PID_RESET];
|
||||
/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
|
||||
hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
|
||||
hid_hw_wait(hid);
|
||||
hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
|
||||
hid_hw_wait(hid);
|
||||
|
||||
pidff->device_control->value[0] =
|
||||
pidff->control_id[PID_ENABLE_ACTUATORS];
|
||||
hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
|
||||
hid_hw_wait(hid);
|
||||
|
||||
/* pool report is sometimes messed up, refetch it */
|
||||
hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
|
||||
hid_hw_wait(hid);
|
||||
|
||||
if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
|
||||
while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
|
||||
if (i++ > 20) {
|
||||
hid_warn(pidff->hid,
|
||||
"device reports %d simultaneous effects\n",
|
||||
pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
|
||||
break;
|
||||
}
|
||||
hid_dbg(pidff->hid, "pid_pool requested again\n");
|
||||
hid_hw_request(hid, pidff->reports[PID_POOL],
|
||||
HID_REQ_GET_REPORT);
|
||||
hid_hw_wait(hid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if autocenter modification is using the supported method
|
||||
*/
|
||||
@@ -1271,25 +1373,23 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
|
||||
|
||||
if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] ==
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) {
|
||||
pidff_autocenter(pidff, 0xffff);
|
||||
pidff_autocenter(pidff, U16_MAX);
|
||||
set_bit(FF_AUTOCENTER, dev->ffbit);
|
||||
} else {
|
||||
hid_notice(pidff->hid,
|
||||
"device has unknown autocenter control method\n");
|
||||
}
|
||||
|
||||
pidff_erase_pid(pidff,
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the device is PID and initialize it
|
||||
* Set initial quirks
|
||||
*/
|
||||
int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
|
||||
int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
|
||||
{
|
||||
struct pidff_device *pidff;
|
||||
struct hid_input *hidinput = list_entry(hid->inputs.next,
|
||||
@@ -1312,6 +1412,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
|
||||
|
||||
pidff->hid = hid;
|
||||
pidff->quirks = initial_quirks;
|
||||
pidff->effect_count = 0;
|
||||
|
||||
hid_device_io_start(hid);
|
||||
|
||||
@@ -1328,14 +1429,9 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
pidff_reset(pidff);
|
||||
|
||||
if (test_bit(FF_GAIN, dev->ffbit)) {
|
||||
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
|
||||
hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
|
||||
HID_REQ_SET_REPORT);
|
||||
}
|
||||
|
||||
/* pool report is sometimes messed up, refetch it */
|
||||
pidff_fetch_pool(pidff);
|
||||
pidff_set_gain_report(pidff, U16_MAX);
|
||||
error = pidff_check_autocenter(pidff, dev);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
33
drivers/hid/usbhid/hid-pidff.h
Normal file
33
drivers/hid/usbhid/hid-pidff.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef __HID_PIDFF_H
|
||||
#define __HID_PIDFF_H
|
||||
|
||||
#include <linux/hid.h>
|
||||
|
||||
/* HID PIDFF quirks */
|
||||
|
||||
/* Delay field (0xA7) missing. Skip it during set effect report upload */
|
||||
#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
|
||||
|
||||
/* Missing Paramter block offset (0x23). Skip it during SET_CONDITION
|
||||
report upload */
|
||||
#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
|
||||
|
||||
/* Initialise device control field even if logical_minimum != 1 */
|
||||
#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2)
|
||||
|
||||
/* Use fixed 0x4000 direction during SET_EFFECT report upload */
|
||||
#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3)
|
||||
|
||||
/* Force all periodic effects to be uploaded as SINE */
|
||||
#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY BIT(4)
|
||||
|
||||
#ifdef CONFIG_HID_PID
|
||||
int hid_pidff_init(struct hid_device *hid);
|
||||
int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks);
|
||||
#else
|
||||
#define hid_pidff_init NULL
|
||||
#define hid_pidff_init_with_quirks NULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -2553,6 +2553,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
|
||||
*/
|
||||
void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
|
||||
{
|
||||
if (!dev->ibi || !slot)
|
||||
return;
|
||||
|
||||
atomic_inc(&dev->ibi->pending_ibis);
|
||||
queue_work(dev->ibi->wq, &slot->work);
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
|
||||
slot->len < SVC_I3C_FIFO_SIZE) {
|
||||
mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL);
|
||||
count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl);
|
||||
readsl(master->regs + SVC_I3C_MRDATAB, buf, count);
|
||||
readsb(master->regs + SVC_I3C_MRDATAB, buf, count);
|
||||
slot->len += count;
|
||||
buf += count;
|
||||
}
|
||||
|
||||
@@ -487,17 +487,6 @@ static int tegra241_cmdqv_hw_reset(struct arm_smmu_device *smmu)
|
||||
|
||||
/* VCMDQ Resource Helpers */
|
||||
|
||||
static void tegra241_vcmdq_free_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
|
||||
{
|
||||
struct arm_smmu_queue *q = &vcmdq->cmdq.q;
|
||||
size_t nents = 1 << q->llq.max_n_shift;
|
||||
size_t qsz = nents << CMDQ_ENT_SZ_SHIFT;
|
||||
|
||||
if (!q->base)
|
||||
return;
|
||||
dmam_free_coherent(vcmdq->cmdqv->smmu.dev, qsz, q->base, q->base_dma);
|
||||
}
|
||||
|
||||
static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
|
||||
{
|
||||
struct arm_smmu_device *smmu = &vcmdq->cmdqv->smmu;
|
||||
@@ -560,7 +549,8 @@ static void tegra241_vintf_free_lvcmdq(struct tegra241_vintf *vintf, u16 lidx)
|
||||
struct tegra241_vcmdq *vcmdq = vintf->lvcmdqs[lidx];
|
||||
char header[64];
|
||||
|
||||
tegra241_vcmdq_free_smmu_cmdq(vcmdq);
|
||||
/* Note that the lvcmdq queue memory space is managed by devres */
|
||||
|
||||
tegra241_vintf_deinit_lvcmdq(vintf, lidx);
|
||||
|
||||
dev_dbg(vintf->cmdqv->dev,
|
||||
@@ -768,13 +758,13 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)
|
||||
|
||||
vintf = kzalloc(sizeof(*vintf), GFP_KERNEL);
|
||||
if (!vintf)
|
||||
goto out_fallback;
|
||||
return -ENOMEM;
|
||||
|
||||
/* Init VINTF0 for in-kernel use */
|
||||
ret = tegra241_cmdqv_init_vintf(cmdqv, 0, vintf);
|
||||
if (ret) {
|
||||
dev_err(cmdqv->dev, "failed to init vintf0: %d\n", ret);
|
||||
goto free_vintf;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Preallocate logical VCMDQs to VINTF0 */
|
||||
@@ -783,24 +773,12 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)
|
||||
|
||||
vcmdq = tegra241_vintf_alloc_lvcmdq(vintf, lidx);
|
||||
if (IS_ERR(vcmdq))
|
||||
goto free_lvcmdq;
|
||||
return PTR_ERR(vcmdq);
|
||||
}
|
||||
|
||||
/* Now, we are ready to run all the impl ops */
|
||||
smmu->impl_ops = &tegra241_cmdqv_impl_ops;
|
||||
return 0;
|
||||
|
||||
free_lvcmdq:
|
||||
for (lidx--; lidx >= 0; lidx--)
|
||||
tegra241_vintf_free_lvcmdq(vintf, lidx);
|
||||
tegra241_cmdqv_deinit_vintf(cmdqv, vintf->idx);
|
||||
free_vintf:
|
||||
kfree(vintf);
|
||||
out_fallback:
|
||||
dev_info(smmu->impl_dev, "Falling back to standard SMMU CMDQ\n");
|
||||
smmu->options &= ~ARM_SMMU_OPT_TEGRA241_CMDQV;
|
||||
tegra241_cmdqv_remove(smmu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOMMU_DEBUGFS
|
||||
|
||||
@@ -3174,6 +3174,7 @@ static int __init probe_acpi_namespace_devices(void)
|
||||
if (dev->bus != &acpi_bus_type)
|
||||
continue;
|
||||
|
||||
up_read(&dmar_global_lock);
|
||||
adev = to_acpi_device(dev);
|
||||
mutex_lock(&adev->physical_node_lock);
|
||||
list_for_each_entry(pn,
|
||||
@@ -3183,6 +3184,7 @@ static int __init probe_acpi_namespace_devices(void)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&adev->physical_node_lock);
|
||||
down_read(&dmar_global_lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -26,11 +26,6 @@
|
||||
#include "../iommu-pages.h"
|
||||
#include "cap_audit.h"
|
||||
|
||||
enum irq_mode {
|
||||
IRQ_REMAPPING,
|
||||
IRQ_POSTING,
|
||||
};
|
||||
|
||||
struct ioapic_scope {
|
||||
struct intel_iommu *iommu;
|
||||
unsigned int id;
|
||||
@@ -50,8 +45,8 @@ struct irq_2_iommu {
|
||||
u16 irte_index;
|
||||
u16 sub_handle;
|
||||
u8 irte_mask;
|
||||
enum irq_mode mode;
|
||||
bool posted_msi;
|
||||
bool posted_vcpu;
|
||||
};
|
||||
|
||||
struct intel_ir_data {
|
||||
@@ -139,7 +134,6 @@ static int alloc_irte(struct intel_iommu *iommu,
|
||||
irq_iommu->irte_index = index;
|
||||
irq_iommu->sub_handle = 0;
|
||||
irq_iommu->irte_mask = mask;
|
||||
irq_iommu->mode = IRQ_REMAPPING;
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
|
||||
|
||||
@@ -194,8 +188,6 @@ static int modify_irte(struct irq_2_iommu *irq_iommu,
|
||||
|
||||
rc = qi_flush_iec(iommu, index, 0);
|
||||
|
||||
/* Update iommu mode according to the IRTE mode */
|
||||
irq_iommu->mode = irte->pst ? IRQ_POSTING : IRQ_REMAPPING;
|
||||
raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
|
||||
|
||||
return rc;
|
||||
@@ -1173,7 +1165,26 @@ static void intel_ir_reconfigure_irte_posted(struct irq_data *irqd)
|
||||
static inline void intel_ir_reconfigure_irte_posted(struct irq_data *irqd) {}
|
||||
#endif
|
||||
|
||||
static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force)
|
||||
static void __intel_ir_reconfigure_irte(struct irq_data *irqd, bool force_host)
|
||||
{
|
||||
struct intel_ir_data *ir_data = irqd->chip_data;
|
||||
|
||||
/*
|
||||
* Don't modify IRTEs for IRQs that are being posted to vCPUs if the
|
||||
* host CPU affinity changes.
|
||||
*/
|
||||
if (ir_data->irq_2_iommu.posted_vcpu && !force_host)
|
||||
return;
|
||||
|
||||
ir_data->irq_2_iommu.posted_vcpu = false;
|
||||
|
||||
if (ir_data->irq_2_iommu.posted_msi)
|
||||
intel_ir_reconfigure_irte_posted(irqd);
|
||||
else
|
||||
modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry);
|
||||
}
|
||||
|
||||
static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force_host)
|
||||
{
|
||||
struct intel_ir_data *ir_data = irqd->chip_data;
|
||||
struct irte *irte = &ir_data->irte_entry;
|
||||
@@ -1186,10 +1197,7 @@ static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force)
|
||||
irte->vector = cfg->vector;
|
||||
irte->dest_id = IRTE_DEST(cfg->dest_apicid);
|
||||
|
||||
if (ir_data->irq_2_iommu.posted_msi)
|
||||
intel_ir_reconfigure_irte_posted(irqd);
|
||||
else if (force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
|
||||
modify_irte(&ir_data->irq_2_iommu, irte);
|
||||
__intel_ir_reconfigure_irte(irqd, force_host);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1244,7 +1252,7 @@ static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *info)
|
||||
|
||||
/* stop posting interrupts, back to the default mode */
|
||||
if (!vcpu_pi_info) {
|
||||
modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry);
|
||||
__intel_ir_reconfigure_irte(data, true);
|
||||
} else {
|
||||
struct irte irte_pi;
|
||||
|
||||
@@ -1267,6 +1275,7 @@ static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *info)
|
||||
irte_pi.pda_h = (vcpu_pi_info->pi_desc_addr >> 32) &
|
||||
~(-1UL << PDA_HIGH_BIT);
|
||||
|
||||
ir_data->irq_2_iommu.posted_vcpu = true;
|
||||
modify_irte(&ir_data->irq_2_iommu, &irte_pi);
|
||||
}
|
||||
|
||||
@@ -1282,43 +1291,44 @@ static struct irq_chip intel_ir_chip = {
|
||||
};
|
||||
|
||||
/*
|
||||
* With posted MSIs, all vectors are multiplexed into a single notification
|
||||
* vector. Devices MSIs are then dispatched in a demux loop where
|
||||
* EOIs can be coalesced as well.
|
||||
* With posted MSIs, the MSI vectors are multiplexed into a single notification
|
||||
* vector, and only the notification vector is sent to the APIC IRR. Device
|
||||
* MSIs are then dispatched in a demux loop that harvests the MSIs from the
|
||||
* CPU's Posted Interrupt Request bitmap. I.e. Posted MSIs never get sent to
|
||||
* the APIC IRR, and thus do not need an EOI. The notification handler instead
|
||||
* performs a single EOI after processing the PIR.
|
||||
*
|
||||
* "INTEL-IR-POST" IRQ chip does not do EOI on ACK, thus the dummy irq_ack()
|
||||
* function. Instead EOI is performed by the posted interrupt notification
|
||||
* handler.
|
||||
* Note! Pending SMP/CPU affinity changes, which are per MSI, must still be
|
||||
* honored, only the APIC EOI is omitted.
|
||||
*
|
||||
* For the example below, 3 MSIs are coalesced into one CPU notification. Only
|
||||
* one apic_eoi() is needed.
|
||||
* one apic_eoi() is needed, but each MSI needs to process pending changes to
|
||||
* its CPU affinity.
|
||||
*
|
||||
* __sysvec_posted_msi_notification()
|
||||
* irq_enter();
|
||||
* handle_edge_irq()
|
||||
* irq_chip_ack_parent()
|
||||
* dummy(); // No EOI
|
||||
* irq_move_irq(); // No EOI
|
||||
* handle_irq_event()
|
||||
* driver_handler()
|
||||
* handle_edge_irq()
|
||||
* irq_chip_ack_parent()
|
||||
* dummy(); // No EOI
|
||||
* irq_move_irq(); // No EOI
|
||||
* handle_irq_event()
|
||||
* driver_handler()
|
||||
* handle_edge_irq()
|
||||
* irq_chip_ack_parent()
|
||||
* dummy(); // No EOI
|
||||
* irq_move_irq(); // No EOI
|
||||
* handle_irq_event()
|
||||
* driver_handler()
|
||||
* apic_eoi()
|
||||
* irq_exit()
|
||||
*
|
||||
*/
|
||||
|
||||
static void dummy_ack(struct irq_data *d) { }
|
||||
|
||||
static struct irq_chip intel_ir_chip_post_msi = {
|
||||
.name = "INTEL-IR-POST",
|
||||
.irq_ack = dummy_ack,
|
||||
.irq_ack = irq_move_irq,
|
||||
.irq_set_affinity = intel_ir_set_affinity,
|
||||
.irq_compose_msi_msg = intel_ir_compose_msi_msg,
|
||||
.irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
|
||||
@@ -1494,6 +1504,9 @@ static void intel_irq_remapping_deactivate(struct irq_domain *domain,
|
||||
struct intel_ir_data *data = irq_data->chip_data;
|
||||
struct irte entry;
|
||||
|
||||
WARN_ON_ONCE(data->irq_2_iommu.posted_vcpu);
|
||||
data->irq_2_iommu.posted_vcpu = false;
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
modify_irte(&data->irq_2_iommu, &entry);
|
||||
}
|
||||
|
||||
@@ -1127,7 +1127,7 @@ int iommufd_access_rw(struct iommufd_access *access, unsigned long iova,
|
||||
struct io_pagetable *iopt;
|
||||
struct iopt_area *area;
|
||||
unsigned long last_iova;
|
||||
int rc;
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (!length)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -461,7 +461,7 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period)
|
||||
max_res = LPG_RESOLUTION_9BIT;
|
||||
}
|
||||
|
||||
min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]),
|
||||
min_period = div64_u64((u64)NSEC_PER_SEC * ((1 << pwm_resolution_arr[0]) - 1),
|
||||
clk_rate_arr[clk_len - 1]);
|
||||
if (period <= min_period)
|
||||
return -EINVAL;
|
||||
@@ -482,7 +482,7 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period)
|
||||
*/
|
||||
|
||||
for (i = 0; i < pwm_resolution_count; i++) {
|
||||
resolution = 1 << pwm_resolution_arr[i];
|
||||
resolution = (1 << pwm_resolution_arr[i]) - 1;
|
||||
for (clk_sel = 1; clk_sel < clk_len; clk_sel++) {
|
||||
u64 numerator = period * clk_rate_arr[clk_sel];
|
||||
|
||||
@@ -529,7 +529,7 @@ static void lpg_calc_duty(struct lpg_channel *chan, uint64_t duty)
|
||||
unsigned int clk_rate;
|
||||
|
||||
if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) {
|
||||
max = LPG_RESOLUTION_15BIT - 1;
|
||||
max = BIT(lpg_pwm_resolution_hi_res[chan->pwm_resolution_sel]) - 1;
|
||||
clk_rate = lpg_clk_rates_hi_res[chan->clk_sel];
|
||||
} else {
|
||||
max = LPG_RESOLUTION_9BIT - 1;
|
||||
@@ -1291,7 +1291,7 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * (1 << resolution) *
|
||||
state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * ((1 << resolution) - 1) *
|
||||
pre_div * (1 << m), refclk);
|
||||
state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2016-2025, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@@ -28,12 +28,6 @@
|
||||
#define HSP_INT_FULL_MASK 0xff
|
||||
|
||||
#define HSP_INT_DIMENSIONING 0x380
|
||||
#define HSP_nSM_SHIFT 0
|
||||
#define HSP_nSS_SHIFT 4
|
||||
#define HSP_nAS_SHIFT 8
|
||||
#define HSP_nDB_SHIFT 12
|
||||
#define HSP_nSI_SHIFT 16
|
||||
#define HSP_nINT_MASK 0xf
|
||||
|
||||
#define HSP_DB_TRIGGER 0x0
|
||||
#define HSP_DB_ENABLE 0x4
|
||||
@@ -97,6 +91,20 @@ struct tegra_hsp_soc {
|
||||
bool has_per_mb_ie;
|
||||
bool has_128_bit_mb;
|
||||
unsigned int reg_stride;
|
||||
|
||||
/* Shifts for dimensioning register. */
|
||||
unsigned int si_shift;
|
||||
unsigned int db_shift;
|
||||
unsigned int as_shift;
|
||||
unsigned int ss_shift;
|
||||
unsigned int sm_shift;
|
||||
|
||||
/* Masks for dimensioning register. */
|
||||
unsigned int si_mask;
|
||||
unsigned int db_mask;
|
||||
unsigned int as_mask;
|
||||
unsigned int ss_mask;
|
||||
unsigned int sm_mask;
|
||||
};
|
||||
|
||||
struct tegra_hsp {
|
||||
@@ -747,11 +755,11 @@ static int tegra_hsp_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(hsp->regs);
|
||||
|
||||
value = tegra_hsp_readl(hsp, HSP_INT_DIMENSIONING);
|
||||
hsp->num_sm = (value >> HSP_nSM_SHIFT) & HSP_nINT_MASK;
|
||||
hsp->num_ss = (value >> HSP_nSS_SHIFT) & HSP_nINT_MASK;
|
||||
hsp->num_as = (value >> HSP_nAS_SHIFT) & HSP_nINT_MASK;
|
||||
hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK;
|
||||
hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
|
||||
hsp->num_sm = (value >> hsp->soc->sm_shift) & hsp->soc->sm_mask;
|
||||
hsp->num_ss = (value >> hsp->soc->ss_shift) & hsp->soc->ss_mask;
|
||||
hsp->num_as = (value >> hsp->soc->as_shift) & hsp->soc->as_mask;
|
||||
hsp->num_db = (value >> hsp->soc->db_shift) & hsp->soc->db_mask;
|
||||
hsp->num_si = (value >> hsp->soc->si_shift) & hsp->soc->si_mask;
|
||||
|
||||
err = platform_get_irq_byname_optional(pdev, "doorbell");
|
||||
if (err >= 0)
|
||||
@@ -915,6 +923,16 @@ static const struct tegra_hsp_soc tegra186_hsp_soc = {
|
||||
.has_per_mb_ie = false,
|
||||
.has_128_bit_mb = false,
|
||||
.reg_stride = 0x100,
|
||||
.si_shift = 16,
|
||||
.db_shift = 12,
|
||||
.as_shift = 8,
|
||||
.ss_shift = 4,
|
||||
.sm_shift = 0,
|
||||
.si_mask = 0xf,
|
||||
.db_mask = 0xf,
|
||||
.as_mask = 0xf,
|
||||
.ss_mask = 0xf,
|
||||
.sm_mask = 0xf,
|
||||
};
|
||||
|
||||
static const struct tegra_hsp_soc tegra194_hsp_soc = {
|
||||
@@ -922,6 +940,16 @@ static const struct tegra_hsp_soc tegra194_hsp_soc = {
|
||||
.has_per_mb_ie = true,
|
||||
.has_128_bit_mb = false,
|
||||
.reg_stride = 0x100,
|
||||
.si_shift = 16,
|
||||
.db_shift = 12,
|
||||
.as_shift = 8,
|
||||
.ss_shift = 4,
|
||||
.sm_shift = 0,
|
||||
.si_mask = 0xf,
|
||||
.db_mask = 0xf,
|
||||
.as_mask = 0xf,
|
||||
.ss_mask = 0xf,
|
||||
.sm_mask = 0xf,
|
||||
};
|
||||
|
||||
static const struct tegra_hsp_soc tegra234_hsp_soc = {
|
||||
@@ -929,6 +957,16 @@ static const struct tegra_hsp_soc tegra234_hsp_soc = {
|
||||
.has_per_mb_ie = false,
|
||||
.has_128_bit_mb = true,
|
||||
.reg_stride = 0x100,
|
||||
.si_shift = 16,
|
||||
.db_shift = 12,
|
||||
.as_shift = 8,
|
||||
.ss_shift = 4,
|
||||
.sm_shift = 0,
|
||||
.si_mask = 0xf,
|
||||
.db_mask = 0xf,
|
||||
.as_mask = 0xf,
|
||||
.ss_mask = 0xf,
|
||||
.sm_mask = 0xf,
|
||||
};
|
||||
|
||||
static const struct tegra_hsp_soc tegra264_hsp_soc = {
|
||||
@@ -936,6 +974,16 @@ static const struct tegra_hsp_soc tegra264_hsp_soc = {
|
||||
.has_per_mb_ie = false,
|
||||
.has_128_bit_mb = true,
|
||||
.reg_stride = 0x1000,
|
||||
.si_shift = 17,
|
||||
.db_shift = 12,
|
||||
.as_shift = 8,
|
||||
.ss_shift = 4,
|
||||
.sm_shift = 0,
|
||||
.si_mask = 0x1f,
|
||||
.db_mask = 0x1f,
|
||||
.as_mask = 0xf,
|
||||
.ss_mask = 0xf,
|
||||
.sm_mask = 0xf,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_hsp_match[] = {
|
||||
|
||||
@@ -1243,6 +1243,8 @@ static int __init smsdvb_module_init(void)
|
||||
smsdvb_debugfs_register();
|
||||
|
||||
rc = smscore_register_hotplug(smsdvb_hotplug);
|
||||
if (rc)
|
||||
smsdvb_debugfs_unregister();
|
||||
|
||||
pr_debug("\n");
|
||||
|
||||
|
||||
@@ -320,7 +320,7 @@ struct adv748x_state {
|
||||
|
||||
/* Free run pattern select */
|
||||
#define ADV748X_SDP_FRP 0x14
|
||||
#define ADV748X_SDP_FRP_MASK GENMASK(3, 1)
|
||||
#define ADV748X_SDP_FRP_MASK GENMASK(2, 0)
|
||||
|
||||
/* Saturation */
|
||||
#define ADV748X_SDP_SD_SAT_U 0xe3 /* user_map_rw_reg_e3 */
|
||||
|
||||
@@ -3562,6 +3562,7 @@ static int ccs_probe(struct i2c_client *client)
|
||||
out_disable_runtime_pm:
|
||||
pm_runtime_put_noidle(&client->dev);
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
out_cleanup:
|
||||
ccs_cleanup(sensor);
|
||||
@@ -3591,9 +3592,10 @@ static void ccs_remove(struct i2c_client *client)
|
||||
v4l2_async_unregister_subdev(subdev);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev))
|
||||
if (!pm_runtime_status_suspended(&client->dev)) {
|
||||
ccs_power_off(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
}
|
||||
|
||||
for (i = 0; i < sensor->ssds_used; i++)
|
||||
v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
|
||||
|
||||
@@ -1230,12 +1230,13 @@ static int hi556_check_hwcfg(struct device *dev)
|
||||
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't get clock frequency");
|
||||
return ret;
|
||||
goto check_hwcfg_error;
|
||||
}
|
||||
|
||||
if (mclk != HI556_MCLK) {
|
||||
dev_err(dev, "external clock %d is not supported", mclk);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto check_hwcfg_error;
|
||||
}
|
||||
|
||||
if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) {
|
||||
|
||||
@@ -1077,10 +1077,6 @@ static int imx214_probe(struct i2c_client *client)
|
||||
*/
|
||||
imx214_power_on(imx214->dev);
|
||||
|
||||
pm_runtime_set_active(imx214->dev);
|
||||
pm_runtime_enable(imx214->dev);
|
||||
pm_runtime_idle(imx214->dev);
|
||||
|
||||
ret = imx214_ctrls_init(imx214);
|
||||
if (ret < 0)
|
||||
goto error_power_off;
|
||||
@@ -1101,22 +1097,30 @@ static int imx214_probe(struct i2c_client *client)
|
||||
|
||||
imx214_entity_init_state(&imx214->sd, NULL);
|
||||
|
||||
pm_runtime_set_active(imx214->dev);
|
||||
pm_runtime_enable(imx214->dev);
|
||||
|
||||
ret = v4l2_async_register_subdev_sensor(&imx214->sd);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "could not register v4l2 device\n");
|
||||
goto free_entity;
|
||||
}
|
||||
|
||||
pm_runtime_idle(imx214->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
free_entity:
|
||||
pm_runtime_disable(imx214->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
media_entity_cleanup(&imx214->sd.entity);
|
||||
|
||||
free_ctrl:
|
||||
mutex_destroy(&imx214->mutex);
|
||||
v4l2_ctrl_handler_free(&imx214->ctrls);
|
||||
|
||||
error_power_off:
|
||||
pm_runtime_disable(imx214->dev);
|
||||
regulator_bulk_disable(IMX214_NUM_SUPPLIES, imx214->supplies);
|
||||
imx214_power_off(imx214->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1129,11 +1133,12 @@ static void imx214_remove(struct i2c_client *client)
|
||||
v4l2_async_unregister_subdev(&imx214->sd);
|
||||
media_entity_cleanup(&imx214->sd.entity);
|
||||
v4l2_ctrl_handler_free(&imx214->ctrls);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
mutex_destroy(&imx214->mutex);
|
||||
pm_runtime_disable(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev)) {
|
||||
imx214_power_off(imx214->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct of_device_id imx214_of_match[] = {
|
||||
|
||||
@@ -134,10 +134,11 @@
|
||||
|
||||
/* Pixel rate is fixed for all the modes */
|
||||
#define IMX219_PIXEL_RATE 182400000
|
||||
#define IMX219_PIXEL_RATE_4LANE 280800000
|
||||
#define IMX219_PIXEL_RATE_4LANE 281600000
|
||||
|
||||
#define IMX219_DEFAULT_LINK_FREQ 456000000
|
||||
#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000
|
||||
#define IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED 363000000
|
||||
#define IMX219_DEFAULT_LINK_FREQ_4LANE 364000000
|
||||
|
||||
/* IMX219 native and active pixel array size. */
|
||||
#define IMX219_NATIVE_WIDTH 3296U
|
||||
@@ -169,15 +170,6 @@ static const struct cci_reg_sequence imx219_common_regs[] = {
|
||||
{ CCI_REG8(0x30eb), 0x05 },
|
||||
{ CCI_REG8(0x30eb), 0x09 },
|
||||
|
||||
/* PLL Clock Table */
|
||||
{ IMX219_REG_VTPXCK_DIV, 5 },
|
||||
{ IMX219_REG_VTSYCK_DIV, 1 },
|
||||
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
|
||||
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
|
||||
{ IMX219_REG_PLL_VT_MPY, 57 },
|
||||
{ IMX219_REG_OPSYCK_DIV, 1 },
|
||||
{ IMX219_REG_PLL_OP_MPY, 114 },
|
||||
|
||||
/* Undocumented registers */
|
||||
{ CCI_REG8(0x455e), 0x00 },
|
||||
{ CCI_REG8(0x471e), 0x4b },
|
||||
@@ -202,12 +194,45 @@ static const struct cci_reg_sequence imx219_common_regs[] = {
|
||||
{ IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) },
|
||||
};
|
||||
|
||||
static const struct cci_reg_sequence imx219_2lane_regs[] = {
|
||||
/* PLL Clock Table */
|
||||
{ IMX219_REG_VTPXCK_DIV, 5 },
|
||||
{ IMX219_REG_VTSYCK_DIV, 1 },
|
||||
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
|
||||
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
|
||||
{ IMX219_REG_PLL_VT_MPY, 57 },
|
||||
{ IMX219_REG_OPSYCK_DIV, 1 },
|
||||
{ IMX219_REG_PLL_OP_MPY, 114 },
|
||||
|
||||
/* 2-Lane CSI Mode */
|
||||
{ IMX219_REG_CSI_LANE_MODE, IMX219_CSI_2_LANE_MODE },
|
||||
};
|
||||
|
||||
static const struct cci_reg_sequence imx219_4lane_regs[] = {
|
||||
/* PLL Clock Table */
|
||||
{ IMX219_REG_VTPXCK_DIV, 5 },
|
||||
{ IMX219_REG_VTSYCK_DIV, 1 },
|
||||
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
|
||||
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
|
||||
{ IMX219_REG_PLL_VT_MPY, 88 },
|
||||
{ IMX219_REG_OPSYCK_DIV, 1 },
|
||||
{ IMX219_REG_PLL_OP_MPY, 91 },
|
||||
|
||||
/* 4-Lane CSI Mode */
|
||||
{ IMX219_REG_CSI_LANE_MODE, IMX219_CSI_4_LANE_MODE },
|
||||
};
|
||||
|
||||
static const s64 imx219_link_freq_menu[] = {
|
||||
IMX219_DEFAULT_LINK_FREQ,
|
||||
};
|
||||
|
||||
static const s64 imx219_link_freq_4lane_menu[] = {
|
||||
IMX219_DEFAULT_LINK_FREQ_4LANE,
|
||||
/*
|
||||
* This will never be advertised to userspace, but will be used for
|
||||
* v4l2_link_freq_to_bitmap
|
||||
*/
|
||||
IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static const char * const imx219_test_pattern_menu[] = {
|
||||
@@ -663,9 +688,11 @@ static int imx219_set_framefmt(struct imx219 *imx219,
|
||||
|
||||
static int imx219_configure_lanes(struct imx219 *imx219)
|
||||
{
|
||||
return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE,
|
||||
imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE :
|
||||
IMX219_CSI_4_LANE_MODE, NULL);
|
||||
/* Write the appropriate PLL settings for the number of MIPI lanes */
|
||||
return cci_multi_reg_write(imx219->regmap,
|
||||
imx219->lanes == 2 ? imx219_2lane_regs : imx219_4lane_regs,
|
||||
imx219->lanes == 2 ? ARRAY_SIZE(imx219_2lane_regs) :
|
||||
ARRAY_SIZE(imx219_4lane_regs), NULL);
|
||||
};
|
||||
|
||||
static int imx219_start_streaming(struct imx219 *imx219,
|
||||
@@ -1042,6 +1069,7 @@ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
|
||||
struct v4l2_fwnode_endpoint ep_cfg = {
|
||||
.bus_type = V4L2_MBUS_CSI2_DPHY
|
||||
};
|
||||
unsigned long link_freq_bitmap;
|
||||
int ret = -EINVAL;
|
||||
|
||||
endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
|
||||
@@ -1063,23 +1091,40 @@ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
|
||||
imx219->lanes = ep_cfg.bus.mipi_csi2.num_data_lanes;
|
||||
|
||||
/* Check the link frequency set in device tree */
|
||||
if (!ep_cfg.nr_of_link_frequencies) {
|
||||
dev_err_probe(dev, -EINVAL,
|
||||
"link-frequency property not found in DT\n");
|
||||
goto error_out;
|
||||
switch (imx219->lanes) {
|
||||
case 2:
|
||||
ret = v4l2_link_freq_to_bitmap(dev,
|
||||
ep_cfg.link_frequencies,
|
||||
ep_cfg.nr_of_link_frequencies,
|
||||
imx219_link_freq_menu,
|
||||
ARRAY_SIZE(imx219_link_freq_menu),
|
||||
&link_freq_bitmap);
|
||||
break;
|
||||
case 4:
|
||||
ret = v4l2_link_freq_to_bitmap(dev,
|
||||
ep_cfg.link_frequencies,
|
||||
ep_cfg.nr_of_link_frequencies,
|
||||
imx219_link_freq_4lane_menu,
|
||||
ARRAY_SIZE(imx219_link_freq_4lane_menu),
|
||||
&link_freq_bitmap);
|
||||
|
||||
if (!ret && (link_freq_bitmap & BIT(1))) {
|
||||
dev_warn(dev, "Link frequency of %d not supported, but has been incorrectly advertised previously\n",
|
||||
IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED);
|
||||
dev_warn(dev, "Using link frequency of %d\n",
|
||||
IMX219_DEFAULT_LINK_FREQ_4LANE);
|
||||
link_freq_bitmap |= BIT(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ep_cfg.nr_of_link_frequencies != 1 ||
|
||||
(ep_cfg.link_frequencies[0] != ((imx219->lanes == 2) ?
|
||||
IMX219_DEFAULT_LINK_FREQ : IMX219_DEFAULT_LINK_FREQ_4LANE))) {
|
||||
if (ret || !(link_freq_bitmap & BIT(0))) {
|
||||
ret = -EINVAL;
|
||||
dev_err_probe(dev, -EINVAL,
|
||||
"Link frequency not supported: %lld\n",
|
||||
ep_cfg.link_frequencies[0]);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
error_out:
|
||||
v4l2_fwnode_endpoint_free(&ep_cfg);
|
||||
fwnode_handle_put(endpoint);
|
||||
@@ -1186,6 +1231,9 @@ static int imx219_probe(struct i2c_client *client)
|
||||
goto error_media_entity;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = v4l2_async_register_subdev_sensor(&imx219->sd);
|
||||
if (ret < 0) {
|
||||
dev_err_probe(dev, ret,
|
||||
@@ -1193,15 +1241,14 @@ static int imx219_probe(struct i2c_client *client)
|
||||
goto error_subdev_cleanup;
|
||||
}
|
||||
|
||||
/* Enable runtime PM and turn off the device */
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_idle(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
error_subdev_cleanup:
|
||||
v4l2_subdev_cleanup(&imx219->sd);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
|
||||
error_media_entity:
|
||||
media_entity_cleanup(&imx219->sd.entity);
|
||||
@@ -1226,9 +1273,10 @@ static void imx219_remove(struct i2c_client *client)
|
||||
imx219_free_controls(imx219);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev))
|
||||
if (!pm_runtime_status_suspended(&client->dev)) {
|
||||
imx219_power_off(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct of_device_id imx219_dt_ids[] = {
|
||||
|
||||
@@ -2442,17 +2442,19 @@ static int imx319_probe(struct i2c_client *client)
|
||||
if (full_power)
|
||||
pm_runtime_set_active(&client->dev);
|
||||
pm_runtime_enable(&client->dev);
|
||||
pm_runtime_idle(&client->dev);
|
||||
|
||||
ret = v4l2_async_register_subdev_sensor(&imx319->sd);
|
||||
if (ret < 0)
|
||||
goto error_media_entity_pm;
|
||||
|
||||
pm_runtime_idle(&client->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
error_media_entity_pm:
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
if (full_power)
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
media_entity_cleanup(&imx319->sd.entity);
|
||||
|
||||
error_handler_free:
|
||||
@@ -2474,7 +2476,8 @@ static void imx319_remove(struct i2c_client *client)
|
||||
v4l2_ctrl_handler_free(sd->ctrl_handler);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev))
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
mutex_destroy(&imx319->mutex);
|
||||
}
|
||||
|
||||
@@ -922,6 +922,8 @@ static int ov7251_set_power_on(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
gpiod_set_value_cansleep(ov7251->enable_gpio, 1);
|
||||
|
||||
/* wait at least 65536 external clock cycles */
|
||||
@@ -1696,7 +1698,7 @@ static int ov7251_probe(struct i2c_client *client)
|
||||
return PTR_ERR(ov7251->analog_regulator);
|
||||
}
|
||||
|
||||
ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
|
||||
ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ov7251->enable_gpio)) {
|
||||
dev_err(dev, "cannot get enable gpio\n");
|
||||
return PTR_ERR(ov7251->enable_gpio);
|
||||
|
||||
@@ -1296,6 +1296,7 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av)
|
||||
av->vdev.release = video_device_release_empty;
|
||||
av->vdev.fops = &isys_fops;
|
||||
av->vdev.v4l2_dev = &av->isys->v4l2_dev;
|
||||
av->vdev.dev_parent = &av->isys->adev->isp->pdev->dev;
|
||||
if (!av->vdev.ioctl_ops)
|
||||
av->vdev.ioctl_ops = &ipu6_v4l2_ioctl_ops;
|
||||
av->vdev.queue = &av->aq.vbq;
|
||||
|
||||
@@ -135,8 +135,8 @@ static const u16 cmt_vals_out[][15] = {
|
||||
};
|
||||
|
||||
static const u16 cmt_vals_in[][13] = {
|
||||
{0x1082, 0x0000, 0x5104, 0x0000, 0x11C7, 0x0000, 0x1041, 0x02BC, 0x7C01, 0xFFE9, 0x9900, 0x9908, 0x8100},
|
||||
{0x1104, 0x0000, 0x9208, 0x0000, 0x138E, 0x0000, 0x1041, 0x015E, 0x7C01, 0xFFE9, 0x0100, 0x0908, 0x1000},
|
||||
{0x1082, 0x0000, 0x5104, 0x0000, 0x11C7, 0x0000, 0x1041, 0x02BC, 0x7C01, 0xFFE9, 0x9900, 0x9908, 0x8100},
|
||||
};
|
||||
|
||||
static const u32 cmt_addrs_out[][15] = {
|
||||
@@ -206,10 +206,11 @@ u32 mgb4_cmt_set_vout_freq(struct mgb4_vout_dev *voutdev, unsigned int freq)
|
||||
|
||||
mgb4_write_reg(video, regs->config, 0x1 | (config & ~0x3));
|
||||
|
||||
mgb4_mask_reg(video, regs->config, 0x100, 0x100);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cmt_addrs_out[0]); i++)
|
||||
mgb4_write_reg(&voutdev->mgbdev->cmt, addr[i], reg_set[i]);
|
||||
|
||||
mgb4_mask_reg(video, regs->config, 0x100, 0x100);
|
||||
mgb4_mask_reg(video, regs->config, 0x100, 0x0);
|
||||
|
||||
mgb4_write_reg(video, regs->config, config & ~0x1);
|
||||
@@ -236,10 +237,11 @@ void mgb4_cmt_set_vin_freq_range(struct mgb4_vin_dev *vindev,
|
||||
|
||||
mgb4_write_reg(video, regs->config, 0x1 | (config & ~0x3));
|
||||
|
||||
mgb4_mask_reg(video, regs->config, 0x1000, 0x1000);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cmt_addrs_in[0]); i++)
|
||||
mgb4_write_reg(&vindev->mgbdev->cmt, addr[i], reg_set[i]);
|
||||
|
||||
mgb4_mask_reg(video, regs->config, 0x1000, 0x1000);
|
||||
mgb4_mask_reg(video, regs->config, 0x1000, 0x0);
|
||||
|
||||
mgb4_write_reg(video, regs->config, config & ~0x1);
|
||||
|
||||
@@ -576,7 +576,7 @@ int wave5_vpu_build_up_dec_param(struct vpu_instance *inst,
|
||||
vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1,
|
||||
WAVE521_COMMAND_QUEUE_DEPTH - 1);
|
||||
}
|
||||
|
||||
vpu_write_reg(inst->dev, W5_CMD_ERR_CONCEAL, 0);
|
||||
ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL);
|
||||
if (ret) {
|
||||
wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work);
|
||||
|
||||
@@ -1424,10 +1424,24 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count
|
||||
if (ret)
|
||||
goto free_bitstream_vbuf;
|
||||
} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
|
||||
struct dec_initial_info *initial_info =
|
||||
&inst->codec_info->dec_info.initial_info;
|
||||
|
||||
if (inst->state == VPU_INST_STATE_STOP)
|
||||
ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ);
|
||||
if (ret)
|
||||
goto return_buffers;
|
||||
|
||||
if (inst->state == VPU_INST_STATE_INIT_SEQ &&
|
||||
inst->dev->product_code == WAVE521C_CODE) {
|
||||
if (initial_info->luma_bitdepth != 8) {
|
||||
dev_info(inst->dev->dev, "%s: no support for %d bit depth",
|
||||
__func__, initial_info->luma_bitdepth);
|
||||
ret = -EINVAL;
|
||||
goto return_buffers;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1446,6 +1460,16 @@ static int streamoff_output(struct vb2_queue *q)
|
||||
struct vb2_v4l2_buffer *buf;
|
||||
int ret;
|
||||
dma_addr_t new_rd_ptr;
|
||||
struct dec_output_info dec_info;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < v4l2_m2m_num_dst_bufs_ready(m2m_ctx); i++) {
|
||||
ret = wave5_vpu_dec_set_disp_flag(inst, i);
|
||||
if (ret)
|
||||
dev_dbg(inst->dev->dev,
|
||||
"%s: Setting display flag of buf index: %u, fail: %d\n",
|
||||
__func__, i, ret);
|
||||
}
|
||||
|
||||
while ((buf = v4l2_m2m_src_buf_remove(m2m_ctx))) {
|
||||
dev_dbg(inst->dev->dev, "%s: (Multiplanar) buf type %4u | index %4u\n",
|
||||
@@ -1453,6 +1477,11 @@ static int streamoff_output(struct vb2_queue *q)
|
||||
v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
|
||||
while (wave5_vpu_dec_get_output_info(inst, &dec_info) == 0) {
|
||||
if (dec_info.index_frame_display >= 0)
|
||||
wave5_vpu_dec_set_disp_flag(inst, dec_info.index_frame_display);
|
||||
}
|
||||
|
||||
ret = wave5_vpu_flush_instance(inst);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1535,7 +1564,7 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q)
|
||||
break;
|
||||
|
||||
if (wave5_vpu_dec_get_output_info(inst, &dec_output_info))
|
||||
dev_dbg(inst->dev->dev, "Getting decoding results from fw, fail\n");
|
||||
dev_dbg(inst->dev->dev, "there is no output info\n");
|
||||
}
|
||||
|
||||
v4l2_m2m_update_stop_streaming_state(m2m_ctx, q);
|
||||
|
||||
@@ -54,12 +54,12 @@ static void wave5_vpu_handle_irq(void *dev_id)
|
||||
struct vpu_device *dev = dev_id;
|
||||
|
||||
irq_reason = wave5_vdi_read_register(dev, W5_VPU_VINT_REASON);
|
||||
seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO);
|
||||
cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST);
|
||||
wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_reason);
|
||||
wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1);
|
||||
|
||||
list_for_each_entry(inst, &dev->instances, list) {
|
||||
seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO);
|
||||
cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST);
|
||||
|
||||
if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
|
||||
irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {
|
||||
|
||||
@@ -73,6 +73,16 @@ int wave5_vpu_flush_instance(struct vpu_instance *inst)
|
||||
inst->type == VPU_INST_TYPE_DEC ? "DECODER" : "ENCODER", inst->id);
|
||||
mutex_unlock(&inst->dev->hw_lock);
|
||||
return -ETIMEDOUT;
|
||||
} else if (ret == -EBUSY) {
|
||||
struct dec_output_info dec_info;
|
||||
|
||||
mutex_unlock(&inst->dev->hw_lock);
|
||||
wave5_vpu_dec_get_output_info(inst, &dec_info);
|
||||
ret = mutex_lock_interruptible(&inst->dev->hw_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (dec_info.index_frame_display > 0)
|
||||
wave5_vpu_dec_set_disp_flag(inst, dec_info.index_frame_display);
|
||||
}
|
||||
} while (ret != 0);
|
||||
mutex_unlock(&inst->dev->hw_lock);
|
||||
|
||||
@@ -79,8 +79,11 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(void *priv, enum mtk_vcodec_fw_use
|
||||
}
|
||||
|
||||
fw = devm_kzalloc(&plat_dev->dev, sizeof(*fw), GFP_KERNEL);
|
||||
if (!fw)
|
||||
if (!fw) {
|
||||
scp_put(scp);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
fw->type = SCP;
|
||||
fw->ops = &mtk_vcodec_rproc_msg;
|
||||
fw->scp = scp;
|
||||
|
||||
@@ -594,7 +594,11 @@ static int h264_enc_init(struct mtk_vcodec_enc_ctx *ctx)
|
||||
|
||||
inst->ctx = ctx;
|
||||
inst->vpu_inst.ctx = ctx;
|
||||
inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264;
|
||||
if (is_ext)
|
||||
inst->vpu_inst.id = SCP_IPI_VENC_H264;
|
||||
else
|
||||
inst->vpu_inst.id = IPI_VENC_H264;
|
||||
|
||||
inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx->dev->reg_base, VENC_SYS);
|
||||
|
||||
ret = vpu_enc_init(&inst->vpu_inst);
|
||||
|
||||
@@ -1650,8 +1650,8 @@ rel_ctrl_handler:
|
||||
|
||||
static int npcm_video_ece_init(struct npcm_video *video)
|
||||
{
|
||||
struct device_node *ece_node __free(device_node) = NULL;
|
||||
struct device *dev = video->dev;
|
||||
struct device_node *ece_node;
|
||||
struct platform_device *ece_pdev;
|
||||
void __iomem *regs;
|
||||
|
||||
@@ -1671,7 +1671,7 @@ static int npcm_video_ece_init(struct npcm_video *video)
|
||||
dev_err(dev, "Failed to find ECE device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
of_node_put(ece_node);
|
||||
struct device *ece_dev __free(put_device) = &ece_pdev->dev;
|
||||
|
||||
regs = devm_platform_ioremap_resource(ece_pdev, 0);
|
||||
if (IS_ERR(regs)) {
|
||||
@@ -1686,7 +1686,7 @@ static int npcm_video_ece_init(struct npcm_video *video)
|
||||
return PTR_ERR(video->ece.regmap);
|
||||
}
|
||||
|
||||
video->ece.reset = devm_reset_control_get(&ece_pdev->dev, NULL);
|
||||
video->ece.reset = devm_reset_control_get(ece_dev, NULL);
|
||||
if (IS_ERR(video->ece.reset)) {
|
||||
dev_err(dev, "Failed to get ECE reset control in DTS\n");
|
||||
return PTR_ERR(video->ece.reset);
|
||||
|
||||
@@ -187,6 +187,9 @@ static int venus_write_queue(struct venus_hfi_device *hdev,
|
||||
/* ensure rd/wr indices's are read from memory */
|
||||
rmb();
|
||||
|
||||
if (qsize > IFACEQ_QUEUE_SIZE / 4)
|
||||
return -EINVAL;
|
||||
|
||||
if (wr_idx >= rd_idx)
|
||||
empty_space = qsize - (wr_idx - rd_idx);
|
||||
else
|
||||
@@ -255,6 +258,9 @@ static int venus_read_queue(struct venus_hfi_device *hdev,
|
||||
wr_idx = qhdr->write_idx;
|
||||
qsize = qhdr->q_size;
|
||||
|
||||
if (qsize > IFACEQ_QUEUE_SIZE / 4)
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure data is valid before using it */
|
||||
rmb();
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ static void rga_cmd_set_dst_info(struct rga_ctx *ctx,
|
||||
* Configure the dest framebuffer base address with pixel offset.
|
||||
*/
|
||||
offsets = rga_get_addr_offset(&ctx->out, offset, dst_x, dst_y, dst_w, dst_h);
|
||||
dst_offset = rga_lookup_draw_pos(&offsets, mir_mode, rot_mode);
|
||||
dst_offset = rga_lookup_draw_pos(&offsets, rot_mode, mir_mode);
|
||||
|
||||
dest[(RGA_DST_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
|
||||
dst_offset->y_off;
|
||||
|
||||
@@ -492,7 +492,8 @@ static void device_run(void *prv)
|
||||
dst->sequence = frm_cap->sequence++;
|
||||
v4l2_m2m_buf_copy_metadata(src, dst, true);
|
||||
|
||||
clk_enable(dev->gate);
|
||||
if (clk_enable(dev->gate))
|
||||
goto end;
|
||||
|
||||
dma2d_config_fg(dev, frm_out,
|
||||
vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0));
|
||||
|
||||
@@ -138,39 +138,10 @@ static void sz_push_half_space(struct streamzap_ir *sz,
|
||||
sz_push_full_space(sz, value & SZ_SPACE_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* streamzap_callback - usb IRQ handler callback
|
||||
*
|
||||
* This procedure is invoked on reception of data from
|
||||
* the usb remote.
|
||||
*/
|
||||
static void streamzap_callback(struct urb *urb)
|
||||
static void sz_process_ir_data(struct streamzap_ir *sz, int len)
|
||||
{
|
||||
struct streamzap_ir *sz;
|
||||
unsigned int i;
|
||||
int len;
|
||||
|
||||
if (!urb)
|
||||
return;
|
||||
|
||||
sz = urb->context;
|
||||
len = urb->actual_length;
|
||||
|
||||
switch (urb->status) {
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
/*
|
||||
* this urb is terminated, clean up.
|
||||
* sz might already be invalid at this point
|
||||
*/
|
||||
dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
|
||||
for (i = 0; i < len; i++) {
|
||||
dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
|
||||
i, (unsigned char)sz->buf_in[i]);
|
||||
@@ -219,6 +190,43 @@ static void streamzap_callback(struct urb *urb)
|
||||
}
|
||||
|
||||
ir_raw_event_handle(sz->rdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* streamzap_callback - usb IRQ handler callback
|
||||
*
|
||||
* This procedure is invoked on reception of data from
|
||||
* the usb remote.
|
||||
*/
|
||||
static void streamzap_callback(struct urb *urb)
|
||||
{
|
||||
struct streamzap_ir *sz;
|
||||
int len;
|
||||
|
||||
if (!urb)
|
||||
return;
|
||||
|
||||
sz = urb->context;
|
||||
len = urb->actual_length;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
|
||||
sz_process_ir_data(sz, len);
|
||||
break;
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
/*
|
||||
* this urb is terminated, clean up.
|
||||
* sz might already be invalid at this point
|
||||
*/
|
||||
dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
|
||||
@@ -1316,9 +1316,6 @@ static int vim2m_probe(struct platform_device *pdev)
|
||||
vfd->v4l2_dev = &dev->v4l2_dev;
|
||||
|
||||
video_set_drvdata(vfd, dev);
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"Device registered as /dev/video%d\n", vfd->num);
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
|
||||
@@ -1345,6 +1342,9 @@ static int vim2m_probe(struct platform_device *pdev)
|
||||
goto error_m2m;
|
||||
}
|
||||
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"Device registered as /dev/video%d\n", vfd->num);
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER
|
||||
ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
|
||||
MEDIA_ENT_F_PROC_VIDEO_SCALER);
|
||||
|
||||
@@ -161,9 +161,15 @@ static const struct visl_ctrl_desc visl_h264_ctrl_descs[] = {
|
||||
},
|
||||
{
|
||||
.cfg.id = V4L2_CID_STATELESS_H264_DECODE_MODE,
|
||||
.cfg.min = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED,
|
||||
.cfg.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
|
||||
.cfg.def = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED,
|
||||
},
|
||||
{
|
||||
.cfg.id = V4L2_CID_STATELESS_H264_START_CODE,
|
||||
.cfg.min = V4L2_STATELESS_H264_START_CODE_NONE,
|
||||
.cfg.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
|
||||
.cfg.def = V4L2_STATELESS_H264_START_CODE_NONE,
|
||||
},
|
||||
{
|
||||
.cfg.id = V4L2_CID_STATELESS_H264_SLICE_PARAMS,
|
||||
@@ -198,9 +204,15 @@ static const struct visl_ctrl_desc visl_hevc_ctrl_descs[] = {
|
||||
},
|
||||
{
|
||||
.cfg.id = V4L2_CID_STATELESS_HEVC_DECODE_MODE,
|
||||
.cfg.min = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED,
|
||||
.cfg.max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
|
||||
.cfg.def = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED,
|
||||
},
|
||||
{
|
||||
.cfg.id = V4L2_CID_STATELESS_HEVC_START_CODE,
|
||||
.cfg.min = V4L2_STATELESS_HEVC_START_CODE_NONE,
|
||||
.cfg.max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
|
||||
.cfg.def = V4L2_STATELESS_HEVC_START_CODE_NONE,
|
||||
},
|
||||
{
|
||||
.cfg.id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS,
|
||||
|
||||
@@ -764,7 +764,7 @@ bool v4l2_detect_gtf(unsigned int frame_height,
|
||||
u64 num;
|
||||
u32 den;
|
||||
|
||||
num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) -
|
||||
num = (((u64)image_width * GTF_D_C_PRIME * hfreq) -
|
||||
((u64)image_width * GTF_D_M_PRIME * 1000));
|
||||
den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) *
|
||||
(2 * GTF_CELL_GRAN);
|
||||
@@ -774,7 +774,7 @@ bool v4l2_detect_gtf(unsigned int frame_height,
|
||||
u64 num;
|
||||
u32 den;
|
||||
|
||||
num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) -
|
||||
num = (((u64)image_width * GTF_S_C_PRIME * hfreq) -
|
||||
((u64)image_width * GTF_S_M_PRIME * 1000));
|
||||
den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) *
|
||||
(2 * GTF_CELL_GRAN);
|
||||
|
||||
@@ -162,7 +162,7 @@ static int kb3930_probe(struct i2c_client *client)
|
||||
devm_gpiod_get_array_optional(dev, "off", GPIOD_IN);
|
||||
if (IS_ERR(ddata->off_gpios))
|
||||
return PTR_ERR(ddata->off_gpios);
|
||||
if (ddata->off_gpios->ndescs < 2) {
|
||||
if (ddata->off_gpios && ddata->off_gpios->ndescs < 2) {
|
||||
dev_err(dev, "invalid off-gpios property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -482,10 +482,11 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
silly = MAX_LOOPS;
|
||||
|
||||
while (thisEUN <= inftl->lastEUN) {
|
||||
inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
|
||||
blockofs, 8, &retlen, (char *)&bci);
|
||||
|
||||
status = bci.Status | bci.Status1;
|
||||
if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
|
||||
blockofs, 8, &retlen, (char *)&bci) < 0)
|
||||
status = SECTOR_IGNORE;
|
||||
else
|
||||
status = bci.Status | bci.Status1;
|
||||
pr_debug("INFTL: status of block %d in EUN %d is %x\n",
|
||||
block , writeEUN, status);
|
||||
|
||||
|
||||
@@ -417,11 +417,14 @@ static void mtdpstore_notify_add(struct mtd_info *mtd)
|
||||
}
|
||||
|
||||
longcnt = BITS_TO_LONGS(div_u64(mtd->size, info->kmsg_size));
|
||||
cxt->rmmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL);
|
||||
cxt->usedmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL);
|
||||
cxt->rmmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL);
|
||||
cxt->usedmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL);
|
||||
|
||||
longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize));
|
||||
cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL);
|
||||
cxt->badmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL);
|
||||
|
||||
if (!cxt->rmmap || !cxt->usedmap || !cxt->badmap)
|
||||
return;
|
||||
|
||||
/* just support dmesg right now */
|
||||
cxt->dev.flags = PSTORE_FLAGS_DMESG;
|
||||
@@ -527,9 +530,6 @@ static void mtdpstore_notify_remove(struct mtd_info *mtd)
|
||||
mtdpstore_flush_removed(cxt);
|
||||
|
||||
unregister_pstore_device(&cxt->dev);
|
||||
kfree(cxt->badmap);
|
||||
kfree(cxt->usedmap);
|
||||
kfree(cxt->rmmap);
|
||||
cxt->mtd = NULL;
|
||||
cxt->index = -1;
|
||||
}
|
||||
|
||||
@@ -3008,7 +3008,7 @@ static int brcmnand_resume(struct device *dev)
|
||||
brcmnand_save_restore_cs_config(host, 1);
|
||||
|
||||
/* Reset the chip, required by some chips after power-up */
|
||||
nand_reset_op(chip);
|
||||
nand_reset(chip, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -387,6 +387,9 @@ static int r852_wait(struct nand_chip *chip)
|
||||
static int r852_ready(struct nand_chip *chip)
|
||||
{
|
||||
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
|
||||
if (dev->card_unstable)
|
||||
return 0;
|
||||
|
||||
return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY);
|
||||
}
|
||||
|
||||
|
||||
@@ -3691,6 +3691,21 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
|
||||
return mv88e6xxx_g1_stats_clear(chip);
|
||||
}
|
||||
|
||||
static int mv88e6320_setup_errata(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
u16 dummy;
|
||||
int err;
|
||||
|
||||
/* Workaround for erratum
|
||||
* 3.3 RGMII timing may be out of spec when transmit delay is enabled
|
||||
*/
|
||||
err = mv88e6xxx_port_hidden_write(chip, 0, 0xf, 0x7, 0xe000);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mv88e6xxx_port_hidden_read(chip, 0, 0xf, 0x7, &dummy);
|
||||
}
|
||||
|
||||
/* Check if the errata has already been applied. */
|
||||
static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
@@ -5144,6 +5159,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6320_ops = {
|
||||
/* MV88E6XXX_FAMILY_6320 */
|
||||
.setup_errata = mv88e6320_setup_errata,
|
||||
.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
|
||||
.ip_pri_map = mv88e6085_g1_ip_pri_map,
|
||||
.irl_init_all = mv88e6352_g2_irl_init_all,
|
||||
@@ -5193,6 +5209,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6321_ops = {
|
||||
/* MV88E6XXX_FAMILY_6320 */
|
||||
.setup_errata = mv88e6320_setup_errata,
|
||||
.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
|
||||
.ip_pri_map = mv88e6085_g1_ip_pri_map,
|
||||
.irl_init_all = mv88e6352_g2_irl_init_all,
|
||||
@@ -6154,7 +6171,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.num_databases = 4096,
|
||||
.num_macs = 8192,
|
||||
.num_ports = 7,
|
||||
.num_internal_phys = 5,
|
||||
.num_internal_phys = 2,
|
||||
.internal_phys_offset = 3,
|
||||
.num_gpio = 15,
|
||||
.max_vid = 4095,
|
||||
.max_sid = 63,
|
||||
@@ -6348,7 +6366,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.num_databases = 4096,
|
||||
.num_macs = 8192,
|
||||
.num_ports = 7,
|
||||
.num_internal_phys = 5,
|
||||
.num_internal_phys = 2,
|
||||
.internal_phys_offset = 3,
|
||||
.num_gpio = 15,
|
||||
.max_vid = 4095,
|
||||
.max_sid = 63,
|
||||
|
||||
@@ -95,6 +95,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
|
||||
if (!dev->test_mtd.name) {
|
||||
ret = -ENOMEM;
|
||||
goto out_put_node;
|
||||
}
|
||||
dev->test_mtd.offset = offset;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -755,6 +755,7 @@ struct mt76_testmode_data {
|
||||
|
||||
struct mt76_vif {
|
||||
u8 idx;
|
||||
u8 link_idx;
|
||||
u8 omac_idx;
|
||||
u8 band_idx;
|
||||
u8 wmm_idx;
|
||||
|
||||
@@ -1164,7 +1164,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
|
||||
.len = cpu_to_le16(sizeof(struct req_tlv)),
|
||||
.active = enable,
|
||||
.link_idx = mvif->idx,
|
||||
.link_idx = mvif->link_idx,
|
||||
},
|
||||
};
|
||||
struct {
|
||||
@@ -1187,7 +1187,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
.bmc_tx_wlan_idx = cpu_to_le16(wcid->idx),
|
||||
.sta_idx = cpu_to_le16(wcid->idx),
|
||||
.conn_state = 1,
|
||||
.link_idx = mvif->idx,
|
||||
.link_idx = mvif->link_idx,
|
||||
},
|
||||
};
|
||||
int err, idx, cmd, len;
|
||||
|
||||
@@ -256,7 +256,7 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)
|
||||
|
||||
ext_capab[0].eml_capabilities = phy->eml_cap;
|
||||
ext_capab[0].mld_capa_and_ops =
|
||||
u16_encode_bits(1, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);
|
||||
u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);
|
||||
|
||||
wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
|
||||
wiphy->iftype_ext_capab = ext_capab;
|
||||
@@ -356,10 +356,15 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
||||
struct mt76_txq *mtxq;
|
||||
int idx, ret = 0;
|
||||
|
||||
mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
mconf->mt76.idx = MT792x_MAX_INTERFACES;
|
||||
} else {
|
||||
mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
|
||||
if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ?
|
||||
@@ -367,6 +372,7 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
||||
mconf->mt76.band_idx = 0xff;
|
||||
mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?
|
||||
0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
|
||||
mconf->mt76.link_idx = hweight16(mvif->valid_links);
|
||||
|
||||
if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
|
||||
mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4;
|
||||
|
||||
@@ -3119,13 +3119,14 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
.env = env_cap,
|
||||
};
|
||||
int ret, valid_cnt = 0;
|
||||
u8 i, *pos;
|
||||
u8 *pos, *last_pos;
|
||||
|
||||
if (!clc)
|
||||
return 0;
|
||||
|
||||
pos = clc->data + sizeof(*seg) * clc->nr_seg;
|
||||
for (i = 0; i < clc->nr_country; i++) {
|
||||
last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4));
|
||||
while (pos < last_pos) {
|
||||
struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos;
|
||||
|
||||
pos += sizeof(*rule);
|
||||
|
||||
@@ -566,8 +566,8 @@ struct mt7925_wow_pattern_tlv {
|
||||
u8 offset;
|
||||
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
|
||||
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
|
||||
u8 rsv[7];
|
||||
} __packed;
|
||||
u8 rsv[4];
|
||||
};
|
||||
|
||||
struct roc_acquire_tlv {
|
||||
__le16 tag;
|
||||
|
||||
@@ -131,6 +131,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
|
||||
|
||||
soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
||||
"%x", soc_info.revision);
|
||||
if (!soc_dev_attr->revision)
|
||||
return -ENOMEM;
|
||||
soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
|
||||
if (!soc_dev_attr->soc_id) {
|
||||
pr_err("Unknown SoC\n");
|
||||
|
||||
@@ -1634,6 +1634,12 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi)
|
||||
int ret = PTR_ERR(cqspi->rx_chan);
|
||||
|
||||
cqspi->rx_chan = NULL;
|
||||
if (ret == -ENODEV) {
|
||||
/* DMA support is not mandatory */
|
||||
dev_info(&cqspi->pdev->dev, "No Rx DMA available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dev_err_probe(&cqspi->pdev->dev, ret, "No Rx DMA available\n");
|
||||
}
|
||||
init_completion(&cqspi->rx_dma_complete);
|
||||
|
||||
@@ -190,9 +190,12 @@ again:
|
||||
klm->bcount = cpu_to_be32(klm_bcount(dmr->end - dmr->start));
|
||||
preve = dmr->end;
|
||||
} else {
|
||||
u64 bcount = min_t(u64, dmr->start - preve, MAX_KLM_SIZE);
|
||||
|
||||
klm->key = cpu_to_be32(mvdev->res.null_mkey);
|
||||
klm->bcount = cpu_to_be32(klm_bcount(dmr->start - preve));
|
||||
preve = dmr->start;
|
||||
klm->bcount = cpu_to_be32(klm_bcount(bcount));
|
||||
preve += bcount;
|
||||
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,8 +229,11 @@ static void led_bl_remove(struct platform_device *pdev)
|
||||
backlight_device_unregister(bl);
|
||||
|
||||
led_bl_power_off(priv);
|
||||
for (i = 0; i < priv->nb_leds; i++)
|
||||
for (i = 0; i < priv->nb_leds; i++) {
|
||||
mutex_lock(&priv->leds[i]->led_access);
|
||||
led_sysfs_enable(priv->leds[i]);
|
||||
mutex_unlock(&priv->leds[i]->led_access);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct of_device_id led_bl_of_match[] = {
|
||||
|
||||
@@ -48,7 +48,7 @@ static int xensyms_next_sym(struct xensyms *xs)
|
||||
return -ENOMEM;
|
||||
|
||||
set_xen_guest_handle(symdata->name, xs->name);
|
||||
symdata->symnum--; /* Rewind */
|
||||
symdata->symnum = symnum; /* Rewind */
|
||||
|
||||
ret = HYPERVISOR_platform_op(&xs->op);
|
||||
if (ret < 0)
|
||||
@@ -78,7 +78,7 @@ static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos)
|
||||
{
|
||||
struct xensyms *xs = m->private;
|
||||
|
||||
xs->op.u.symdata.symnum = ++(*pos);
|
||||
*pos = xs->op.u.symdata.symnum;
|
||||
|
||||
if (xensyms_next_sym(xs))
|
||||
return NULL;
|
||||
|
||||
@@ -4274,6 +4274,18 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
|
||||
*/
|
||||
btrfs_flush_workqueue(fs_info->delalloc_workers);
|
||||
|
||||
/*
|
||||
* When finishing a compressed write bio we schedule a work queue item
|
||||
* to finish an ordered extent - btrfs_finish_compressed_write_work()
|
||||
* calls btrfs_finish_ordered_extent() which in turns does a call to
|
||||
* btrfs_queue_ordered_fn(), and that queues the ordered extent
|
||||
* completion either in the endio_write_workers work queue or in the
|
||||
* fs_info->endio_freespace_worker work queue. We flush those queues
|
||||
* below, so before we flush them we must flush this queue for the
|
||||
* workers of compressed writes.
|
||||
*/
|
||||
flush_workqueue(fs_info->compressed_write_workers);
|
||||
|
||||
/*
|
||||
* After we parked the cleaner kthread, ordered extents may have
|
||||
* completed and created new delayed iputs. If one of the async reclaim
|
||||
|
||||
@@ -1045,6 +1045,7 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info,
|
||||
ret = btrfs_add_chunk_map(fs_info, map);
|
||||
if (ret) {
|
||||
test_err("error adding chunk map to mapping tree");
|
||||
btrfs_free_chunk_map(map);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
||||
@@ -2107,6 +2107,9 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
|
||||
physical = map->stripes[i].physical;
|
||||
zinfo = device->zone_info;
|
||||
|
||||
if (!device->bdev)
|
||||
continue;
|
||||
|
||||
if (zinfo->max_active_zones == 0)
|
||||
continue;
|
||||
|
||||
@@ -2268,6 +2271,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
|
||||
struct btrfs_zoned_device_info *zinfo = device->zone_info;
|
||||
unsigned int nofs_flags;
|
||||
|
||||
if (!device->bdev)
|
||||
continue;
|
||||
|
||||
if (zinfo->max_active_zones == 0)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -1995,7 +1995,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
||||
* split it in half by count; each resulting block will have at least
|
||||
* half the space free.
|
||||
*/
|
||||
if (i > 0)
|
||||
if (i >= 0)
|
||||
split = count - move;
|
||||
else
|
||||
split = count/2;
|
||||
|
||||
@@ -1884,7 +1884,6 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
|
||||
|
||||
/* Log is no longer empty */
|
||||
write_lock(&journal->j_state_lock);
|
||||
WARN_ON(!sb->s_sequence);
|
||||
journal->j_flags &= ~JBD2_FLUSHED;
|
||||
write_unlock(&journal->j_state_lock);
|
||||
|
||||
|
||||
@@ -2474,6 +2474,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
|
||||
return 0;
|
||||
if (tcon->nodelete != ctx->nodelete)
|
||||
return 0;
|
||||
if (tcon->posix_extensions != ctx->linux_ext)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -810,6 +810,7 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
|
||||
}
|
||||
map->oflags = UDF_BLK_MAPPED;
|
||||
map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
|
||||
ret = 0;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
||||
@@ -1221,21 +1221,6 @@ unsigned long hid_lookup_quirk(const struct hid_device *hdev);
|
||||
int hid_quirks_init(char **quirks_param, __u16 bus, int count);
|
||||
void hid_quirks_exit(__u16 bus);
|
||||
|
||||
#ifdef CONFIG_HID_PID
|
||||
int hid_pidff_init(struct hid_device *hid);
|
||||
int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks);
|
||||
#else
|
||||
#define hid_pidff_init NULL
|
||||
#define hid_pidff_init_with_quirks NULL
|
||||
#endif
|
||||
|
||||
/* HID PIDFF quirks */
|
||||
#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
|
||||
#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
|
||||
#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2)
|
||||
#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3)
|
||||
#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY BIT(4)
|
||||
|
||||
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
|
||||
|
||||
#define hid_err(hid, fmt, ...) \
|
||||
|
||||
@@ -457,6 +457,7 @@ enum {
|
||||
REQ_F_SKIP_LINK_CQES_BIT,
|
||||
REQ_F_SINGLE_POLL_BIT,
|
||||
REQ_F_DOUBLE_POLL_BIT,
|
||||
REQ_F_MULTISHOT_BIT,
|
||||
REQ_F_APOLL_MULTISHOT_BIT,
|
||||
REQ_F_CLEAR_POLLIN_BIT,
|
||||
REQ_F_HASH_LOCKED_BIT,
|
||||
@@ -530,6 +531,8 @@ enum {
|
||||
REQ_F_SINGLE_POLL = IO_REQ_FLAG(REQ_F_SINGLE_POLL_BIT),
|
||||
/* double poll may active */
|
||||
REQ_F_DOUBLE_POLL = IO_REQ_FLAG(REQ_F_DOUBLE_POLL_BIT),
|
||||
/* request posts multiple completions, should be set at prep time */
|
||||
REQ_F_MULTISHOT = IO_REQ_FLAG(REQ_F_MULTISHOT_BIT),
|
||||
/* fast poll multishot mode */
|
||||
REQ_F_APOLL_MULTISHOT = IO_REQ_FLAG(REQ_F_APOLL_MULTISHOT_BIT),
|
||||
/* recvmsg special flag, clear EPOLLIN */
|
||||
|
||||
@@ -1528,7 +1528,7 @@ enum rksip1_ext_param_buffer_version {
|
||||
* The expected memory layout of the parameters buffer is::
|
||||
*
|
||||
* +-------------------- struct rkisp1_ext_params_cfg -------------------+
|
||||
* | version = RKISP_EXT_PARAMS_BUFFER_V1; |
|
||||
* | version = RKISP1_EXT_PARAM_BUFFER_V1; |
|
||||
* | data_size = sizeof(struct rkisp1_ext_params_bls_config) |
|
||||
* | + sizeof(struct rkisp1_ext_params_dpcc_config); |
|
||||
* | +------------------------- data ---------------------------------+ |
|
||||
|
||||
@@ -1821,7 +1821,7 @@ fail:
|
||||
* Don't allow any multishot execution from io-wq. It's more restrictive
|
||||
* than necessary and also cleaner.
|
||||
*/
|
||||
if (req->flags & REQ_F_APOLL_MULTISHOT) {
|
||||
if (req->flags & (REQ_F_MULTISHOT|REQ_F_APOLL_MULTISHOT)) {
|
||||
err = -EBADFD;
|
||||
if (!io_file_can_poll(req))
|
||||
goto fail;
|
||||
@@ -1832,7 +1832,7 @@ fail:
|
||||
goto fail;
|
||||
return;
|
||||
} else {
|
||||
req->flags &= ~REQ_F_APOLL_MULTISHOT;
|
||||
req->flags &= ~(REQ_F_APOLL_MULTISHOT|REQ_F_MULTISHOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -484,6 +484,8 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
||||
p->nbufs = tmp;
|
||||
p->addr = READ_ONCE(sqe->addr);
|
||||
p->len = READ_ONCE(sqe->len);
|
||||
if (!p->len)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_mul_overflow((unsigned long)p->len, (unsigned long)p->nbufs,
|
||||
&size))
|
||||
|
||||
@@ -435,6 +435,7 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
||||
sr->msg_flags |= MSG_WAITALL;
|
||||
sr->buf_group = req->buf_index;
|
||||
req->buf_list = NULL;
|
||||
req->flags |= REQ_F_MULTISHOT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
@@ -1616,6 +1617,8 @@ retry:
|
||||
}
|
||||
|
||||
io_req_set_res(req, ret, cflags);
|
||||
if (!(issue_flags & IO_URING_F_MULTISHOT))
|
||||
return IOU_OK;
|
||||
return IOU_STOP_MULTISHOT;
|
||||
}
|
||||
|
||||
|
||||
@@ -6223,6 +6223,9 @@ static void zap_class(struct pending_free *pf, struct lock_class *class)
|
||||
hlist_del_rcu(&class->hash_entry);
|
||||
WRITE_ONCE(class->key, NULL);
|
||||
WRITE_ONCE(class->name, NULL);
|
||||
/* Class allocated but not used, -1 in nr_unused_locks */
|
||||
if (class->usage_mask == 0)
|
||||
debug_atomic_dec(nr_unused_locks);
|
||||
nr_lock_classes--;
|
||||
__clear_bit(class - lock_classes, lock_classes_in_use);
|
||||
if (class - lock_classes == max_lock_class_idx)
|
||||
|
||||
@@ -88,8 +88,6 @@ static void sg_split_phys(struct sg_splitter *splitters, const int nb_splits)
|
||||
if (!j) {
|
||||
out_sg->offset += split->skip_sg0;
|
||||
out_sg->length -= split->skip_sg0;
|
||||
} else {
|
||||
out_sg->offset = 0;
|
||||
}
|
||||
sg_dma_address(out_sg) = 0;
|
||||
sg_dma_len(out_sg) = 0;
|
||||
|
||||
@@ -367,6 +367,12 @@ u32 airtime_link_metric_get(struct ieee80211_local *local,
|
||||
return (u32)result;
|
||||
}
|
||||
|
||||
/* Check that the first metric is at least 10% better than the second one */
|
||||
static bool is_metric_better(u32 x, u32 y)
|
||||
{
|
||||
return (x < y) && (x < (y - x / 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* hwmp_route_info_get - Update routing info to originator and transmitter
|
||||
*
|
||||
@@ -458,8 +464,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
|
||||
(mpath->sn == orig_sn &&
|
||||
(rcu_access_pointer(mpath->next_hop) !=
|
||||
sta ?
|
||||
mult_frac(new_metric, 10, 9) :
|
||||
new_metric) >= mpath->metric)) {
|
||||
!is_metric_better(new_metric, mpath->metric) :
|
||||
new_metric >= mpath->metric))) {
|
||||
process = false;
|
||||
fresh_info = false;
|
||||
}
|
||||
@@ -533,8 +539,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
|
||||
if ((mpath->flags & MESH_PATH_FIXED) ||
|
||||
((mpath->flags & MESH_PATH_ACTIVE) &&
|
||||
((rcu_access_pointer(mpath->next_hop) != sta ?
|
||||
mult_frac(last_hop_metric, 10, 9) :
|
||||
last_hop_metric) > mpath->metric)))
|
||||
!is_metric_better(last_hop_metric, mpath->metric) :
|
||||
last_hop_metric > mpath->metric))))
|
||||
fresh_info = false;
|
||||
} else {
|
||||
mpath = mesh_path_add(sdata, ta);
|
||||
|
||||
@@ -1419,6 +1419,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
|
||||
switch (optname) {
|
||||
case IP_TOS:
|
||||
return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->tos));
|
||||
case IP_FREEBIND:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_test_bit(FREEBIND, sk));
|
||||
case IP_TRANSPARENT:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_test_bit(TRANSPARENT, sk));
|
||||
case IP_BIND_ADDRESS_NO_PORT:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
|
||||
@@ -1430,6 +1436,26 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct sock *sk = (void *)msk;
|
||||
|
||||
switch (optname) {
|
||||
case IPV6_V6ONLY:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
sk->sk_ipv6only);
|
||||
case IPV6_TRANSPARENT:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_test_bit(TRANSPARENT, sk));
|
||||
case IPV6_FREEBIND:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_test_bit(FREEBIND, sk));
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
@@ -1469,6 +1495,8 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname,
|
||||
|
||||
if (level == SOL_IP)
|
||||
return mptcp_getsockopt_v4(msk, optname, optval, option);
|
||||
if (level == SOL_IPV6)
|
||||
return mptcp_getsockopt_v6(msk, optname, optval, option);
|
||||
if (level == SOL_TCP)
|
||||
return mptcp_getsockopt_sol_tcp(msk, optname, optval, option);
|
||||
if (level == SOL_MPTCP)
|
||||
|
||||
@@ -754,8 +754,6 @@ static bool subflow_hmac_valid(const struct request_sock *req,
|
||||
|
||||
subflow_req = mptcp_subflow_rsk(req);
|
||||
msk = subflow_req->msk;
|
||||
if (!msk)
|
||||
return false;
|
||||
|
||||
subflow_generate_hmac(READ_ONCE(msk->remote_key),
|
||||
READ_ONCE(msk->local_key),
|
||||
@@ -853,12 +851,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
|
||||
|
||||
} else if (subflow_req->mp_join) {
|
||||
mptcp_get_options(skb, &mp_opt);
|
||||
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) ||
|
||||
!subflow_hmac_valid(req, &mp_opt) ||
|
||||
!mptcp_can_accept_new_subflow(subflow_req->msk)) {
|
||||
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
|
||||
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK))
|
||||
fallback = true;
|
||||
}
|
||||
}
|
||||
|
||||
create_child:
|
||||
@@ -908,6 +902,17 @@ create_child:
|
||||
goto dispose_child;
|
||||
}
|
||||
|
||||
if (!subflow_hmac_valid(req, &mp_opt)) {
|
||||
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
|
||||
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
||||
goto dispose_child;
|
||||
}
|
||||
|
||||
if (!mptcp_can_accept_new_subflow(owner)) {
|
||||
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
||||
goto dispose_child;
|
||||
}
|
||||
|
||||
/* move the msk reference ownership to the subflow */
|
||||
subflow_req->msk = NULL;
|
||||
ctx->conn = (struct sock *)owner;
|
||||
|
||||
@@ -621,7 +621,8 @@ static void __svc_rdma_free(struct work_struct *work)
|
||||
/* Destroy the CM ID */
|
||||
rdma_destroy_id(rdma->sc_cm_id);
|
||||
|
||||
rpcrdma_rn_unregister(device, &rdma->sc_rn);
|
||||
if (!test_bit(XPT_LISTENER, &rdma->sc_xprt.xpt_flags))
|
||||
rpcrdma_rn_unregister(device, &rdma->sc_rn);
|
||||
kfree(rdma);
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,11 @@ ARGIND == 2 && !anchor && NF == 2 && $1 ~ /^0x/ && $2 !~ /^0x/ {
|
||||
# section.
|
||||
#
|
||||
ARGIND == 2 && sect && NF == 4 && /^ [^ \*]/ && !($1 in sect_addend) {
|
||||
# There are a few sections with constant data (without symbols) that
|
||||
# can get resized during linking, so it is best to ignore them.
|
||||
if ($1 ~ /^\.rodata\.(cst|str)[0-9]/)
|
||||
next;
|
||||
|
||||
if (!($1 in sect_base)) {
|
||||
sect_base[$1] = base;
|
||||
|
||||
|
||||
@@ -181,7 +181,8 @@ struct ima_kexec_hdr {
|
||||
#define IMA_UPDATE_XATTR 1
|
||||
#define IMA_CHANGE_ATTR 2
|
||||
#define IMA_DIGSIG 3
|
||||
#define IMA_MUST_MEASURE 4
|
||||
#define IMA_MAY_EMIT_TOMTOU 4
|
||||
#define IMA_EMITTED_OPENWRITERS 5
|
||||
|
||||
/* IMA integrity metadata associated with an inode */
|
||||
struct ima_iint_cache {
|
||||
|
||||
@@ -129,16 +129,22 @@ static void ima_rdwr_violation_check(struct file *file,
|
||||
if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) {
|
||||
if (!iint)
|
||||
iint = ima_iint_find(inode);
|
||||
|
||||
/* IMA_MEASURE is set from reader side */
|
||||
if (iint && test_bit(IMA_MUST_MEASURE,
|
||||
&iint->atomic_flags))
|
||||
if (iint && test_and_clear_bit(IMA_MAY_EMIT_TOMTOU,
|
||||
&iint->atomic_flags))
|
||||
send_tomtou = true;
|
||||
}
|
||||
} else {
|
||||
if (must_measure)
|
||||
set_bit(IMA_MUST_MEASURE, &iint->atomic_flags);
|
||||
if (inode_is_open_for_write(inode) && must_measure)
|
||||
send_writers = true;
|
||||
set_bit(IMA_MAY_EMIT_TOMTOU, &iint->atomic_flags);
|
||||
|
||||
/* Limit number of open_writers violations */
|
||||
if (inode_is_open_for_write(inode) && must_measure) {
|
||||
if (!test_and_set_bit(IMA_EMITTED_OPENWRITERS,
|
||||
&iint->atomic_flags))
|
||||
send_writers = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!send_tomtou && !send_writers)
|
||||
@@ -167,6 +173,8 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
|
||||
if (atomic_read(&inode->i_writecount) == 1) {
|
||||
struct kstat stat;
|
||||
|
||||
clear_bit(IMA_EMITTED_OPENWRITERS, &iint->atomic_flags);
|
||||
|
||||
update = test_and_clear_bit(IMA_UPDATE_XATTR,
|
||||
&iint->atomic_flags);
|
||||
if ((iint->flags & IMA_NEW_FILE) ||
|
||||
|
||||
@@ -4744,6 +4744,22 @@ static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix,
|
||||
int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
spec->mute_led_polarity = 0;
|
||||
spec->mute_led_coef.idx = 0x0b;
|
||||
spec->mute_led_coef.mask = 1 << 3;
|
||||
spec->mute_led_coef.on = 1 << 3;
|
||||
spec->mute_led_coef.off = 0;
|
||||
snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
|
||||
}
|
||||
}
|
||||
|
||||
/* turn on/off mic-mute LED per capture hook by coef bit */
|
||||
static int coef_micmute_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
@@ -7851,6 +7867,7 @@ enum {
|
||||
ALC287_FIXUP_TAS2781_I2C,
|
||||
ALC287_FIXUP_YOGA7_14ARB7_I2C,
|
||||
ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
|
||||
ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT,
|
||||
ALC245_FIXUP_HP_X360_MUTE_LEDS,
|
||||
ALC287_FIXUP_THINKPAD_I2S_SPK,
|
||||
ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD,
|
||||
@@ -10084,6 +10101,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc245_fixup_hp_mute_led_coefbit,
|
||||
},
|
||||
[ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc245_fixup_hp_mute_led_v1_coefbit,
|
||||
},
|
||||
[ALC245_FIXUP_HP_X360_MUTE_LEDS] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc245_fixup_hp_mute_led_coefbit,
|
||||
@@ -10569,6 +10590,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bb3, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bb4, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bcd, "HP Omen 16-xd0xxx", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bdd, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bde, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bdf, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
||||
@@ -2564,6 +2564,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
|
||||
ARRAY_SIZE(wcd9375_dapm_widgets));
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev, "Failed to add snd_ctls\n");
|
||||
wcd_clsh_ctrl_free(wcd937x->clsh_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2571,6 +2572,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
|
||||
ARRAY_SIZE(wcd9375_audio_map));
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev, "Failed to add routes\n");
|
||||
wcd_clsh_ctrl_free(wcd937x->clsh_info);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#define PLAYBACK_MIN_PERIOD_SIZE 128
|
||||
#define CAPTURE_MIN_NUM_PERIODS 2
|
||||
#define CAPTURE_MAX_NUM_PERIODS 8
|
||||
#define CAPTURE_MAX_PERIOD_SIZE 4096
|
||||
#define CAPTURE_MIN_PERIOD_SIZE 320
|
||||
#define CAPTURE_MAX_PERIOD_SIZE 65536
|
||||
#define CAPTURE_MIN_PERIOD_SIZE 6144
|
||||
#define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE)
|
||||
#define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE)
|
||||
#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
|
||||
@@ -64,12 +64,12 @@ struct q6apm_dai_rtd {
|
||||
phys_addr_t phys;
|
||||
unsigned int pcm_size;
|
||||
unsigned int pcm_count;
|
||||
unsigned int pos; /* Buffer position */
|
||||
unsigned int periods;
|
||||
unsigned int bytes_sent;
|
||||
unsigned int bytes_received;
|
||||
unsigned int copied_total;
|
||||
uint16_t bits_per_sample;
|
||||
snd_pcm_uframes_t queue_ptr;
|
||||
bool next_track;
|
||||
enum stream_state state;
|
||||
struct q6apm_graph *graph;
|
||||
@@ -123,25 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *
|
||||
{
|
||||
struct q6apm_dai_rtd *prtd = priv;
|
||||
struct snd_pcm_substream *substream = prtd->substream;
|
||||
unsigned long flags;
|
||||
|
||||
switch (opcode) {
|
||||
case APM_CLIENT_EVENT_CMD_EOS_DONE:
|
||||
prtd->state = Q6APM_STREAM_STOPPED;
|
||||
break;
|
||||
case APM_CLIENT_EVENT_DATA_WRITE_DONE:
|
||||
spin_lock_irqsave(&prtd->lock, flags);
|
||||
prtd->pos += prtd->pcm_count;
|
||||
spin_unlock_irqrestore(&prtd->lock, flags);
|
||||
snd_pcm_period_elapsed(substream);
|
||||
if (prtd->state == Q6APM_STREAM_RUNNING)
|
||||
q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
|
||||
|
||||
break;
|
||||
case APM_CLIENT_EVENT_DATA_READ_DONE:
|
||||
spin_lock_irqsave(&prtd->lock, flags);
|
||||
prtd->pos += prtd->pcm_count;
|
||||
spin_unlock_irqrestore(&prtd->lock, flags);
|
||||
snd_pcm_period_elapsed(substream);
|
||||
if (prtd->state == Q6APM_STREAM_RUNNING)
|
||||
q6apm_read(prtd->graph);
|
||||
@@ -248,7 +239,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
|
||||
}
|
||||
|
||||
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
|
||||
prtd->pos = 0;
|
||||
/* rate and channels are sent to audio driver */
|
||||
ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
|
||||
if (ret < 0) {
|
||||
@@ -294,6 +284,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
||||
int i, ret = 0, avail_periods;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
|
||||
for (i = 0; i < avail_periods; i++) {
|
||||
ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP);
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
prtd->queue_ptr += runtime->period_size;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int q6apm_dai_trigger(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
@@ -305,9 +316,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
/* start writing buffers for playback only as we already queued capture buffers */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
/* TODO support be handled via SoftPause Module */
|
||||
@@ -377,13 +385,14 @@ static int q6apm_dai_open(struct snd_soc_component *component,
|
||||
}
|
||||
}
|
||||
|
||||
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
|
||||
/* setup 10ms latency to accommodate DSP restrictions */
|
||||
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "constraint for period bytes step ret = %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
|
||||
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret);
|
||||
goto err;
|
||||
@@ -428,16 +437,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
||||
snd_pcm_uframes_t ptr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&prtd->lock, flags);
|
||||
if (prtd->pos == prtd->pcm_size)
|
||||
prtd->pos = 0;
|
||||
ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size;
|
||||
if (ptr)
|
||||
return ptr - 1;
|
||||
|
||||
ptr = bytes_to_frames(runtime, prtd->pos);
|
||||
spin_unlock_irqrestore(&prtd->lock, flags);
|
||||
|
||||
return ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int q6apm_dai_hw_params(struct snd_soc_component *component,
|
||||
@@ -652,8 +657,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
|
||||
prtd->pcm_size = runtime->fragments * runtime->fragment_size;
|
||||
prtd->bits_per_sample = 16;
|
||||
|
||||
prtd->pos = 0;
|
||||
|
||||
if (prtd->next_track != true) {
|
||||
memcpy(&prtd->codec, codec, sizeof(*codec));
|
||||
|
||||
@@ -836,6 +839,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
|
||||
.hw_params = q6apm_dai_hw_params,
|
||||
.pointer = q6apm_dai_pointer,
|
||||
.trigger = q6apm_dai_trigger,
|
||||
.ack = q6apm_dai_ack,
|
||||
.compress_ops = &q6apm_dai_compress_ops,
|
||||
.use_dai_pcm_id = true,
|
||||
};
|
||||
|
||||
@@ -494,6 +494,19 @@ int q6apm_read(struct q6apm_graph *graph)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_read);
|
||||
|
||||
int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir)
|
||||
{
|
||||
struct audioreach_graph_data *data;
|
||||
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
data = &graph->rx_data;
|
||||
else
|
||||
data = &graph->tx_data;
|
||||
|
||||
return (int)atomic_read(&data->hw_ptr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer);
|
||||
|
||||
static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
|
||||
{
|
||||
struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
|
||||
@@ -520,7 +533,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
|
||||
done = data->payload;
|
||||
phys = graph->rx_data.buf[token].phys;
|
||||
mutex_unlock(&graph->lock);
|
||||
|
||||
/* token numbering starts at 0 */
|
||||
atomic_set(&graph->rx_data.hw_ptr, token + 1);
|
||||
if (lower_32_bits(phys) == done->buf_addr_lsw &&
|
||||
upper_32_bits(phys) == done->buf_addr_msw) {
|
||||
graph->result.opcode = hdr->opcode;
|
||||
@@ -553,6 +567,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
|
||||
rd_done = data->payload;
|
||||
phys = graph->tx_data.buf[hdr->token].phys;
|
||||
mutex_unlock(&graph->lock);
|
||||
/* token numbering starts at 0 */
|
||||
atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1);
|
||||
|
||||
if (upper_32_bits(phys) == rd_done->buf_addr_msw &&
|
||||
lower_32_bits(phys) == rd_done->buf_addr_lsw) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifndef __Q6APM_H__
|
||||
#define __Q6APM_H__
|
||||
#include <linux/types.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -77,6 +78,7 @@ struct audioreach_graph_data {
|
||||
uint32_t num_periods;
|
||||
uint32_t dsp_buf;
|
||||
uint32_t mem_map_handle;
|
||||
atomic_t hw_ptr;
|
||||
};
|
||||
|
||||
struct audioreach_graph {
|
||||
@@ -150,4 +152,5 @@ int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph,
|
||||
int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
|
||||
int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
|
||||
int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id);
|
||||
int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir);
|
||||
#endif /* __APM_GRAPH_ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user